[alsa-devel] [RFC PATCH] ALSA: hda - hdmi begin to support dynamic PCM assignment
Takashi Iwai
tiwai at suse.de
Fri Nov 13 10:21:07 CET 2015
On Fri, 13 Nov 2015 09:56:30 +0100,
libin.yang at linux.intel.com wrote:
>
> From: Libin Yang <libin.yang at linux.intel.com>
>
> Begin to support dynamic PCM assignment to pin in
> hdmi audio driver.
>
> This means PCM will not be statically bound with pin.
> When there is a monitor connected, the corresponding pin
> will try to find a proper PCM to bind. When the monitor
> is disconnected, the corresponding pin will unbind
> the PCM. This helps to reduce the PCM number when there
> are many pins (device entries in DP MST mode) and only
> a few of them work at the same time.
>
> This patch adds the pcm member in struct hdmi_spec_per_pin.
> When PCM is dynamically bound to the pin, the member pcm
> will pointer to the corresponding pcm_rec[] in hdmi_spec,
> which means the hda_pcm is bound to the pin.
>
> Signed-off-by: Libin Yang <libin.yang at linux.intel.com>
> ---
> sound/pci/hda/patch_hdmi.c | 26 +++++++++++++++++++++-----
> 1 file changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
> index f503a88..f3363b8 100644
> --- a/sound/pci/hda/patch_hdmi.c
> +++ b/sound/pci/hda/patch_hdmi.c
> @@ -82,6 +82,7 @@ struct hdmi_spec_per_pin {
> struct mutex lock;
> struct delayed_work work;
> struct snd_kcontrol *eld_ctl;
> + struct hda_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
> int repoll_count;
> bool setup; /* the stream has been set up by prepare callback */
> int channels; /* current number of channels */
> @@ -140,7 +141,8 @@ struct hdmi_spec {
> struct hdmi_ops ops;
>
> bool dyn_pin_out;
> -
> + bool dyn_pcm_assign;
> + struct mutex pcm_lock;
> /*
> * Non-generic VIA/NVIDIA specific
> */
> @@ -378,13 +380,26 @@ static int hinfo_to_pin_index(struct hda_codec *codec,
> struct hda_pcm_stream *hinfo)
> {
> struct hdmi_spec *spec = codec->spec;
> + struct hdmi_spec_per_pin *per_pin;
> int pin_idx;
>
> - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
> - if (get_pcm_rec(spec, pin_idx)->stream == hinfo)
> - return pin_idx;
> + if (!spec->dyn_pcm_assign) {
> + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
> + if (get_pcm_rec(spec, pin_idx)->stream == hinfo)
> + return pin_idx;
> + } else {
> + mutex_lock(&spec->pcm_lock);
> + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
> + per_pin = get_pin(spec, pin_idx);
> + if (per_pin->pcm && per_pin->pcm->stream == hinfo) {
> + mutex_unlock(&spec->pcm_lock);
> + return pin_idx;
> + }
> + }
> + mutex_unlock(&spec->pcm_lock);
You can assign per_pin->pcm statically at init time when
dyn_pcm_assign=false. Then the same code is used in the above.
The need of spec->pcm_lock isn't clear at this moment. I guess you're
trying to avoid the race of dynamic pin assignment and release. But
then the code above doesn't protect anything because you return the
pin_idx as an available value after the unlock. Then the pin release
can happen after this point while you're accessing with the pin_idx.
So, better to consider the implementation of lock or other mechanism
once when the whole picture is ready.
Takashi
More information about the Alsa-devel
mailing list