[alsa-devel] [RFC PATCH v2 1/3] ALSA: hda - add DP mst verb support

Yang, Libin libin.yang at intel.com
Fri Mar 25 03:26:06 CET 2016


Hi Takashi,

> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai at suse.de]
> Sent: Thursday, March 24, 2016 5:19 PM
> To: Yang, Libin
> Cc: libin.yang at linux.intel.com; alsa-devel at alsa-project.org; Lin,
> Mengdong
> Subject: Re: [alsa-devel] [RFC PATCH v2 1/3] ALSA: hda - add DP mst verb
> support
> 
> On Thu, 24 Mar 2016 09:44:32 +0100,
> Yang, Libin wrote:
> >
> > Hi Takashi,
> >
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai at suse.de]
> > > Sent: Tuesday, March 22, 2016 7:17 PM
> > > To: libin.yang at linux.intel.com
> > > Cc: alsa-devel at alsa-project.org; Lin, Mengdong; Yang, Libin
> > > Subject: Re: [alsa-devel] [RFC PATCH v2 1/3] ALSA: hda - add DP mst
> verb
> > > support
> > >
> > > On Mon, 21 Mar 2016 09:37:54 +0100,
> > > libin.yang at linux.intel.com wrote:
> > > >
> > > > From: Libin Yang <libin.yang at linux.intel.com>
> > > >
> > > > Add snd_hda_get_dev_select() and snd_hda_set_dev_select()
> > > functions
> > > > for DP MST audio support.
> > > >
> > > > Signed-off-by: Libin Yang <libin.yang at linux.intel.com>
> > > > ---
> > > >  sound/pci/hda/hda_codec.c | 83
> > > ++++++++++++++++++++++++++++++++++++++++++++---
> > > >  sound/pci/hda/hda_codec.h |  3 ++
> > > >  2 files changed, 82 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/sound/pci/hda/hda_codec.c
> b/sound/pci/hda/hda_codec.c
> > > > index d17e38e..db94a66 100644
> > > > --- a/sound/pci/hda/hda_codec.c
> > > > +++ b/sound/pci/hda/hda_codec.c
> > > > @@ -325,9 +325,16 @@ int snd_hda_get_conn_index(struct
> > > hda_codec *codec, hda_nid_t mux,
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
> > > >
> > > > -
> > > > -/* return DEVLIST_LEN parameter of the given widget */
> > > > -static unsigned int get_num_devices(struct hda_codec *codec,
> > > hda_nid_t nid)
> > > > +/**
> > > > + * snd_hda_get_num_devices - get DEVLIST_LEN parameter of the
> > > given widget
> > > > + *  @codec: the HDA codec
> > > > + *  @nid: NID of the pin to parse
> > > > + *
> > > > + * Get the device entry number on the given widget.
> > > > + * This is a feature of DP MST audio. Each pin can
> > > > + * have several device entries in it.
> > > > + */
> > > > +unsigned int snd_hda_get_num_devices(struct hda_codec *codec,
> > > hda_nid_t nid)
> > > >  {
> > > >  	unsigned int wcaps = get_wcaps(codec, nid);
> > > >  	unsigned int parm;
> > > > @@ -341,6 +348,7 @@ static unsigned int get_num_devices(struct
> > > hda_codec *codec, hda_nid_t nid)
> > > >  		parm = 0;
> > > >  	return parm & AC_DEV_LIST_LEN_MASK;
> > > >  }
> > > > +EXPORT_SYMBOL_GPL(snd_hda_get_num_devices);
> > > >
> > > >  /**
> > > >   * snd_hda_get_devices - copy device list without cache
> > > > @@ -358,7 +366,7 @@ int snd_hda_get_devices(struct hda_codec
> > > *codec, hda_nid_t nid,
> > > >  	unsigned int parm;
> > > >  	int i, dev_len, devices;
> > > >
> > > > -	parm = get_num_devices(codec, nid);
> > > > +	parm = snd_hda_get_num_devices(codec, nid);
> > > >  	if (!parm)	/* not multi-stream capable */
> > > >  		return 0;
> > > >
> > > > @@ -382,6 +390,73 @@ int snd_hda_get_devices(struct
> hda_codec
> > > *codec, hda_nid_t nid,
> > > >  	return devices;
> > > >  }
> > > >
> > > > +/**
> > > > + * snd_hda_get_dev_select - get device entry select on the pin
> > > > + * @codec: the HDA codec
> > > > + * @nid: NID of the pin to get device entry select
> > > > + *
> > > > + * Get the devcie entry select on the pin. Return the device entry
> > > > + * id selected on the pin. Return 0 means the first device entry
> > > > + * is selected or MST is not supported.
> > > > + */
> > > > +int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t
> nid)
> > > > +{
> > > > +	/* not support dp_mst will always return 0, using first dev_entry
> > > */
> > > > +	if (!codec->dp_mst)
> > > > +		return 0;
> > > > +
> > > > +	return snd_hda_codec_read(codec, nid, 0,
> > > AC_VERB_GET_DEVICE_SEL, 0);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(snd_hda_get_dev_select);
> > > > +
> > > > +/**
> > > > + * snd_hda_set_dev_select - set device entry select on the pin
> > > > + * @codec: the HDA codec
> > > > + * @nid: NID of the pin to set device entry select
> > > > + * @dev_id: device entry id to be set
> > > > + *
> > > > + * Set the device entry select on the pin nid.
> > > > + */
> > > > +int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t
> nid,
> > > int dev_id)
> > > > +{
> > > > +	int ret, dev, num_devices;
> > > > +	unsigned long timeout;
> > > > +
> > > > +	/* not support dp_mst will always return 0, using first dev_entry
> > > */
> > > > +	if (!codec->dp_mst)
> > > > +		return 0;
> > > > +
> > > > +	/* AC_PAR_DEVLIST_LEN is 0 based. */
> > > > +	num_devices = snd_hda_get_num_devices(codec, nid);
> > > > +	/* If Device List Length is 0, the pin is not multi stream capable.
> > > > +	 */
> > > > +	if (num_devices == 0)
> > > > +		return 0;
> > > > +
> > > > +	/* Behavior of setting index being equal to or greater than
> > > > +	 * Device List Length is not predictable
> > > > +	 */
> > > > +	if (num_devices + 1 <= dev_id)
> > > > +		return 0;
> > >
> > > Is this correct?  Doesn't num_devices=1 mean that there is only a
> > > single device?  If dev_id=1 must be invalid, but the check above
> > > passes.  The standard form of such index check is like
> >
> > num_device is the return value of the verb AC_PAR_DEVLIST_LEN.
> > device number is AC_PAR_DEVLIST_LEN + 1.
> >
> > >From the spec:
> > Device List Length is a 0 based integer value indicating the number
> >  of sink device that a multi stream capable Digital Display Pin
> > Widget can support. If Device List Length is value is 0, there is
> > only one sink device connection possible indicating the Pin Widget
> >  is not multi stream capable, and there is no Device Select control
> >
> > And dev_id is 0 based.
> >
> > If dev_id = 1, it means set the second device entry, and
> > num_device + 1 (the real number of device entries)
> > must be equal to or greater than 2.
> > (num_device + 1 > dev_id )
> >
> > So (num_device + 1 <= dev_id) is wrong situation.
> 
> If so, the term "num_devices" is counter-intuitive.  It should be
> corrected to the natural value, i.e. based on 1, or renamed to a
> different one.  Readers would assume that the number of devices is 1
> if there is a single element, not 0.  If this isn't true, it just
> confuses readers.

Get it. So what do you think if using:

if (dev_id > num_device)  //both is 0 based.

Regards,
Libin

> 
> 
> > >
> > > 	if (dev_id >= num_devices)
> > > 		error;
> > >
> > > And this also leads to the question.  Shouldn't we return an error if
> > > an invalid dev_id is given?
> >
> > I'm thinking if the wrong dev_id is given, we just leave as it is before.
> > I will return the -EINVAL in next version.
> 
> IMO, it's safer to return an error.  Since non-zero dev_id is only for
> MST, the code path that passes such a value must handle MST properly,
> i.e. not through the default code path.
> 
> 
> > > > +
> > > > +	timeout = jiffies + msecs_to_jiffies(500);
> > > > +
> > > > +	/* make sure the device entry selection takes effect */
> > > > +	do {
> > > > +		ret = snd_hda_codec_write(codec, nid, 0,
> > > > +			AC_VERB_SET_DEVICE_SEL, dev_id);
> > > > +		udelay(20);
> > > > +
> > > > +		dev = snd_hda_get_dev_select(codec, nid);
> > > > +		if (dev == dev_id)
> > > > +			break;
> > > > +		msleep(20);
> > > > +	} while (time_before(jiffies, timeout));
> > >
> > > Is this loop needed?  Most verbs take effect immediately, and so far,
> > > the only exception is the power state.
> >
> > OK, I will remove the loop.
> 
> Well, I don't mean to remove forcibly.  Just want to be sure.
> If such a loop is needed practically, we must have it, of course.
> Let's check.
> 
> 
> thanks,
> 
> Takashi


More information about the Alsa-devel mailing list