18
18
19
19
#include <linux/init.h>
20
20
#include <linux/delay.h>
21
+ #include <linux/pci.h>
21
22
#include <linux/slab.h>
22
23
#include <linux/module.h>
23
24
#include <linux/pm_runtime.h>
@@ -119,6 +120,7 @@ struct hdmi_pcm {
119
120
};
120
121
121
122
struct hdmi_spec {
123
+ struct hda_codec * codec ;
122
124
int num_cvts ;
123
125
struct snd_array cvts ; /* struct hdmi_spec_per_cvt */
124
126
hda_nid_t cvt_nids [4 ]; /* only for haswell fix */
@@ -163,9 +165,11 @@ struct hdmi_spec {
163
165
struct hda_multi_out multiout ;
164
166
struct hda_pcm_stream pcm_playback ;
165
167
166
- /* i915/powerwell (Haswell+/Valleyview+) specific */
167
- bool use_acomp_notifier ; /* use i915 eld_notify callback for hotplug */
168
+ bool use_jack_detect ; /* jack detection enabled */
169
+ bool use_acomp_notifier ; /* use eld_notify callback for hotplug */
170
+ bool acomp_registered ; /* audio component registered in this driver */
168
171
struct drm_audio_component_audio_ops drm_audio_ops ;
172
+ int (* port2pin )(struct hda_codec * , int ); /* reverse port/pin mapping */
169
173
170
174
struct hdac_chmap chmap ;
171
175
hda_nid_t vendor_nid ;
@@ -765,6 +769,10 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid,
765
769
static void jack_callback (struct hda_codec * codec ,
766
770
struct hda_jack_callback * jack )
767
771
{
772
+ /* stop polling when notification is enabled */
773
+ if (codec_has_acomp (codec ))
774
+ return ;
775
+
768
776
/* hda_jack don't support DP MST */
769
777
check_presence_and_report (codec , jack -> nid , 0 );
770
778
}
@@ -823,6 +831,9 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
823
831
int tag = res >> AC_UNSOL_RES_TAG_SHIFT ;
824
832
int subtag = (res & AC_UNSOL_RES_SUBTAG ) >> AC_UNSOL_RES_SUBTAG_SHIFT ;
825
833
834
+ if (codec_has_acomp (codec ))
835
+ return ;
836
+
826
837
if (!snd_hda_jack_tbl_get_from_tag (codec , tag )) {
827
838
codec_dbg (codec , "Unexpected HDMI event tag 0x%x\n" , tag );
828
839
return ;
@@ -1636,18 +1647,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
1636
1647
snd_hda_power_down_pm (codec );
1637
1648
return false;
1638
1649
}
1639
- }
1640
-
1641
- if ( codec_has_acomp ( codec )) {
1650
+ ret = hdmi_present_sense_via_verbs ( per_pin , repoll );
1651
+ snd_hda_power_down_pm ( codec );
1652
+ } else {
1642
1653
sync_eld_via_acomp (codec , per_pin );
1643
1654
ret = false; /* don't call snd_hda_jack_report_sync() */
1644
- } else {
1645
- ret = hdmi_present_sense_via_verbs (per_pin , repoll );
1646
1655
}
1647
1656
1648
- if (!codec_has_acomp (codec ))
1649
- snd_hda_power_down_pm (codec );
1650
-
1651
1657
return ret ;
1652
1658
}
1653
1659
@@ -2252,18 +2258,24 @@ static int generic_hdmi_init(struct hda_codec *codec)
2252
2258
struct hdmi_spec * spec = codec -> spec ;
2253
2259
int pin_idx ;
2254
2260
2261
+ mutex_lock (& spec -> pcm_lock );
2262
+ spec -> use_jack_detect = !codec -> jackpoll_interval ;
2255
2263
for (pin_idx = 0 ; pin_idx < spec -> num_pins ; pin_idx ++ ) {
2256
2264
struct hdmi_spec_per_pin * per_pin = get_pin (spec , pin_idx );
2257
2265
hda_nid_t pin_nid = per_pin -> pin_nid ;
2258
2266
int dev_id = per_pin -> dev_id ;
2259
2267
2260
2268
snd_hda_set_dev_select (codec , pin_nid , dev_id );
2261
2269
hdmi_init_pin (codec , pin_nid );
2262
- if (!codec_has_acomp (codec ))
2270
+ if (codec_has_acomp (codec ))
2271
+ continue ;
2272
+ if (spec -> use_jack_detect )
2273
+ snd_hda_jack_detect_enable (codec , pin_nid );
2274
+ else
2263
2275
snd_hda_jack_detect_enable_callback (codec , pin_nid ,
2264
- codec -> jackpoll_interval > 0 ?
2265
- jack_callback : NULL );
2276
+ jack_callback );
2266
2277
}
2278
+ mutex_unlock (& spec -> pcm_lock );
2267
2279
return 0 ;
2268
2280
}
2269
2281
@@ -2296,7 +2308,9 @@ static void generic_hdmi_free(struct hda_codec *codec)
2296
2308
struct hdmi_spec * spec = codec -> spec ;
2297
2309
int pin_idx , pcm_idx ;
2298
2310
2299
- if (codec_has_acomp (codec )) {
2311
+ if (spec -> acomp_registered ) {
2312
+ snd_hdac_acomp_exit (& codec -> bus -> core );
2313
+ } else if (codec_has_acomp (codec )) {
2300
2314
snd_hdac_acomp_register_notifier (& codec -> bus -> core , NULL );
2301
2315
codec -> relaxed_resume = 0 ;
2302
2316
}
@@ -2364,6 +2378,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec)
2364
2378
if (!spec )
2365
2379
return - ENOMEM ;
2366
2380
2381
+ spec -> codec = codec ;
2367
2382
spec -> ops = generic_standard_hdmi_ops ;
2368
2383
spec -> dev_num = 1 ; /* initialize to 1 */
2369
2384
mutex_init (& spec -> pcm_lock );
@@ -2401,6 +2416,136 @@ static int patch_generic_hdmi(struct hda_codec *codec)
2401
2416
return 0 ;
2402
2417
}
2403
2418
2419
+ /*
2420
+ * generic audio component binding
2421
+ */
2422
+
2423
+ /* turn on / off the unsol event jack detection dynamically */
2424
+ static void reprogram_jack_detect (struct hda_codec * codec , hda_nid_t nid ,
2425
+ bool use_acomp )
2426
+ {
2427
+ struct hda_jack_tbl * tbl ;
2428
+
2429
+ tbl = snd_hda_jack_tbl_get (codec , nid );
2430
+ if (tbl ) {
2431
+ /* clear unsol even if component notifier is used, or re-enable
2432
+ * if notifier is cleared
2433
+ */
2434
+ unsigned int val = use_acomp ? 0 : (AC_USRSP_EN | tbl -> tag );
2435
+ snd_hda_codec_write_cache (codec , nid , 0 ,
2436
+ AC_VERB_SET_UNSOLICITED_ENABLE , val );
2437
+ } else {
2438
+ /* if no jack entry was defined beforehand, create a new one
2439
+ * at need (i.e. only when notifier is cleared)
2440
+ */
2441
+ if (!use_acomp )
2442
+ snd_hda_jack_detect_enable (codec , nid );
2443
+ }
2444
+ }
2445
+
2446
+ /* set up / clear component notifier dynamically */
2447
+ static void generic_acomp_notifier_set (struct drm_audio_component * acomp ,
2448
+ bool use_acomp )
2449
+ {
2450
+ struct hdmi_spec * spec ;
2451
+ int i ;
2452
+
2453
+ spec = container_of (acomp -> audio_ops , struct hdmi_spec , drm_audio_ops );
2454
+ mutex_lock (& spec -> pcm_lock );
2455
+ spec -> use_acomp_notifier = use_acomp ;
2456
+ spec -> codec -> relaxed_resume = use_acomp ;
2457
+ /* reprogram each jack detection logic depending on the notifier */
2458
+ if (spec -> use_jack_detect ) {
2459
+ for (i = 0 ; i < spec -> num_pins ; i ++ )
2460
+ reprogram_jack_detect (spec -> codec ,
2461
+ get_pin (spec , i )-> pin_nid ,
2462
+ use_acomp );
2463
+ }
2464
+ mutex_unlock (& spec -> pcm_lock );
2465
+ }
2466
+
2467
+ /* enable / disable the notifier via master bind / unbind */
2468
+ static int generic_acomp_master_bind (struct device * dev ,
2469
+ struct drm_audio_component * acomp )
2470
+ {
2471
+ generic_acomp_notifier_set (acomp , true);
2472
+ return 0 ;
2473
+ }
2474
+
2475
+ static void generic_acomp_master_unbind (struct device * dev ,
2476
+ struct drm_audio_component * acomp )
2477
+ {
2478
+ generic_acomp_notifier_set (acomp , false);
2479
+ }
2480
+
2481
+ /* check whether both HD-audio and DRM PCI devices belong to the same bus */
2482
+ static int match_bound_vga (struct device * dev , int subtype , void * data )
2483
+ {
2484
+ struct hdac_bus * bus = data ;
2485
+ struct pci_dev * pci , * master ;
2486
+
2487
+ if (!dev_is_pci (dev ) || !dev_is_pci (bus -> dev ))
2488
+ return 0 ;
2489
+ master = to_pci_dev (bus -> dev );
2490
+ pci = to_pci_dev (dev );
2491
+ return master -> bus == pci -> bus ;
2492
+ }
2493
+
2494
+ /* audio component notifier for AMD/Nvidia HDMI codecs */
2495
+ static void generic_acomp_pin_eld_notify (void * audio_ptr , int port , int dev_id )
2496
+ {
2497
+ struct hda_codec * codec = audio_ptr ;
2498
+ struct hdmi_spec * spec = codec -> spec ;
2499
+ hda_nid_t pin_nid = spec -> port2pin (codec , port );
2500
+
2501
+ if (!pin_nid )
2502
+ return ;
2503
+ if (get_wcaps_type (get_wcaps (codec , pin_nid )) != AC_WID_PIN )
2504
+ return ;
2505
+ /* skip notification during system suspend (but not in runtime PM);
2506
+ * the state will be updated at resume
2507
+ */
2508
+ if (snd_power_get_state (codec -> card ) != SNDRV_CTL_POWER_D0 )
2509
+ return ;
2510
+ /* ditto during suspend/resume process itself */
2511
+ if (snd_hdac_is_in_pm (& codec -> core ))
2512
+ return ;
2513
+
2514
+ check_presence_and_report (codec , pin_nid , dev_id );
2515
+ }
2516
+
2517
+ /* set up the private drm_audio_ops from the template */
2518
+ static void setup_drm_audio_ops (struct hda_codec * codec ,
2519
+ const struct drm_audio_component_audio_ops * ops )
2520
+ {
2521
+ struct hdmi_spec * spec = codec -> spec ;
2522
+
2523
+ spec -> drm_audio_ops .audio_ptr = codec ;
2524
+ /* intel_audio_codec_enable() or intel_audio_codec_disable()
2525
+ * will call pin_eld_notify with using audio_ptr pointer
2526
+ * We need make sure audio_ptr is really setup
2527
+ */
2528
+ wmb ();
2529
+ spec -> drm_audio_ops .pin2port = ops -> pin2port ;
2530
+ spec -> drm_audio_ops .pin_eld_notify = ops -> pin_eld_notify ;
2531
+ spec -> drm_audio_ops .master_bind = ops -> master_bind ;
2532
+ spec -> drm_audio_ops .master_unbind = ops -> master_unbind ;
2533
+ }
2534
+
2535
+ /* initialize the generic HDMI audio component */
2536
+ static void generic_acomp_init (struct hda_codec * codec ,
2537
+ const struct drm_audio_component_audio_ops * ops ,
2538
+ int (* port2pin )(struct hda_codec * , int ))
2539
+ {
2540
+ struct hdmi_spec * spec = codec -> spec ;
2541
+
2542
+ spec -> port2pin = port2pin ;
2543
+ setup_drm_audio_ops (codec , ops );
2544
+ if (!snd_hdac_acomp_init (& codec -> bus -> core , & spec -> drm_audio_ops ,
2545
+ match_bound_vga , 0 ))
2546
+ spec -> acomp_registered = true;
2547
+ }
2548
+
2404
2549
/*
2405
2550
* Intel codec parsers and helpers
2406
2551
*/
@@ -2569,20 +2714,19 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
2569
2714
check_presence_and_report (codec , pin_nid , dev_id );
2570
2715
}
2571
2716
2717
+ static const struct drm_audio_component_audio_ops intel_audio_ops = {
2718
+ .pin2port = intel_pin2port ,
2719
+ .pin_eld_notify = intel_pin_eld_notify ,
2720
+ };
2721
+
2572
2722
/* register i915 component pin_eld_notify callback */
2573
2723
static void register_i915_notifier (struct hda_codec * codec )
2574
2724
{
2575
2725
struct hdmi_spec * spec = codec -> spec ;
2576
2726
2577
2727
spec -> use_acomp_notifier = true;
2578
- spec -> drm_audio_ops .audio_ptr = codec ;
2579
- /* intel_audio_codec_enable() or intel_audio_codec_disable()
2580
- * will call pin_eld_notify with using audio_ptr pointer
2581
- * We need make sure audio_ptr is really setup
2582
- */
2583
- wmb ();
2584
- spec -> drm_audio_ops .pin2port = intel_pin2port ;
2585
- spec -> drm_audio_ops .pin_eld_notify = intel_pin_eld_notify ;
2728
+ spec -> port2pin = intel_port2pin ;
2729
+ setup_drm_audio_ops (codec , & intel_audio_ops );
2586
2730
snd_hdac_acomp_register_notifier (& codec -> bus -> core ,
2587
2731
& spec -> drm_audio_ops );
2588
2732
/* no need for forcible resume for jack check thanks to notifier */
@@ -2980,6 +3124,7 @@ static int patch_simple_hdmi(struct hda_codec *codec,
2980
3124
if (!spec )
2981
3125
return - ENOMEM ;
2982
3126
3127
+ spec -> codec = codec ;
2983
3128
codec -> spec = spec ;
2984
3129
hdmi_array_init (spec , 1 );
2985
3130
@@ -3284,6 +3429,26 @@ static int nvhdmi_chmap_validate(struct hdac_chmap *chmap,
3284
3429
return 0 ;
3285
3430
}
3286
3431
3432
+ /* map from pin NID to port; port is 0-based */
3433
+ /* for Nvidia: assume widget NID starting from 4, with step 1 (4, 5, 6, ...) */
3434
+ static int nvhdmi_pin2port (void * audio_ptr , int pin_nid )
3435
+ {
3436
+ return pin_nid - 4 ;
3437
+ }
3438
+
3439
+ /* reverse-map from port to pin NID: see above */
3440
+ static int nvhdmi_port2pin (struct hda_codec * codec , int port )
3441
+ {
3442
+ return port + 4 ;
3443
+ }
3444
+
3445
+ static const struct drm_audio_component_audio_ops nvhdmi_audio_ops = {
3446
+ .pin2port = nvhdmi_pin2port ,
3447
+ .pin_eld_notify = generic_acomp_pin_eld_notify ,
3448
+ .master_bind = generic_acomp_master_bind ,
3449
+ .master_unbind = generic_acomp_master_unbind ,
3450
+ };
3451
+
3287
3452
static int patch_nvhdmi (struct hda_codec * codec )
3288
3453
{
3289
3454
struct hdmi_spec * spec ;
@@ -3300,6 +3465,8 @@ static int patch_nvhdmi(struct hda_codec *codec)
3300
3465
nvhdmi_chmap_cea_alloc_validate_get_type ;
3301
3466
spec -> chmap .ops .chmap_validate = nvhdmi_chmap_validate ;
3302
3467
3468
+ generic_acomp_init (codec , & nvhdmi_audio_ops , nvhdmi_port2pin );
3469
+
3303
3470
return 0 ;
3304
3471
}
3305
3472
@@ -3787,6 +3954,26 @@ static int atihdmi_init(struct hda_codec *codec)
3787
3954
return 0 ;
3788
3955
}
3789
3956
3957
+ /* map from pin NID to port; port is 0-based */
3958
+ /* for AMD: assume widget NID starting from 3, with step 2 (3, 5, 7, ...) */
3959
+ static int atihdmi_pin2port (void * audio_ptr , int pin_nid )
3960
+ {
3961
+ return pin_nid / 2 - 1 ;
3962
+ }
3963
+
3964
+ /* reverse-map from port to pin NID: see above */
3965
+ static int atihdmi_port2pin (struct hda_codec * codec , int port )
3966
+ {
3967
+ return port * 2 + 3 ;
3968
+ }
3969
+
3970
+ static const struct drm_audio_component_audio_ops atihdmi_audio_ops = {
3971
+ .pin2port = atihdmi_pin2port ,
3972
+ .pin_eld_notify = generic_acomp_pin_eld_notify ,
3973
+ .master_bind = generic_acomp_master_bind ,
3974
+ .master_unbind = generic_acomp_master_unbind ,
3975
+ };
3976
+
3790
3977
static int patch_atihdmi (struct hda_codec * codec )
3791
3978
{
3792
3979
struct hdmi_spec * spec ;
@@ -3835,6 +4022,8 @@ static int patch_atihdmi(struct hda_codec *codec)
3835
4022
*/
3836
4023
codec -> link_down_at_suspend = 1 ;
3837
4024
4025
+ generic_acomp_init (codec , & atihdmi_audio_ops , atihdmi_port2pin );
4026
+
3838
4027
return 0 ;
3839
4028
}
3840
4029
0 commit comments