diff options
author | Mengdong Lin <mengdong.lin@intel.com> | 2013-08-26 21:35:21 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-08-27 06:15:09 -0400 |
commit | f1aa06847506d5b88f5eb41fae6a24a7128097e7 (patch) | |
tree | cac7c3bd3fa0cc6a945f2393ab678b263f65b99c /sound/pci | |
parent | 68538bf2bce557c3b5fe8c59b034d45352500db1 (diff) |
ALSA: hda - add flags and routines to get devices selection info for DP1.2 MST
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@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 58 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 16 |
2 files changed, 74 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fdbb09a9b9e5..5b6c4e3c92ca 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -666,6 +666,64 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, | |||
666 | } | 666 | } |
667 | EXPORT_SYMBOL_HDA(snd_hda_get_conn_index); | 667 | EXPORT_SYMBOL_HDA(snd_hda_get_conn_index); |
668 | 668 | ||
669 | |||
670 | /* return DEVLIST_LEN parameter of the given widget */ | ||
671 | static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid) | ||
672 | { | ||
673 | unsigned int wcaps = get_wcaps(codec, nid); | ||
674 | unsigned int parm; | ||
675 | |||
676 | if (!codec->dp_mst || !(wcaps & AC_WCAP_DIGITAL) || | ||
677 | get_wcaps_type(wcaps) != AC_WID_PIN) | ||
678 | return 0; | ||
679 | |||
680 | parm = snd_hda_param_read(codec, nid, AC_PAR_DEVLIST_LEN); | ||
681 | if (parm == -1 && codec->bus->rirb_error) | ||
682 | parm = 0; | ||
683 | return parm & AC_DEV_LIST_LEN_MASK; | ||
684 | } | ||
685 | |||
686 | /** | ||
687 | * snd_hda_get_devices - copy device list without cache | ||
688 | * @codec: the HDA codec | ||
689 | * @nid: NID of the pin to parse | ||
690 | * @dev_list: device list array | ||
691 | * @max_devices: max. number of devices to store | ||
692 | * | ||
693 | * Copy the device list. This info is dynamic and so not cached. | ||
694 | * Currently called only from hda_proc.c, so not exported. | ||
695 | */ | ||
696 | int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, | ||
697 | u8 *dev_list, int max_devices) | ||
698 | { | ||
699 | unsigned int parm; | ||
700 | int i, dev_len, devices; | ||
701 | |||
702 | parm = get_num_devices(codec, nid); | ||
703 | if (!parm) /* not multi-stream capable */ | ||
704 | return 0; | ||
705 | |||
706 | dev_len = parm + 1; | ||
707 | dev_len = dev_len < max_devices ? dev_len : max_devices; | ||
708 | |||
709 | devices = 0; | ||
710 | while (devices < dev_len) { | ||
711 | parm = snd_hda_codec_read(codec, nid, 0, | ||
712 | AC_VERB_GET_DEVICE_LIST, devices); | ||
713 | if (parm == -1 && codec->bus->rirb_error) | ||
714 | break; | ||
715 | |||
716 | for (i = 0; i < 8; i++) { | ||
717 | dev_list[devices] = (u8)parm; | ||
718 | parm >>= 4; | ||
719 | devices++; | ||
720 | if (devices >= dev_len) | ||
721 | break; | ||
722 | } | ||
723 | } | ||
724 | return devices; | ||
725 | } | ||
726 | |||
669 | /** | 727 | /** |
670 | * snd_hda_queue_unsol_event - add an unsolicited event to queue | 728 | * snd_hda_queue_unsol_event - add an unsolicited event to queue |
671 | * @bus: the BUS | 729 | * @bus: the BUS |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 701c2e069b10..b838c70420d1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -94,6 +94,8 @@ enum { | |||
94 | #define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32 | 94 | #define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32 |
95 | #define AC_VERB_GET_HDMI_CP_CTRL 0x0f33 | 95 | #define AC_VERB_GET_HDMI_CP_CTRL 0x0f33 |
96 | #define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34 | 96 | #define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34 |
97 | #define AC_VERB_GET_DEVICE_SEL 0xf35 | ||
98 | #define AC_VERB_GET_DEVICE_LIST 0xf36 | ||
97 | 99 | ||
98 | /* | 100 | /* |
99 | * SET verbs | 101 | * SET verbs |
@@ -133,6 +135,7 @@ enum { | |||
133 | #define AC_VERB_SET_HDMI_DIP_XMIT 0x732 | 135 | #define AC_VERB_SET_HDMI_DIP_XMIT 0x732 |
134 | #define AC_VERB_SET_HDMI_CP_CTRL 0x733 | 136 | #define AC_VERB_SET_HDMI_CP_CTRL 0x733 |
135 | #define AC_VERB_SET_HDMI_CHAN_SLOT 0x734 | 137 | #define AC_VERB_SET_HDMI_CHAN_SLOT 0x734 |
138 | #define AC_VERB_SET_DEVICE_SEL 0x735 | ||
136 | 139 | ||
137 | /* | 140 | /* |
138 | * Parameter IDs | 141 | * Parameter IDs |
@@ -154,6 +157,7 @@ enum { | |||
154 | #define AC_PAR_GPIO_CAP 0x11 | 157 | #define AC_PAR_GPIO_CAP 0x11 |
155 | #define AC_PAR_AMP_OUT_CAP 0x12 | 158 | #define AC_PAR_AMP_OUT_CAP 0x12 |
156 | #define AC_PAR_VOL_KNB_CAP 0x13 | 159 | #define AC_PAR_VOL_KNB_CAP 0x13 |
160 | #define AC_PAR_DEVLIST_LEN 0x15 | ||
157 | #define AC_PAR_HDMI_LPCM_CAP 0x20 | 161 | #define AC_PAR_HDMI_LPCM_CAP 0x20 |
158 | 162 | ||
159 | /* | 163 | /* |
@@ -352,6 +356,10 @@ enum { | |||
352 | #define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */ | 356 | #define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */ |
353 | #define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */ | 357 | #define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */ |
354 | 358 | ||
359 | /* Display pin's device list length */ | ||
360 | #define AC_DEV_LIST_LEN_MASK 0x3f | ||
361 | #define AC_MAX_DEV_LIST_LEN 64 | ||
362 | |||
355 | /* | 363 | /* |
356 | * Control Parameters | 364 | * Control Parameters |
357 | */ | 365 | */ |
@@ -460,6 +468,11 @@ enum { | |||
460 | #define AC_DEFCFG_PORT_CONN (0x3<<30) | 468 | #define AC_DEFCFG_PORT_CONN (0x3<<30) |
461 | #define AC_DEFCFG_PORT_CONN_SHIFT 30 | 469 | #define AC_DEFCFG_PORT_CONN_SHIFT 30 |
462 | 470 | ||
471 | /* Display pin's device list entry */ | ||
472 | #define AC_DE_PD (1<<0) | ||
473 | #define AC_DE_ELDV (1<<1) | ||
474 | #define AC_DE_IA (1<<2) | ||
475 | |||
463 | /* device device types (0x0-0xf) */ | 476 | /* device device types (0x0-0xf) */ |
464 | enum { | 477 | enum { |
465 | AC_JACK_LINE_OUT, | 478 | AC_JACK_LINE_OUT, |
@@ -885,6 +898,7 @@ struct hda_codec { | |||
885 | unsigned int pcm_format_first:1; /* PCM format must be set first */ | 898 | unsigned int pcm_format_first:1; /* PCM format must be set first */ |
886 | unsigned int epss:1; /* supporting EPSS? */ | 899 | unsigned int epss:1; /* supporting EPSS? */ |
887 | unsigned int cached_write:1; /* write only to caches */ | 900 | unsigned int cached_write:1; /* write only to caches */ |
901 | unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */ | ||
888 | #ifdef CONFIG_PM | 902 | #ifdef CONFIG_PM |
889 | unsigned int power_on :1; /* current (global) power-state */ | 903 | unsigned int power_on :1; /* current (global) power-state */ |
890 | unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */ | 904 | unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */ |
@@ -972,6 +986,8 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums, | |||
972 | const hda_nid_t *list); | 986 | const hda_nid_t *list); |
973 | int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, | 987 | int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, |
974 | hda_nid_t nid, int recursive); | 988 | hda_nid_t nid, int recursive); |
989 | int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, | ||
990 | u8 *dev_list, int max_devices); | ||
975 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | 991 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, |
976 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp); | 992 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp); |
977 | 993 | ||