diff options
author | Jeeja KP <jeeja.kp@intel.com> | 2017-02-07 08:39:45 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-02-16 13:55:14 -0500 |
commit | fc181b04f2d44805624d4bc5a0615bc084199a81 (patch) | |
tree | 93799d5818adf927fa5590f4eebc71aa6ab500d8 | |
parent | 2acd8309a3a4e6dc04e72d2db0716825095c02d6 (diff) |
ASoC: hdac_hdmi: Add MST verb support
To support DP MST audio, new pin verbs/params are added. This patch
adds helper functions to do following:
o To set a specific port
o To get the currently selected port
o To get the length of port.
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/codecs/hdac_hdmi.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 17a1ad3ead21..84b7d6cd7c37 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c | |||
@@ -142,6 +142,76 @@ hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi, | |||
142 | return pcm; | 142 | return pcm; |
143 | } | 143 | } |
144 | 144 | ||
145 | /* MST supported verbs */ | ||
146 | /* | ||
147 | * Get the no devices that can be connected to a port on the Pin widget. | ||
148 | */ | ||
149 | static int hdac_hdmi_get_port_len(struct hdac_ext_device *hdac, hda_nid_t nid) | ||
150 | { | ||
151 | unsigned int caps; | ||
152 | unsigned int type, param; | ||
153 | |||
154 | caps = get_wcaps(&hdac->hdac, nid); | ||
155 | type = get_wcaps_type(caps); | ||
156 | |||
157 | if (!(caps & AC_WCAP_DIGITAL) || (type != AC_WID_PIN)) | ||
158 | return 0; | ||
159 | |||
160 | param = snd_hdac_read_parm_uncached(&hdac->hdac, nid, | ||
161 | AC_PAR_DEVLIST_LEN); | ||
162 | if (param == -1) | ||
163 | return param; | ||
164 | |||
165 | return param & AC_DEV_LIST_LEN_MASK; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * Get the port entry select on the pin. Return the port entry | ||
170 | * id selected on the pin. Return 0 means the first port entry | ||
171 | * is selected or MST is not supported. | ||
172 | */ | ||
173 | static int hdac_hdmi_port_select_get(struct hdac_ext_device *hdac, | ||
174 | struct hdac_hdmi_port *port) | ||
175 | { | ||
176 | return snd_hdac_codec_read(&hdac->hdac, port->pin->nid, | ||
177 | 0, AC_VERB_GET_DEVICE_SEL, 0); | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * Sets the selected port entry for the configuring Pin widget verb. | ||
182 | * returns error if port set is not equal to port get otherwise success | ||
183 | */ | ||
184 | static int hdac_hdmi_port_select_set(struct hdac_ext_device *hdac, | ||
185 | struct hdac_hdmi_port *port) | ||
186 | { | ||
187 | int num_ports; | ||
188 | |||
189 | if (!port->pin->mst_capable) | ||
190 | return 0; | ||
191 | |||
192 | /* AC_PAR_DEVLIST_LEN is 0 based. */ | ||
193 | num_ports = hdac_hdmi_get_port_len(hdac, port->pin->nid); | ||
194 | |||
195 | if (num_ports < 0) | ||
196 | return -EIO; | ||
197 | /* | ||
198 | * Device List Length is a 0 based integer value indicating the | ||
199 | * number of sink device that a MST Pin Widget can support. | ||
200 | */ | ||
201 | if (num_ports + 1 < port->id) | ||
202 | return 0; | ||
203 | |||
204 | snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0, | ||
205 | AC_VERB_SET_DEVICE_SEL, port->id); | ||
206 | |||
207 | if (port->id != hdac_hdmi_port_select_get(hdac, port)) | ||
208 | return -EIO; | ||
209 | |||
210 | dev_dbg(&hdac->hdac.dev, "Selected the port=%d\n", port->id); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
145 | static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, | 215 | static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, |
146 | int pcm_idx) | 216 | int pcm_idx) |
147 | { | 217 | { |