summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorLibin Yang <libin.yang@linux.intel.com>2017-01-12 03:04:52 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-01-12 04:06:47 -0500
commit13800f397ee3b4996f316b9caa8482cb90edef0d (patch)
tree4a919d8a11d95b805e3e743bc9ff21fe1f6b3803 /sound
parent34869776c76b0aa3bb882ec8a4b6f1ebb6d6f937 (diff)
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: Takashi Iwai <tiwai@suse.de> Signed-off-by: Libin Yang <libin.yang@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/1484208294-8637-2-git-send-email-libin.yang@intel.com
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_codec.c72
-rw-r--r--sound/pci/hda/hda_codec.h3
2 files changed, 71 insertions, 4 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 9913be8532ab..9dc847db1cc4 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -311,9 +311,15 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
311} 311}
312EXPORT_SYMBOL_GPL(snd_hda_get_conn_index); 312EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
313 313
314 314/**
315/* return DEVLIST_LEN parameter of the given widget */ 315 * snd_hda_get_num_devices - get DEVLIST_LEN parameter of the given widget
316static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid) 316 * @codec: the HDA codec
317 * @nid: NID of the pin to parse
318 *
319 * Get the device entry number on the given widget. This is a feature of
320 * DP MST audio. Each pin can have several device entries in it.
321 */
322unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid)
317{ 323{
318 unsigned int wcaps = get_wcaps(codec, nid); 324 unsigned int wcaps = get_wcaps(codec, nid);
319 unsigned int parm; 325 unsigned int parm;
@@ -327,6 +333,7 @@ static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid)
327 parm = 0; 333 parm = 0;
328 return parm & AC_DEV_LIST_LEN_MASK; 334 return parm & AC_DEV_LIST_LEN_MASK;
329} 335}
336EXPORT_SYMBOL_GPL(snd_hda_get_num_devices);
330 337
331/** 338/**
332 * snd_hda_get_devices - copy device list without cache 339 * 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 unsigned int parm; 351 unsigned int parm;
345 int i, dev_len, devices; 352 int i, dev_len, devices;
346 353
347 parm = get_num_devices(codec, nid); 354 parm = snd_hda_get_num_devices(codec, nid);
348 if (!parm) /* not multi-stream capable */ 355 if (!parm) /* not multi-stream capable */
349 return 0; 356 return 0;
350 357
@@ -368,6 +375,63 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
368 return devices; 375 return devices;
369} 376}
370 377
378/**
379 * snd_hda_get_dev_select - get device entry select on the pin
380 * @codec: the HDA codec
381 * @nid: NID of the pin to get device entry select
382 *
383 * Get the devcie entry select on the pin. Return the device entry
384 * id selected on the pin. Return 0 means the first device entry
385 * is selected or MST is not supported.
386 */
387int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid)
388{
389 /* not support dp_mst will always return 0, using first dev_entry */
390 if (!codec->dp_mst)
391 return 0;
392
393 return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DEVICE_SEL, 0);
394}
395EXPORT_SYMBOL_GPL(snd_hda_get_dev_select);
396
397/**
398 * snd_hda_set_dev_select - set device entry select on the pin
399 * @codec: the HDA codec
400 * @nid: NID of the pin to set device entry select
401 * @dev_id: device entry id to be set
402 *
403 * Set the device entry select on the pin nid.
404 */
405int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id)
406{
407 int ret, num_devices;
408
409 /* not support dp_mst will always return 0, using first dev_entry */
410 if (!codec->dp_mst)
411 return 0;
412
413 /* AC_PAR_DEVLIST_LEN is 0 based. */
414 num_devices = snd_hda_get_num_devices(codec, nid) + 1;
415 /* If Device List Length is 0 (num_device = 1),
416 * the pin is not multi stream capable.
417 * Do nothing in this case.
418 */
419 if (num_devices == 1)
420 return 0;
421
422 /* Behavior of setting index being equal to or greater than
423 * Device List Length is not predictable
424 */
425 if (num_devices <= dev_id)
426 return -EINVAL;
427
428 ret = snd_hda_codec_write(codec, nid, 0,
429 AC_VERB_SET_DEVICE_SEL, dev_id);
430
431 return ret;
432}
433EXPORT_SYMBOL_GPL(snd_hda_set_dev_select);
434
371/* 435/*
372 * read widget caps for each widget and store in cache 436 * read widget caps for each widget and store in cache
373 */ 437 */
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 373fcad840ea..f17f25245e52 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -347,8 +347,11 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
347 const hda_nid_t *list); 347 const hda_nid_t *list);
348int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, 348int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
349 hda_nid_t nid, int recursive); 349 hda_nid_t nid, int recursive);
350unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid);
350int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, 351int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
351 u8 *dev_list, int max_devices); 352 u8 *dev_list, int max_devices);
353int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid);
354int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id);
352 355
353struct hda_verb { 356struct hda_verb {
354 hda_nid_t nid; 357 hda_nid_t nid;