@@ -86,7 +86,6 @@ struct hdmi_spec_per_pin {
86
86
struct hdmi_eld sink_eld ;
87
87
struct mutex lock ;
88
88
struct delayed_work work ;
89
- struct snd_kcontrol * eld_ctl ;
90
89
struct hdmi_pcm * pcm ; /* pointer to spec->pcm_rec[n] dynamically*/
91
90
int pcm_idx ; /* which pcm is attached. -1 means no pcm is attached */
92
91
int repoll_count ;
@@ -136,6 +135,7 @@ struct hdmi_ops {
136
135
struct hdmi_pcm {
137
136
struct hda_pcm * pcm ;
138
137
struct snd_jack * jack ;
138
+ struct snd_kcontrol * eld_ctl ;
139
139
};
140
140
141
141
struct hdmi_spec {
@@ -471,17 +471,22 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
471
471
struct hdmi_spec * spec = codec -> spec ;
472
472
struct hdmi_spec_per_pin * per_pin ;
473
473
struct hdmi_eld * eld ;
474
- int pin_idx ;
474
+ int pcm_idx ;
475
475
476
476
uinfo -> type = SNDRV_CTL_ELEM_TYPE_BYTES ;
477
477
478
- pin_idx = kcontrol -> private_value ;
479
- per_pin = get_pin (spec , pin_idx );
478
+ pcm_idx = kcontrol -> private_value ;
479
+ mutex_lock (& spec -> pcm_lock );
480
+ per_pin = pcm_idx_to_pin (spec , pcm_idx );
481
+ if (!per_pin ) {
482
+ /* no pin is bound to the pcm */
483
+ uinfo -> count = 0 ;
484
+ mutex_unlock (& spec -> pcm_lock );
485
+ return 0 ;
486
+ }
480
487
eld = & per_pin -> sink_eld ;
481
-
482
- mutex_lock (& per_pin -> lock );
483
488
uinfo -> count = eld -> eld_valid ? eld -> eld_size : 0 ;
484
- mutex_unlock (& per_pin -> lock );
489
+ mutex_unlock (& spec -> pcm_lock );
485
490
486
491
return 0 ;
487
492
}
@@ -493,16 +498,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
493
498
struct hdmi_spec * spec = codec -> spec ;
494
499
struct hdmi_spec_per_pin * per_pin ;
495
500
struct hdmi_eld * eld ;
496
- int pin_idx ;
501
+ int pcm_idx ;
497
502
498
- pin_idx = kcontrol -> private_value ;
499
- per_pin = get_pin (spec , pin_idx );
503
+ pcm_idx = kcontrol -> private_value ;
504
+ mutex_lock (& spec -> pcm_lock );
505
+ per_pin = pcm_idx_to_pin (spec , pcm_idx );
506
+ if (!per_pin ) {
507
+ /* no pin is bound to the pcm */
508
+ memset (ucontrol -> value .bytes .data , 0 ,
509
+ ARRAY_SIZE (ucontrol -> value .bytes .data ));
510
+ mutex_unlock (& spec -> pcm_lock );
511
+ return 0 ;
512
+ }
500
513
eld = & per_pin -> sink_eld ;
501
514
502
- mutex_lock (& per_pin -> lock );
503
515
if (eld -> eld_size > ARRAY_SIZE (ucontrol -> value .bytes .data ) ||
504
516
eld -> eld_size > ELD_MAX_SIZE ) {
505
- mutex_unlock (& per_pin -> lock );
517
+ mutex_unlock (& spec -> pcm_lock );
506
518
snd_BUG ();
507
519
return - EINVAL ;
508
520
}
@@ -512,7 +524,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
512
524
if (eld -> eld_valid )
513
525
memcpy (ucontrol -> value .bytes .data , eld -> eld_buffer ,
514
526
eld -> eld_size );
515
- mutex_unlock (& per_pin -> lock );
527
+ mutex_unlock (& spec -> pcm_lock );
516
528
517
529
return 0 ;
518
530
}
@@ -525,7 +537,7 @@ static struct snd_kcontrol_new eld_bytes_ctl = {
525
537
.get = hdmi_eld_ctl_get ,
526
538
};
527
539
528
- static int hdmi_create_eld_ctl (struct hda_codec * codec , int pin_idx ,
540
+ static int hdmi_create_eld_ctl (struct hda_codec * codec , int pcm_idx ,
529
541
int device )
530
542
{
531
543
struct snd_kcontrol * kctl ;
@@ -535,14 +547,17 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
535
547
kctl = snd_ctl_new1 (& eld_bytes_ctl , codec );
536
548
if (!kctl )
537
549
return - ENOMEM ;
538
- kctl -> private_value = pin_idx ;
550
+ kctl -> private_value = pcm_idx ;
539
551
kctl -> id .device = device ;
540
552
541
- err = snd_hda_ctl_add (codec , get_pin (spec , pin_idx )-> pin_nid , kctl );
553
+ /* no pin nid is associated with the kctl now
554
+ * tbd: associate pin nid to eld ctl later
555
+ */
556
+ err = snd_hda_ctl_add (codec , 0 , kctl );
542
557
if (err < 0 )
543
558
return err ;
544
559
545
- get_pin (spec , pin_idx )-> eld_ctl = kctl ;
560
+ get_hdmi_pcm (spec , pcm_idx )-> eld_ctl = kctl ;
546
561
return 0 ;
547
562
}
548
563
@@ -1841,7 +1856,10 @@ static void update_eld(struct hda_codec *codec,
1841
1856
struct hdmi_spec * spec = codec -> spec ;
1842
1857
bool old_eld_valid = pin_eld -> eld_valid ;
1843
1858
bool eld_changed ;
1859
+ int pcm_idx = -1 ;
1844
1860
1861
+ /* for monitor disconnection, save pcm_idx firstly */
1862
+ pcm_idx = per_pin -> pcm_idx ;
1845
1863
if (spec -> dyn_pcm_assign ) {
1846
1864
if (eld -> eld_valid ) {
1847
1865
hdmi_attach_hda_pcm (spec , per_pin );
@@ -1851,6 +1869,11 @@ static void update_eld(struct hda_codec *codec,
1851
1869
hdmi_detach_hda_pcm (spec , per_pin );
1852
1870
}
1853
1871
}
1872
+ /* if pcm_idx == -1, it means this is in monitor connection event
1873
+ * we can get the correct pcm_idx now.
1874
+ */
1875
+ if (pcm_idx == -1 )
1876
+ pcm_idx = per_pin -> pcm_idx ;
1854
1877
1855
1878
if (eld -> eld_valid )
1856
1879
snd_hdmi_show_eld (codec , & eld -> info );
@@ -1884,11 +1907,11 @@ static void update_eld(struct hda_codec *codec,
1884
1907
hdmi_setup_audio_infoframe (codec , per_pin , per_pin -> non_pcm );
1885
1908
}
1886
1909
1887
- if (eld_changed )
1910
+ if (eld_changed && pcm_idx >= 0 )
1888
1911
snd_ctl_notify (codec -> card ,
1889
1912
SNDRV_CTL_EVENT_MASK_VALUE |
1890
1913
SNDRV_CTL_EVENT_MASK_INFO ,
1891
- & per_pin -> eld_ctl -> id );
1914
+ & get_hdmi_pcm ( spec , pcm_idx ) -> eld_ctl -> id );
1892
1915
}
1893
1916
1894
1917
/* update ELD and jack state via HD-audio verbs */
@@ -2629,17 +2652,16 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
2629
2652
if (err < 0 )
2630
2653
return err ;
2631
2654
snd_hda_spdif_ctls_unassign (codec , pcm_idx );
2632
- }
2633
-
2634
- for (pin_idx = 0 ; pin_idx < spec -> num_pins ; pin_idx ++ ) {
2635
- struct hdmi_spec_per_pin * per_pin = get_pin (spec , pin_idx );
2636
2655
2637
2656
/* add control for ELD Bytes */
2638
- err = hdmi_create_eld_ctl (codec , pin_idx ,
2639
- get_pcm_rec (spec , pin_idx )-> device );
2640
-
2657
+ err = hdmi_create_eld_ctl (codec , pcm_idx ,
2658
+ get_pcm_rec (spec , pcm_idx )-> device );
2641
2659
if (err < 0 )
2642
2660
return err ;
2661
+ }
2662
+
2663
+ for (pin_idx = 0 ; pin_idx < spec -> num_pins ; pin_idx ++ ) {
2664
+ struct hdmi_spec_per_pin * per_pin = get_pin (spec , pin_idx );
2643
2665
2644
2666
hdmi_present_sense (per_pin , 0 );
2645
2667
}
0 commit comments