Commit 13800f39 authored by Libin Yang's avatar Libin Yang Committed by Daniel Vetter

ALSA: hda - add DP mst verb support

Add snd_hda_get_dev_select() and snd_hda_set_dev_select() functions
for DP MST audio support.
Reviewed-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarLibin Yang <libin.yang@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1484208294-8637-2-git-send-email-libin.yang@intel.com
parent 34869776
...@@ -311,9 +311,15 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, ...@@ -311,9 +311,15 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
} }
EXPORT_SYMBOL_GPL(snd_hda_get_conn_index); EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
/**
/* return DEVLIST_LEN parameter of the given widget */ * snd_hda_get_num_devices - get DEVLIST_LEN parameter of the given widget
static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid) * @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 wcaps = get_wcaps(codec, nid);
unsigned int parm; unsigned int parm;
...@@ -327,6 +333,7 @@ static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid) ...@@ -327,6 +333,7 @@ static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid)
parm = 0; parm = 0;
return parm & AC_DEV_LIST_LEN_MASK; return parm & AC_DEV_LIST_LEN_MASK;
} }
EXPORT_SYMBOL_GPL(snd_hda_get_num_devices);
/** /**
* snd_hda_get_devices - copy device list without cache * snd_hda_get_devices - copy device list without cache
...@@ -344,7 +351,7 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, ...@@ -344,7 +351,7 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
unsigned int parm; unsigned int parm;
int i, dev_len, devices; 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 */ if (!parm) /* not multi-stream capable */
return 0; return 0;
...@@ -368,6 +375,63 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, ...@@ -368,6 +375,63 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
return devices; 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, num_devices;
/* 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) + 1;
/* If Device List Length is 0 (num_device = 1),
* the pin is not multi stream capable.
* Do nothing in this case.
*/
if (num_devices == 1)
return 0;
/* Behavior of setting index being equal to or greater than
* Device List Length is not predictable
*/
if (num_devices <= dev_id)
return -EINVAL;
ret = snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_DEVICE_SEL, dev_id);
return ret;
}
EXPORT_SYMBOL_GPL(snd_hda_set_dev_select);
/* /*
* read widget caps for each widget and store in cache * read widget caps for each widget and store in cache
*/ */
......
...@@ -347,8 +347,11 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums, ...@@ -347,8 +347,11 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
const hda_nid_t *list); const hda_nid_t *list);
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
hda_nid_t nid, int recursive); hda_nid_t nid, int recursive);
unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
u8 *dev_list, int max_devices); u8 *dev_list, int max_devices);
int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id);
struct hda_verb { struct hda_verb {
hda_nid_t nid; hda_nid_t nid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment