[alsa-devel] [RFC PATCH 1/3] ALSA: hda - add flags and routines to get devices selection info for DP1.2 MST

Takashi Iwai tiwai at suse.de
Fri Aug 23 14:21:30 CEST 2013


At Fri, 23 Aug 2013 00:56:36 -0400,
mengdong.lin at intel.com wrote:
> 
> From: Mengdong Lin <mengdong.lin at intel.com>
> 
> This patch adds flags and routines to get device list & selection info on
> a pin.
> 
> To support Display Port 1.2 multi-stream transport (MST) over single DP port,
> a pin can support multiple devices. Please refer to HD-A spec Document Change
> Notificaton HDA040-A.
> 
> A display audio codec can set flag "dp_mst" in its patch, indicating its pins
> can support MST. But at runtime, a pin may not be multi-streaming capable and
> report the device list is empty, depending on Gfx driver configuration.
> 
> Signed-off-by: Mengdong Lin <mengdong.lin at intel.com>
> 
> diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
> index fdbb09a..fb58291 100644
> --- a/sound/pci/hda/hda_codec.c
> +++ b/sound/pci/hda/hda_codec.c
> @@ -666,6 +666,63 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
>  }
>  EXPORT_SYMBOL_HDA(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)
> +{
> +	unsigned int wcaps = get_wcaps(codec, nid);
> +	unsigned int parm;
> +
> +	if (!codec->dp_mst || !(wcaps & AC_WCAP_DIGITAL) ||
> +	    get_wcaps_type(wcaps) != AC_WID_PIN)
> +		return 0;
> +
> +	parm = snd_hda_param_read(codec, nid, AC_PAR_DEVLIST_LEN);
> +	if (parm == -1 && codec->bus->rirb_error)
> +		parm = 0;
> +	return parm & AC_DEVLIST_LEN;
> +}
> +
> +/**
> + * snd_hda_get_devices - copy device list without cache
> + * @codec: the HDA codec
> + * @nid: NID of the pin to parse
> + * @dev_list: device list array
> + * @max_devices: max. number of devices to store
> + *
> + * Copy the device list. This info is dynamic and so not cached.
> + * Currently called only from hda_proc.c, so not exported.
> + */
> +int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
> +			union hda_devlist_entry *dev_list, int max_devices)
> +{
> +	unsigned int parm;
> +	int i, dev_len, devices;
> +
> +	parm = get_num_devices(codec, nid);
> +	if (!parm)	/* not multi-stream capable */
> +		return 0;
> +
> +	dev_len = parm + 1;

Check dev_len with max_devices here.


> +	devices = 0;
> +
> +	while (devices < dev_len) {
> +		parm = snd_hda_codec_read(codec, nid, 0,
> +					  AC_VERB_GET_DEVICE_LIST, devices);
> +		if (parm == -1 && codec->bus->rirb_error)
> +			break;
> +
> +		for (i = 0; i < 8; i++) {
> +			dev_list[devices].value = parm & 0x7;
> +			parm >>= 4;
> +			devices++;
> +			if (devices >= dev_len)
> +				break;
> +		}
> +	}
> +	return devices;
> +}
> +
>  /**
>   * snd_hda_queue_unsol_event - add an unsolicited event to queue
>   * @bus: the BUS
> diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
> index 701c2e0..736b55a 100644
> --- a/sound/pci/hda/hda_codec.h
> +++ b/sound/pci/hda/hda_codec.h
> @@ -94,6 +94,8 @@ enum {
>  #define AC_VERB_GET_HDMI_DIP_XMIT		0x0f32
>  #define AC_VERB_GET_HDMI_CP_CTRL		0x0f33
>  #define AC_VERB_GET_HDMI_CHAN_SLOT		0x0f34
> +#define AC_VERB_GET_DEVICE_SEL			0xf35
> +#define AC_VERB_GET_DEVICE_LIST			0xf36
>  
>  /*
>   * SET verbs
> @@ -133,6 +135,7 @@ enum {
>  #define AC_VERB_SET_HDMI_DIP_XMIT		0x732
>  #define AC_VERB_SET_HDMI_CP_CTRL		0x733
>  #define AC_VERB_SET_HDMI_CHAN_SLOT		0x734
> +#define AC_VERB_SET_DEVICE_SEL			0x735
>  
>  /*
>   * Parameter IDs
> @@ -154,6 +157,7 @@ enum {
>  #define AC_PAR_GPIO_CAP			0x11
>  #define AC_PAR_AMP_OUT_CAP		0x12
>  #define AC_PAR_VOL_KNB_CAP		0x13
> +#define AC_PAR_DEVLIST_LEN		0x15
>  #define AC_PAR_HDMI_LPCM_CAP		0x20
>  
>  /*
> @@ -795,6 +799,19 @@ struct hda_pcm {
>  	bool own_chmap;		/* codec driver provides own channel maps */
>  };
>  
> +/* display pin's device list entry */
> +union  hda_devlist_entry {
> +	unsigned int value;
> +	struct  {
> +		unsigned int present_detect:1;
> +		unsigned int eld_valid:1;
> +		unsigned int inactive:1;
> +	} bits;
> +};

The bit fields are not really portable.
Please use the explicit bit operation instead.


thanks,

Takashi


More information about the Alsa-devel mailing list