[alsa-devel] [RFC PATCH] ALSA: hda - hdmi eld control created based on pcm
From: Libin Yang libin.yang@linux.intel.com
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 libin.yang@linux.intel.com --- sound/pci/hda/patch_hdmi.c | 74 ++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 26 deletions(-)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 541986f..d77509a 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -86,7 +86,6 @@ struct hdmi_spec_per_pin { struct hdmi_eld sink_eld; struct mutex lock; struct delayed_work work; - struct snd_kcontrol *eld_ctl; struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ int repoll_count; @@ -136,6 +135,7 @@ struct hdmi_ops { struct hdmi_pcm { struct hda_pcm *pcm; struct snd_jack *jack; + struct snd_kcontrol *eld_ctl; };
struct hdmi_spec { @@ -471,17 +471,22 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; - int pin_idx; + int pcm_idx;
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- pin_idx = kcontrol->private_value; - per_pin = get_pin(spec, pin_idx); + pcm_idx = kcontrol->private_value; + mutex_lock(&spec->pcm_lock); + per_pin = pcm_idx_to_pin(spec, pcm_idx); + if (!per_pin) { + /* no pin is bound to the pcm */ + uinfo->count = 0; + mutex_unlock(&spec->pcm_lock); + return 0; + } eld = &per_pin->sink_eld; - - mutex_lock(&per_pin->lock); uinfo->count = eld->eld_valid ? eld->eld_size : 0; - mutex_unlock(&per_pin->lock); + mutex_unlock(&spec->pcm_lock);
return 0; } @@ -493,16 +498,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; - int pin_idx; + int pcm_idx;
- pin_idx = kcontrol->private_value; - per_pin = get_pin(spec, pin_idx); + pcm_idx = kcontrol->private_value; + mutex_lock(&spec->pcm_lock); + per_pin = pcm_idx_to_pin(spec, pcm_idx); + if (!per_pin) { + /* no pin is bound to the pcm */ + memset(ucontrol->value.bytes.data, 0, + ARRAY_SIZE(ucontrol->value.bytes.data)); + mutex_unlock(&spec->pcm_lock); + return 0; + } eld = &per_pin->sink_eld;
- mutex_lock(&per_pin->lock); if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || eld->eld_size > ELD_MAX_SIZE) { - mutex_unlock(&per_pin->lock); + mutex_unlock(&spec->pcm_lock); snd_BUG(); return -EINVAL; } @@ -512,7 +524,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, if (eld->eld_valid) memcpy(ucontrol->value.bytes.data, eld->eld_buffer, eld->eld_size); - mutex_unlock(&per_pin->lock); + mutex_unlock(&spec->pcm_lock);
return 0; } @@ -525,7 +537,7 @@ static struct snd_kcontrol_new eld_bytes_ctl = { .get = hdmi_eld_ctl_get, };
-static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, +static int hdmi_create_eld_ctl(struct hda_codec *codec, int pcm_idx, int device) { struct snd_kcontrol *kctl; @@ -535,14 +547,17 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, kctl = snd_ctl_new1(&eld_bytes_ctl, codec); if (!kctl) return -ENOMEM; - kctl->private_value = pin_idx; + kctl->private_value = pcm_idx; kctl->id.device = device;
- err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl); + /* no pin nid is associated with the kctl now + * tbd: associate pin nid to eld ctl later + */ + err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err;
- get_pin(spec, pin_idx)->eld_ctl = kctl; + get_hdmi_pcm(spec, pcm_idx)->eld_ctl = kctl; return 0; }
@@ -1841,7 +1856,10 @@ static void update_eld(struct hda_codec *codec, struct hdmi_spec *spec = codec->spec; bool old_eld_valid = pin_eld->eld_valid; bool eld_changed; + int pcm_idx = -1;
+ /* for monitor disconnection, save pcm_idx firstly */ + pcm_idx = per_pin->pcm_idx; if (spec->dyn_pcm_assign) { if (eld->eld_valid) { hdmi_attach_hda_pcm(spec, per_pin); @@ -1851,6 +1869,11 @@ static void update_eld(struct hda_codec *codec, hdmi_detach_hda_pcm(spec, per_pin); } } + /* if pcm_idx == -1, it means this is in monitor connection event + * we can get the correct pcm_idx now. + */ + if (pcm_idx == -1) + pcm_idx = per_pin->pcm_idx;
if (eld->eld_valid) snd_hdmi_show_eld(codec, &eld->info); @@ -1884,11 +1907,11 @@ static void update_eld(struct hda_codec *codec, hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); }
- if (eld_changed) + if (eld_changed && pcm_idx >= 0) snd_ctl_notify(codec->card, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, - &per_pin->eld_ctl->id); + &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id); }
/* update ELD and jack state via HD-audio verbs */ @@ -2629,17 +2652,16 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) if (err < 0) return err; snd_hda_spdif_ctls_unassign(codec, pcm_idx); - } - - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
/* add control for ELD Bytes */ - err = hdmi_create_eld_ctl(codec, pin_idx, - get_pcm_rec(spec, pin_idx)->device); - + err = hdmi_create_eld_ctl(codec, pcm_idx, + get_pcm_rec(spec, pcm_idx)->device); if (err < 0) return err; + } + + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
hdmi_present_sense(per_pin, 0); }
On Tue, 23 Feb 2016 09:33:37 +0100, libin.yang@linux.intel.com wrote:
From: Libin Yang libin.yang@linux.intel.com
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 libin.yang@linux.intel.com
Looks good to me -- as long as you tested :) Let me know if you'd like to merge it as is.
thanks,
Takashi
sound/pci/hda/patch_hdmi.c | 74 ++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 26 deletions(-)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 541986f..d77509a 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -86,7 +86,6 @@ struct hdmi_spec_per_pin { struct hdmi_eld sink_eld; struct mutex lock; struct delayed_work work;
- struct snd_kcontrol *eld_ctl; struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ int repoll_count;
@@ -136,6 +135,7 @@ struct hdmi_ops { struct hdmi_pcm { struct hda_pcm *pcm; struct snd_jack *jack;
- struct snd_kcontrol *eld_ctl;
};
struct hdmi_spec { @@ -471,17 +471,22 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld;
- int pin_idx;
int pcm_idx;
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- pin_idx = kcontrol->private_value;
- per_pin = get_pin(spec, pin_idx);
- pcm_idx = kcontrol->private_value;
- mutex_lock(&spec->pcm_lock);
- per_pin = pcm_idx_to_pin(spec, pcm_idx);
- if (!per_pin) {
/* no pin is bound to the pcm */
uinfo->count = 0;
mutex_unlock(&spec->pcm_lock);
return 0;
- } eld = &per_pin->sink_eld;
- mutex_lock(&per_pin->lock); uinfo->count = eld->eld_valid ? eld->eld_size : 0;
- mutex_unlock(&per_pin->lock);
mutex_unlock(&spec->pcm_lock);
return 0;
} @@ -493,16 +498,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld;
- int pin_idx;
- int pcm_idx;
- pin_idx = kcontrol->private_value;
- per_pin = get_pin(spec, pin_idx);
- pcm_idx = kcontrol->private_value;
- mutex_lock(&spec->pcm_lock);
- per_pin = pcm_idx_to_pin(spec, pcm_idx);
- if (!per_pin) {
/* no pin is bound to the pcm */
memset(ucontrol->value.bytes.data, 0,
ARRAY_SIZE(ucontrol->value.bytes.data));
mutex_unlock(&spec->pcm_lock);
return 0;
- } eld = &per_pin->sink_eld;
- mutex_lock(&per_pin->lock); if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || eld->eld_size > ELD_MAX_SIZE) {
mutex_unlock(&per_pin->lock);
snd_BUG(); return -EINVAL; }mutex_unlock(&spec->pcm_lock);
@@ -512,7 +524,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, if (eld->eld_valid) memcpy(ucontrol->value.bytes.data, eld->eld_buffer, eld->eld_size);
- mutex_unlock(&per_pin->lock);
mutex_unlock(&spec->pcm_lock);
return 0;
} @@ -525,7 +537,7 @@ static struct snd_kcontrol_new eld_bytes_ctl = { .get = hdmi_eld_ctl_get, };
-static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, +static int hdmi_create_eld_ctl(struct hda_codec *codec, int pcm_idx, int device) { struct snd_kcontrol *kctl; @@ -535,14 +547,17 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, kctl = snd_ctl_new1(&eld_bytes_ctl, codec); if (!kctl) return -ENOMEM;
- kctl->private_value = pin_idx;
- kctl->private_value = pcm_idx; kctl->id.device = device;
- err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl);
- /* no pin nid is associated with the kctl now
* tbd: associate pin nid to eld ctl later
*/
- err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err;
- get_pin(spec, pin_idx)->eld_ctl = kctl;
- get_hdmi_pcm(spec, pcm_idx)->eld_ctl = kctl; return 0;
}
@@ -1841,7 +1856,10 @@ static void update_eld(struct hda_codec *codec, struct hdmi_spec *spec = codec->spec; bool old_eld_valid = pin_eld->eld_valid; bool eld_changed;
int pcm_idx = -1;
/* for monitor disconnection, save pcm_idx firstly */
pcm_idx = per_pin->pcm_idx; if (spec->dyn_pcm_assign) { if (eld->eld_valid) { hdmi_attach_hda_pcm(spec, per_pin);
@@ -1851,6 +1869,11 @@ static void update_eld(struct hda_codec *codec, hdmi_detach_hda_pcm(spec, per_pin); } }
/* if pcm_idx == -1, it means this is in monitor connection event
* we can get the correct pcm_idx now.
*/
if (pcm_idx == -1)
pcm_idx = per_pin->pcm_idx;
if (eld->eld_valid) snd_hdmi_show_eld(codec, &eld->info);
@@ -1884,11 +1907,11 @@ static void update_eld(struct hda_codec *codec, hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); }
- if (eld_changed)
- if (eld_changed && pcm_idx >= 0) snd_ctl_notify(codec->card, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&per_pin->eld_ctl->id);
&get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
}
/* update ELD and jack state via HD-audio verbs */ @@ -2629,17 +2652,16 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) if (err < 0) return err; snd_hda_spdif_ctls_unassign(codec, pcm_idx);
}
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
/* add control for ELD Bytes */
err = hdmi_create_eld_ctl(codec, pin_idx,
get_pcm_rec(spec, pin_idx)->device);
err = hdmi_create_eld_ctl(codec, pcm_idx,
get_pcm_rec(spec, pcm_idx)->device);
if (err < 0) return err;
}
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
hdmi_present_sense(per_pin, 0); }
-- 1.9.1
Hi Takashi,
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de] Sent: Tuesday, February 23, 2016 9:59 PM To: libin.yang@linux.intel.com Cc: alsa-devel@alsa-project.org; Lin, Mengdong; Yang, Libin Subject: Re: [alsa-devel] [RFC PATCH] ALSA: hda - hdmi eld control created based on pcm
On Tue, 23 Feb 2016 09:33:37 +0100, libin.yang@linux.intel.com wrote:
From: Libin Yang libin.yang@linux.intel.com
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 libin.yang@linux.intel.com
Looks good to me -- as long as you tested :) Let me know if you'd like to merge it as is.
The patch is tested with my basic test case. It's great if the patch can be merged :)
Regards, Libin
thanks,
Takashi
sound/pci/hda/patch_hdmi.c | 74
++++++++++++++++++++++++++++++----------------
1 file changed, 48 insertions(+), 26 deletions(-)
diff --git a/sound/pci/hda/patch_hdmi.c
b/sound/pci/hda/patch_hdmi.c
index 541986f..d77509a 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -86,7 +86,6 @@ struct hdmi_spec_per_pin { struct hdmi_eld sink_eld; struct mutex lock; struct delayed_work work;
- struct snd_kcontrol *eld_ctl; struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n]
dynamically*/
int pcm_idx; /* which pcm is attached. -1 means no pcm is
attached */
int repoll_count; @@ -136,6 +135,7 @@ struct hdmi_ops { struct hdmi_pcm { struct hda_pcm *pcm; struct snd_jack *jack;
- struct snd_kcontrol *eld_ctl;
};
struct hdmi_spec { @@ -471,17 +471,22 @@ static int hdmi_eld_ctl_info(struct
snd_kcontrol *kcontrol,
struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld;
- int pin_idx;
int pcm_idx;
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- pin_idx = kcontrol->private_value;
- per_pin = get_pin(spec, pin_idx);
- pcm_idx = kcontrol->private_value;
- mutex_lock(&spec->pcm_lock);
- per_pin = pcm_idx_to_pin(spec, pcm_idx);
- if (!per_pin) {
/* no pin is bound to the pcm */
uinfo->count = 0;
mutex_unlock(&spec->pcm_lock);
return 0;
- } eld = &per_pin->sink_eld;
- mutex_lock(&per_pin->lock); uinfo->count = eld->eld_valid ? eld->eld_size : 0;
- mutex_unlock(&per_pin->lock);
mutex_unlock(&spec->pcm_lock);
return 0;
} @@ -493,16 +498,23 @@ static int hdmi_eld_ctl_get(struct
snd_kcontrol *kcontrol,
struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld;
- int pin_idx;
- int pcm_idx;
- pin_idx = kcontrol->private_value;
- per_pin = get_pin(spec, pin_idx);
- pcm_idx = kcontrol->private_value;
- mutex_lock(&spec->pcm_lock);
- per_pin = pcm_idx_to_pin(spec, pcm_idx);
- if (!per_pin) {
/* no pin is bound to the pcm */
memset(ucontrol->value.bytes.data, 0,
ARRAY_SIZE(ucontrol->value.bytes.data));
mutex_unlock(&spec->pcm_lock);
return 0;
- } eld = &per_pin->sink_eld;
- mutex_lock(&per_pin->lock); if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || eld->eld_size > ELD_MAX_SIZE) {
mutex_unlock(&per_pin->lock);
snd_BUG(); return -EINVAL; }mutex_unlock(&spec->pcm_lock);
@@ -512,7 +524,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol
*kcontrol,
if (eld->eld_valid) memcpy(ucontrol->value.bytes.data, eld->eld_buffer, eld->eld_size);
- mutex_unlock(&per_pin->lock);
mutex_unlock(&spec->pcm_lock);
return 0;
} @@ -525,7 +537,7 @@ static struct snd_kcontrol_new eld_bytes_ctl =
{
.get = hdmi_eld_ctl_get, };
-static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, +static int hdmi_create_eld_ctl(struct hda_codec *codec, int pcm_idx, int device) { struct snd_kcontrol *kctl; @@ -535,14 +547,17 @@ static int hdmi_create_eld_ctl(struct
hda_codec *codec, int pin_idx,
kctl = snd_ctl_new1(&eld_bytes_ctl, codec); if (!kctl) return -ENOMEM;
- kctl->private_value = pin_idx;
- kctl->private_value = pcm_idx; kctl->id.device = device;
- err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid,
kctl);
- /* no pin nid is associated with the kctl now
* tbd: associate pin nid to eld ctl later
*/
- err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err;
- get_pin(spec, pin_idx)->eld_ctl = kctl;
- get_hdmi_pcm(spec, pcm_idx)->eld_ctl = kctl; return 0;
}
@@ -1841,7 +1856,10 @@ static void update_eld(struct hda_codec
*codec,
struct hdmi_spec *spec = codec->spec; bool old_eld_valid = pin_eld->eld_valid; bool eld_changed;
int pcm_idx = -1;
/* for monitor disconnection, save pcm_idx firstly */
pcm_idx = per_pin->pcm_idx; if (spec->dyn_pcm_assign) { if (eld->eld_valid) { hdmi_attach_hda_pcm(spec, per_pin);
@@ -1851,6 +1869,11 @@ static void update_eld(struct hda_codec
*codec,
hdmi_detach_hda_pcm(spec, per_pin); }
}
/* if pcm_idx == -1, it means this is in monitor connection event
* we can get the correct pcm_idx now.
*/
if (pcm_idx == -1)
pcm_idx = per_pin->pcm_idx;
if (eld->eld_valid) snd_hdmi_show_eld(codec, &eld->info);
@@ -1884,11 +1907,11 @@ static void update_eld(struct hda_codec
*codec,
hdmi_setup_audio_infoframe(codec, per_pin, per_pin-
non_pcm); }
- if (eld_changed)
- if (eld_changed && pcm_idx >= 0) snd_ctl_notify(codec->card, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&per_pin->eld_ctl->id);
&get_hdmi_pcm(spec, pcm_idx)->eld_ctl-
id); }
/* update ELD and jack state via HD-audio verbs */ @@ -2629,17 +2652,16 @@ static int
generic_hdmi_build_controls(struct hda_codec *codec)
if (err < 0) return err; snd_hda_spdif_ctls_unassign(codec, pcm_idx);
- }
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = get_pin(spec,
pin_idx);
/* add control for ELD Bytes */
err = hdmi_create_eld_ctl(codec, pin_idx,
get_pcm_rec(spec, pin_idx)->device);
err = hdmi_create_eld_ctl(codec, pcm_idx,
get_pcm_rec(spec, pcm_idx)-
device); if (err < 0) return err;
- }
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = get_pin(spec,
pin_idx);
hdmi_present_sense(per_pin, 0);
}
1.9.1
On Tue, 23 Feb 2016 15:25:44 +0100, Yang, Libin wrote:
Hi Takashi,
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de] Sent: Tuesday, February 23, 2016 9:59 PM To: libin.yang@linux.intel.com Cc: alsa-devel@alsa-project.org; Lin, Mengdong; Yang, Libin Subject: Re: [alsa-devel] [RFC PATCH] ALSA: hda - hdmi eld control created based on pcm
On Tue, 23 Feb 2016 09:33:37 +0100, libin.yang@linux.intel.com wrote:
From: Libin Yang libin.yang@linux.intel.com
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 libin.yang@linux.intel.com
Looks good to me -- as long as you tested :) Let me know if you'd like to merge it as is.
The patch is tested with my basic test case. It's great if the patch can be merged :)
OK, applied now.
thanks,
Takashi
participants (3)
-
libin.yang@linux.intel.com
-
Takashi Iwai
-
Yang, Libin