[alsa-devel] [RFC V2 PATCH 3/5] ALSA: hda - hdmi dynamically bind PCM to pin when monitor hotplug
Yang, Libin
libin.yang at intel.com
Wed Nov 25 07:53:27 CET 2015
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai at suse.de]
> Sent: Tuesday, November 24, 2015 12:00 AM
> To: libin.yang at linux.intel.com
> Cc: alsa-devel at alsa-project.org; mengdong.lin at linux.intel.com; Yang,
> Libin
> Subject: Re: [alsa-devel] [RFC V2 PATCH 3/5] ALSA: hda - hdmi
> dynamically bind PCM to pin when monitor hotplug
>
> On Mon, 23 Nov 2015 15:09:32 +0100,
> libin.yang at linux.intel.com wrote:
> >
> > From: Libin Yang <libin.yang at linux.intel.com>
> >
> > Dynamically bind/unbind the PCM to pin when HDMI/DP monitor
> hotplug.
> >
> > When monitor is connected, find a proper PCM for the monitor.
> > When monitor is disconnected, unbind the PCM from the pin.
>
> You must have some strategy about binding. Please tell the story
> behind the scene, too.
>
> >
> > Signed-off-by: Libin Yang <libin.yang at linux.intel.com>
> > ---
> > sound/pci/hda/patch_hdmi.c | 82
> ++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 82 insertions(+)
> >
> > diff --git a/sound/pci/hda/patch_hdmi.c
> b/sound/pci/hda/patch_hdmi.c
> > index de22ac2..bcc2a90 100644
> > --- a/sound/pci/hda/patch_hdmi.c
> > +++ b/sound/pci/hda/patch_hdmi.c
> > @@ -72,6 +72,8 @@ struct hdmi_spec_per_cvt {
> >
> > struct hdmi_spec_per_pin {
> > hda_nid_t pin_nid;
> > + /* pin idx, different device entries on the same pin use the same
> idx */
> > + int pin_nid_idx;
> > int num_mux_nids;
> > hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
> > int mux_idx;
> > @@ -83,6 +85,7 @@ struct hdmi_spec_per_pin {
> > struct delayed_work work;
> > struct snd_kcontrol *eld_ctl;
> > struct hda_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;
> > bool setup; /* the stream has been set up by prepare callback */
> > int channels; /* current number of channels */
> > @@ -136,6 +139,7 @@ struct hdmi_spec {
> > struct snd_array pins; /* struct hdmi_spec_per_pin */
> > struct hda_pcm *pcm_rec[16];
> > struct mutex pcm_lock;
> > + unsigned long pcm_bitmap;
> > int pcm_used; /* counter of pcm_rec[] */
> > unsigned int channels_max; /* max over all cvts */
> >
> > @@ -1663,6 +1667,70 @@ static int hdmi_read_pin_conn(struct
> hda_codec *codec, int pin_idx)
> > return 0;
> > }
> >
> > +static int get_preferred_pcm_slot(struct hdmi_spec *spec,
> > + struct hdmi_spec_per_pin *per_pin)
> > +{
> > + if ((spec->pcm_bitmap & (1 << per_pin->pin_nid_idx)) == 0)
>
> Use test_bit().
Get it.
>
> > + return per_pin->pin_nid_idx;
> > + return -1;
> > +}
> > +
> > +static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
> > + struct hdmi_spec_per_pin *per_pin)
> > +{
> > + int slot;
> > + int i;
> > +
> > + /* try the prefer PCM */
> > + slot = get_preferred_pcm_slot(spec, per_pin);
> > + if (slot != -1)
> > + return slot;
> > +
> > + /* have a second try */
> > + for (i = spec->num_pins; i < spec->pcm_used; i++) {
> > + if ((spec->pcm_bitmap & (1 << i)) == 0)
>
> Ditto.
>
> > + return i;
> > + }
> > +
> > + /* the last try */
> > + for (i = 0; i < spec->pcm_used; i++) {
> > + if ((spec->pcm_bitmap & (1 << i)) == 0)
>
> Ditto.
>
> > + return i;
> > + }
> > + return -ENODEV;
>
> I think you don't need to split get_preferred_pcm_slot().
> It's a function that is called only from here, and it's even better to
> be open-coded. Then you can see the code flow more easily.
> (Also, you may notice that the last loop doesn't go all, but just up
> to num_pins, by looking through the code closely.)
>
> static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
> struct hdmi_spec_per_pin *per_pin)
> {
> int i;
>
> /* try the prefer PCM */
> if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
> return per_pin->pin_nid_idx;
>
> /* have a second try; check the "reserved area" over num_pins
> */
> for (i = spec->num_pins; i < spec->pcm_used; i++)
> if (!test_bit(i, &spec->pcm_bitmap))
> return i;
>
> /* the last try; check the empty slots in pins */
> for (i = 0; i < spec->num_pins; i++)
> if (!test_bit(i, &spec->pcm_bitmap))
> return i;
>
> return -EBUSY;
> }
OK. I will use the new code.
Regards,
Libin
>
>
>
> Takashi
More information about the Alsa-devel
mailing list