Skip to content

Commit fb087ea

Browse files
libinyangtiwai
authored andcommitted
ALSA: hda - hdmi eld control created based on pcm
eld control is created based on pcm now. When monitor is connected, eld control will be bound to pin automatically. Signed-off-by: Libin Yang <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent fe0d128 commit fb087ea

File tree

1 file changed

+48
-26
lines changed

1 file changed

+48
-26
lines changed

sound/pci/hda/patch_hdmi.c

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ struct hdmi_spec_per_pin {
8686
struct hdmi_eld sink_eld;
8787
struct mutex lock;
8888
struct delayed_work work;
89-
struct snd_kcontrol *eld_ctl;
9089
struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
9190
int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */
9291
int repoll_count;
@@ -136,6 +135,7 @@ struct hdmi_ops {
136135
struct hdmi_pcm {
137136
struct hda_pcm *pcm;
138137
struct snd_jack *jack;
138+
struct snd_kcontrol *eld_ctl;
139139
};
140140

141141
struct hdmi_spec {
@@ -471,17 +471,22 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
471471
struct hdmi_spec *spec = codec->spec;
472472
struct hdmi_spec_per_pin *per_pin;
473473
struct hdmi_eld *eld;
474-
int pin_idx;
474+
int pcm_idx;
475475

476476
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
477477

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+
}
480487
eld = &per_pin->sink_eld;
481-
482-
mutex_lock(&per_pin->lock);
483488
uinfo->count = eld->eld_valid ? eld->eld_size : 0;
484-
mutex_unlock(&per_pin->lock);
489+
mutex_unlock(&spec->pcm_lock);
485490

486491
return 0;
487492
}
@@ -493,16 +498,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
493498
struct hdmi_spec *spec = codec->spec;
494499
struct hdmi_spec_per_pin *per_pin;
495500
struct hdmi_eld *eld;
496-
int pin_idx;
501+
int pcm_idx;
497502

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+
}
500513
eld = &per_pin->sink_eld;
501514

502-
mutex_lock(&per_pin->lock);
503515
if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
504516
eld->eld_size > ELD_MAX_SIZE) {
505-
mutex_unlock(&per_pin->lock);
517+
mutex_unlock(&spec->pcm_lock);
506518
snd_BUG();
507519
return -EINVAL;
508520
}
@@ -512,7 +524,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
512524
if (eld->eld_valid)
513525
memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
514526
eld->eld_size);
515-
mutex_unlock(&per_pin->lock);
527+
mutex_unlock(&spec->pcm_lock);
516528

517529
return 0;
518530
}
@@ -525,7 +537,7 @@ static struct snd_kcontrol_new eld_bytes_ctl = {
525537
.get = hdmi_eld_ctl_get,
526538
};
527539

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,
529541
int device)
530542
{
531543
struct snd_kcontrol *kctl;
@@ -535,14 +547,17 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
535547
kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
536548
if (!kctl)
537549
return -ENOMEM;
538-
kctl->private_value = pin_idx;
550+
kctl->private_value = pcm_idx;
539551
kctl->id.device = device;
540552

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);
542557
if (err < 0)
543558
return err;
544559

545-
get_pin(spec, pin_idx)->eld_ctl = kctl;
560+
get_hdmi_pcm(spec, pcm_idx)->eld_ctl = kctl;
546561
return 0;
547562
}
548563

@@ -1841,7 +1856,10 @@ static void update_eld(struct hda_codec *codec,
18411856
struct hdmi_spec *spec = codec->spec;
18421857
bool old_eld_valid = pin_eld->eld_valid;
18431858
bool eld_changed;
1859+
int pcm_idx = -1;
18441860

1861+
/* for monitor disconnection, save pcm_idx firstly */
1862+
pcm_idx = per_pin->pcm_idx;
18451863
if (spec->dyn_pcm_assign) {
18461864
if (eld->eld_valid) {
18471865
hdmi_attach_hda_pcm(spec, per_pin);
@@ -1851,6 +1869,11 @@ static void update_eld(struct hda_codec *codec,
18511869
hdmi_detach_hda_pcm(spec, per_pin);
18521870
}
18531871
}
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;
18541877

18551878
if (eld->eld_valid)
18561879
snd_hdmi_show_eld(codec, &eld->info);
@@ -1884,11 +1907,11 @@ static void update_eld(struct hda_codec *codec,
18841907
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
18851908
}
18861909

1887-
if (eld_changed)
1910+
if (eld_changed && pcm_idx >= 0)
18881911
snd_ctl_notify(codec->card,
18891912
SNDRV_CTL_EVENT_MASK_VALUE |
18901913
SNDRV_CTL_EVENT_MASK_INFO,
1891-
&per_pin->eld_ctl->id);
1914+
&get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
18921915
}
18931916

18941917
/* update ELD and jack state via HD-audio verbs */
@@ -2629,17 +2652,16 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
26292652
if (err < 0)
26302653
return err;
26312654
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);
26362655

26372656
/* 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);
26412659
if (err < 0)
26422660
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);
26432665

26442666
hdmi_present_sense(per_pin, 0);
26452667
}

0 commit comments

Comments
 (0)