diff options
author | Libin Yang <libin.yang@linux.intel.com> | 2017-01-12 03:04:52 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-01-12 04:06:47 -0500 |
commit | 13800f397ee3b4996f316b9caa8482cb90edef0d (patch) | |
tree | 4a919d8a11d95b805e3e743bc9ff21fe1f6b3803 /sound | |
parent | 34869776c76b0aa3bb882ec8a4b6f1ebb6d6f937 (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.c | 72 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 |
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 | } |
312 | EXPORT_SYMBOL_GPL(snd_hda_get_conn_index); | 312 | EXPORT_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 |
316 | static 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 | */ | ||
322 | unsigned 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 | } |
336 | EXPORT_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 | */ | ||
387 | int 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 | } | ||
395 | EXPORT_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 | */ | ||
405 | int 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 | } | ||
433 | EXPORT_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); |
348 | int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, | 348 | int 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); |
350 | unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid); | ||
350 | int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, | 351 | int 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); |
353 | int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid); | ||
354 | int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id); | ||
352 | 355 | ||
353 | struct hda_verb { | 356 | struct hda_verb { |
354 | hda_nid_t nid; | 357 | hda_nid_t nid; |