blob: 6cf86a0a118c001e268f531928e69a739d8de27e [file] [log] [blame]
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301/*
2 * hdac_hdmi.c - ASoc HDA-HDMI codec driver for Intel platforms
3 *
4 * Copyright (C) 2014-2015 Intel Corp
5 * Author: Samreen Nilofer <samreen.nilofer@intel.com>
6 * Subhransu S. Prusty <subhransu.s.prusty@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <linux/init.h>
21#include <linux/delay.h>
22#include <linux/module.h>
23#include <linux/pm_runtime.h>
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +053024#include <linux/hdmi.h>
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +053025#include <drm/drm_edid.h>
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053026#include <sound/pcm_params.h>
Jeeja KP4a3478d2016-02-12 07:46:06 +053027#include <sound/jack.h>
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053028#include <sound/soc.h>
29#include <sound/hdaudio_ext.h>
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +053030#include <sound/hda_i915.h>
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +053031#include <sound/pcm_drm_eld.h>
Subhransu S. Prustybcced702016-04-14 10:07:30 +053032#include <sound/hda_chmap.h>
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053033#include "../../hda/local.h"
Jeeja KP4a3478d2016-02-12 07:46:06 +053034#include "hdac_hdmi.h"
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053035
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +053036#define NAME_SIZE 32
37
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +053038#define AMP_OUT_MUTE 0xb080
39#define AMP_OUT_UNMUTE 0xb000
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053040#define PIN_OUT (AC_PINCTL_OUT_EN)
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +053041
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053042#define HDA_MAX_CONNECTIONS 32
43
Subhransu S. Prusty148569f2016-02-12 07:46:07 +053044#define HDA_MAX_CVTS 3
Jeeja KP754695f2017-02-06 12:09:14 +053045#define HDA_MAX_PORTS 3
Subhransu S. Prusty148569f2016-02-12 07:46:07 +053046
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +053047#define ELD_MAX_SIZE 256
48#define ELD_FIXED_BYTES 20
49
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +053050#define ELD_VER_CEA_861D 2
51#define ELD_VER_PARTIAL 31
52#define ELD_MAX_MNL 16
53
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053054struct hdac_hdmi_cvt_params {
55 unsigned int channels_min;
56 unsigned int channels_max;
57 u32 rates;
58 u64 formats;
59 unsigned int maxbps;
60};
61
62struct hdac_hdmi_cvt {
Subhransu S. Prusty15b91442015-12-09 21:46:10 +053063 struct list_head head;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053064 hda_nid_t nid;
Jeeja KP4a3478d2016-02-12 07:46:06 +053065 const char *name;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053066 struct hdac_hdmi_cvt_params params;
67};
68
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +053069/* Currently only spk_alloc, more to be added */
70struct hdac_hdmi_parsed_eld {
71 u8 spk_alloc;
72};
73
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +053074struct hdac_hdmi_eld {
75 bool monitor_present;
76 bool eld_valid;
77 int eld_size;
78 char eld_buffer[ELD_MAX_SIZE];
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +053079 struct hdac_hdmi_parsed_eld info;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +053080};
81
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053082struct hdac_hdmi_pin {
Subhransu S. Prusty15b91442015-12-09 21:46:10 +053083 struct list_head head;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053084 hda_nid_t nid;
Jeeja KP2acd8302017-02-06 12:09:18 +053085 bool mst_capable;
Jeeja KP754695f2017-02-06 12:09:14 +053086 struct hdac_hdmi_port *ports;
87 int num_ports;
88 struct hdac_ext_device *edev;
89};
90
91struct hdac_hdmi_port {
92 int id;
93 struct hdac_hdmi_pin *pin;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053094 int num_mux_nids;
95 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +053096 struct hdac_hdmi_eld eld;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053097};
98
Jeeja KP4a3478d2016-02-12 07:46:06 +053099struct hdac_hdmi_pcm {
100 struct list_head head;
101 int pcm_id;
Jeeja KP754695f2017-02-06 12:09:14 +0530102 struct hdac_hdmi_port *port;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530103 struct hdac_hdmi_cvt *cvt;
104 struct snd_jack *jack;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530105 int stream_tag;
106 int channels;
107 int format;
Jeeja KPab1eea12017-01-24 21:49:05 +0530108 bool chmap_set;
109 unsigned char chmap[8]; /* ALSA API channel-map */
110 struct mutex lock;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530111};
112
Jeeja KP754695f2017-02-06 12:09:14 +0530113struct hdac_hdmi_dai_port_map {
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530114 int dai_id;
Jeeja KP754695f2017-02-06 12:09:14 +0530115 struct hdac_hdmi_port *port;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530116 struct hdac_hdmi_cvt *cvt;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530117};
118
119struct hdac_hdmi_priv {
Jeeja KP754695f2017-02-06 12:09:14 +0530120 struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS];
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530121 struct list_head pin_list;
122 struct list_head cvt_list;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530123 struct list_head pcm_list;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530124 int num_pin;
125 int num_cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530126 int num_ports;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530127 struct mutex pin_mutex;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530128 struct hdac_chmap chmap;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530129};
130
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530131static struct hdac_hdmi_pcm *
132hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi,
133 struct hdac_hdmi_cvt *cvt)
134{
135 struct hdac_hdmi_pcm *pcm = NULL;
Jeeja KP1de777f2017-01-10 17:57:48 +0530136
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530137 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
138 if (pcm->cvt == cvt)
139 break;
140 }
141
142 return pcm;
143}
Jeeja KP1de777f2017-01-10 17:57:48 +0530144
Jeeja KPfc181b02017-02-07 19:09:45 +0530145/* MST supported verbs */
146/*
147 * Get the no devices that can be connected to a port on the Pin widget.
148 */
149static 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 */
173static 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 */
184static 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
Subhransu S. Prusty28890992016-04-14 10:07:34 +0530215static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi,
216 int pcm_idx)
217{
218 struct hdac_hdmi_pcm *pcm;
219
220 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
221 if (pcm->pcm_id == pcm_idx)
222 return pcm;
223 }
224
225 return NULL;
226}
227
Subhransu S. Prustye342ac02015-11-10 18:42:07 +0530228static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
229{
Geliang Tang51b2c422015-12-28 22:47:13 +0800230 struct hdac_device *hdac = dev_to_hdac_dev(dev);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +0530231
Geliang Tang51b2c422015-12-28 22:47:13 +0800232 return to_ehdac_device(hdac);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +0530233}
234
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530235static unsigned int sad_format(const u8 *sad)
236{
237 return ((sad[0] >> 0x3) & 0x1f);
238}
239
240static unsigned int sad_sample_bits_lpcm(const u8 *sad)
241{
242 return (sad[2] & 7);
243}
244
245static int hdac_hdmi_eld_limit_formats(struct snd_pcm_runtime *runtime,
246 void *eld)
247{
248 u64 formats = SNDRV_PCM_FMTBIT_S16;
249 int i;
250 const u8 *sad, *eld_buf = eld;
251
252 sad = drm_eld_sad(eld_buf);
253 if (!sad)
254 goto format_constraint;
255
256 for (i = drm_eld_sad_count(eld_buf); i > 0; i--, sad += 3) {
257 if (sad_format(sad) == 1) { /* AUDIO_CODING_TYPE_LPCM */
258
259 /*
260 * the controller support 20 and 24 bits in 32 bit
261 * container so we set S32
262 */
263 if (sad_sample_bits_lpcm(sad) & 0x6)
264 formats |= SNDRV_PCM_FMTBIT_S32;
265 }
266 }
267
268format_constraint:
269 return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
270 formats);
271
272}
273
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530274static void
275hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid,
276 int packet_index, int byte_index)
277{
278 int val;
279
280 val = (packet_index << 5) | (byte_index & 0x1f);
281
282 snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
283 AC_VERB_SET_HDMI_DIP_INDEX, val);
284}
285
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530286struct dp_audio_infoframe {
287 u8 type; /* 0x84 */
288 u8 len; /* 0x1b */
289 u8 ver; /* 0x11 << 2 */
290
291 u8 CC02_CT47; /* match with HDMI infoframe from this on */
292 u8 SS01_SF24;
293 u8 CXT04;
294 u8 CA;
295 u8 LFEPBL01_LSV36_DM_INH7;
296};
297
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530298static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
Jeeja KP754695f2017-02-06 12:09:14 +0530299 struct hdac_hdmi_pcm *pcm, struct hdac_hdmi_port *port)
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530300{
301 uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
302 struct hdmi_audio_infoframe frame;
Jeeja KP754695f2017-02-06 12:09:14 +0530303 struct hdac_hdmi_pin *pin = port->pin;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530304 struct dp_audio_infoframe dp_ai;
305 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KPab1eea12017-01-24 21:49:05 +0530306 struct hdac_hdmi_cvt *cvt = pcm->cvt;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530307 u8 *dip;
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530308 int ret;
309 int i;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530310 const u8 *eld_buf;
311 u8 conn_type;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530312 int channels, ca;
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530313
Jeeja KP754695f2017-02-06 12:09:14 +0530314 ca = snd_hdac_channel_allocation(&hdac->hdac, port->eld.info.spk_alloc,
Jeeja KPab1eea12017-01-24 21:49:05 +0530315 pcm->channels, pcm->chmap_set, true, pcm->chmap);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530316
317 channels = snd_hdac_get_active_channels(ca);
Jeeja KPab1eea12017-01-24 21:49:05 +0530318 hdmi->chmap.ops.set_channel_count(&hdac->hdac, cvt->nid, channels);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530319
320 snd_hdac_setup_channel_mapping(&hdmi->chmap, pin->nid, false, ca,
Jeeja KPab1eea12017-01-24 21:49:05 +0530321 pcm->channels, pcm->chmap, pcm->chmap_set);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530322
Jeeja KP754695f2017-02-06 12:09:14 +0530323 eld_buf = port->eld.eld_buffer;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530324 conn_type = drm_eld_get_conn_type(eld_buf);
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530325
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530326 switch (conn_type) {
327 case DRM_ELD_CONN_TYPE_HDMI:
328 hdmi_audio_infoframe_init(&frame);
329
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530330 frame.channels = channels;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530331 frame.channel_allocation = ca;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530332
333 ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
334 if (ret < 0)
335 return ret;
336
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530337 break;
338
339 case DRM_ELD_CONN_TYPE_DP:
340 memset(&dp_ai, 0, sizeof(dp_ai));
341 dp_ai.type = 0x84;
342 dp_ai.len = 0x1b;
343 dp_ai.ver = 0x11 << 2;
344 dp_ai.CC02_CT47 = channels - 1;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530345 dp_ai.CA = ca;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530346
347 dip = (u8 *)&dp_ai;
348 break;
349
350 default:
351 dev_err(&hdac->hdac.dev, "Invalid connection type: %d\n",
352 conn_type);
353 return -EIO;
354 }
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530355
356 /* stop infoframe transmission */
Jeeja KPab1eea12017-01-24 21:49:05 +0530357 hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0);
358 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530359 AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE);
360
361
362 /* Fill infoframe. Index auto-incremented */
Jeeja KPab1eea12017-01-24 21:49:05 +0530363 hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0);
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530364 if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
Subhransu S. Prusty391005e2016-03-10 09:04:07 +0530365 for (i = 0; i < sizeof(buffer); i++)
Jeeja KPab1eea12017-01-24 21:49:05 +0530366 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prusty391005e2016-03-10 09:04:07 +0530367 AC_VERB_SET_HDMI_DIP_DATA, buffer[i]);
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530368 } else {
369 for (i = 0; i < sizeof(dp_ai); i++)
Jeeja KPab1eea12017-01-24 21:49:05 +0530370 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530371 AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
372 }
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530373
374 /* Start infoframe */
Jeeja KPab1eea12017-01-24 21:49:05 +0530375 hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0);
376 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530377 AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST);
378
379 return 0;
380}
381
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530382static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
383 unsigned int tx_mask, unsigned int rx_mask,
384 int slots, int slot_width)
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530385{
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530386 struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai);
387 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530388 struct hdac_hdmi_dai_port_map *dai_map;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530389 struct hdac_hdmi_pcm *pcm;
390
391 dev_dbg(&edev->hdac.dev, "%s: strm_tag: %d\n", __func__, tx_mask);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530392
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530393 dai_map = &hdmi->dai_map[dai->id];
394
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530395 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530396
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530397 if (pcm)
398 pcm->stream_tag = (tx_mask << 4);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530399
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530400 return 0;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530401}
402
403static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
404 struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai)
405{
406 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530407 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530408 struct hdac_hdmi_dai_port_map *dai_map;
409 struct hdac_hdmi_port *port;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530410 struct hdac_hdmi_pcm *pcm;
411 int format;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530412
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530413 dai_map = &hdmi->dai_map[dai->id];
Jeeja KP754695f2017-02-06 12:09:14 +0530414 port = dai_map->port;
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530415
Jeeja KP754695f2017-02-06 12:09:14 +0530416 if (!port)
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530417 return -ENODEV;
418
Jeeja KP754695f2017-02-06 12:09:14 +0530419 if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) {
420 dev_err(&hdac->hdac.dev,
421 "device is not configured for this pin:port%d:%d\n",
422 port->pin->nid, port->id);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530423 return -ENODEV;
424 }
425
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530426 format = snd_hdac_calc_stream_format(params_rate(hparams),
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530427 params_channels(hparams), params_format(hparams),
428 24, 0);
429
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530430 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
431 if (!pcm)
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530432 return -EIO;
433
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530434 pcm->format = format;
435 pcm->channels = params_channels(hparams);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530436
437 return 0;
438}
439
Jeeja KP754695f2017-02-06 12:09:14 +0530440static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *hdac,
441 struct hdac_hdmi_pin *pin,
442 struct hdac_hdmi_port *port)
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530443{
444 if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
445 dev_warn(&hdac->hdac.dev,
446 "HDMI: pin %d wcaps %#x does not support connection list\n",
447 pin->nid, get_wcaps(&hdac->hdac, pin->nid));
448 return -EINVAL;
449 }
450
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530451 if (hdac_hdmi_port_select_set(hdac, port) < 0)
452 return -EIO;
453
Jeeja KP754695f2017-02-06 12:09:14 +0530454 port->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
455 port->mux_nids, HDA_MAX_CONNECTIONS);
456 if (port->num_mux_nids == 0)
457 dev_warn(&hdac->hdac.dev,
458 "No connections found for pin:port %d:%d\n",
459 pin->nid, port->id);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530460
Jeeja KP754695f2017-02-06 12:09:14 +0530461 dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin:port %d:%d\n",
462 port->num_mux_nids, pin->nid, port->id);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530463
Jeeja KP754695f2017-02-06 12:09:14 +0530464 return port->num_mux_nids;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530465}
466
467/*
Jeeja KP754695f2017-02-06 12:09:14 +0530468 * Query pcm list and return port to which stream is routed.
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530469 *
Jeeja KP754695f2017-02-06 12:09:14 +0530470 * Also query connection list of the pin, to validate the cvt to port map.
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530471 *
Jeeja KP754695f2017-02-06 12:09:14 +0530472 * Same stream rendering to multiple ports simultaneously can be done
473 * possibly, but not supported for now in driver. So return the first port
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530474 * connected.
475 */
Jeeja KP754695f2017-02-06 12:09:14 +0530476static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530477 struct hdac_ext_device *edev,
478 struct hdac_hdmi_priv *hdmi,
479 struct hdac_hdmi_cvt *cvt)
480{
481 struct hdac_hdmi_pcm *pcm;
Jeeja KP754695f2017-02-06 12:09:14 +0530482 struct hdac_hdmi_port *port = NULL;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530483 int ret, i;
484
485 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
486 if (pcm->cvt == cvt) {
Jeeja KP754695f2017-02-06 12:09:14 +0530487 port = pcm->port;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530488 break;
489 }
490 }
491
Jeeja KP754695f2017-02-06 12:09:14 +0530492 if (port) {
493 ret = hdac_hdmi_query_port_connlist(edev, port->pin, port);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530494 if (ret < 0)
495 return NULL;
496
Jeeja KP754695f2017-02-06 12:09:14 +0530497 for (i = 0; i < port->num_mux_nids; i++) {
498 if (port->mux_nids[i] == cvt->nid)
499 return port;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530500 }
501 }
502
503 return NULL;
504}
505
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530506/*
507 * This tries to get a valid pin and set the HW constraints based on the
508 * ELD. Even if a valid pin is not found return success so that device open
509 * doesn't fail.
510 */
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530511static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
512 struct snd_soc_dai *dai)
513{
514 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
515 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530516 struct hdac_hdmi_dai_port_map *dai_map;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530517 struct hdac_hdmi_cvt *cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530518 struct hdac_hdmi_port *port;
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530519 int ret;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530520
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530521 dai_map = &hdmi->dai_map[dai->id];
522
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530523 cvt = dai_map->cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530524 port = hdac_hdmi_get_port_from_cvt(hdac, hdmi, cvt);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530525
526 /*
527 * To make PA and other userland happy.
528 * userland scans devices so returning error does not help.
529 */
Jeeja KP754695f2017-02-06 12:09:14 +0530530 if (!port)
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530531 return 0;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530532
Jeeja KP754695f2017-02-06 12:09:14 +0530533 if ((!port->eld.monitor_present) ||
534 (!port->eld.eld_valid)) {
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530535
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530536 dev_warn(&hdac->hdac.dev,
Jeeja KP754695f2017-02-06 12:09:14 +0530537 "Failed: present?:%d ELD valid?:%d pin:port: %d:%d\n",
538 port->eld.monitor_present, port->eld.eld_valid,
539 port->pin->nid, port->id);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +0530540
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530541 return 0;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530542 }
543
Jeeja KP754695f2017-02-06 12:09:14 +0530544 dai_map->port = port;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530545
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530546 ret = hdac_hdmi_eld_limit_formats(substream->runtime,
Jeeja KP754695f2017-02-06 12:09:14 +0530547 port->eld.eld_buffer);
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530548 if (ret < 0)
549 return ret;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530550
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530551 return snd_pcm_hw_constraint_eld(substream->runtime,
Jeeja KP754695f2017-02-06 12:09:14 +0530552 port->eld.eld_buffer);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530553}
554
555static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
556 struct snd_soc_dai *dai)
557{
558 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
559 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530560 struct hdac_hdmi_dai_port_map *dai_map;
Jeeja KPab1eea12017-01-24 21:49:05 +0530561 struct hdac_hdmi_pcm *pcm;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530562
563 dai_map = &hdmi->dai_map[dai->id];
564
Jeeja KPab1eea12017-01-24 21:49:05 +0530565 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530566
Jeeja KPab1eea12017-01-24 21:49:05 +0530567 if (pcm) {
568 mutex_lock(&pcm->lock);
569 pcm->chmap_set = false;
570 memset(pcm->chmap, 0, sizeof(pcm->chmap));
571 pcm->channels = 0;
572 mutex_unlock(&pcm->lock);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530573 }
Jeeja KPab1eea12017-01-24 21:49:05 +0530574
Jeeja KP754695f2017-02-06 12:09:14 +0530575 if (dai_map->port)
576 dai_map->port = NULL;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530577}
578
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530579static int
580hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
581{
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530582 unsigned int chans;
583 struct hdac_ext_device *edev = to_ehdac_device(hdac);
584 struct hdac_hdmi_priv *hdmi = edev->private_data;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530585 int err;
586
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530587 chans = get_wcaps(hdac, cvt->nid);
588 chans = get_wcaps_channels(chans);
589
590 cvt->params.channels_min = 2;
591
592 cvt->params.channels_max = chans;
593 if (chans > hdmi->chmap.channels_max)
594 hdmi->chmap.channels_max = chans;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530595
596 err = snd_hdac_query_supported_pcm(hdac, cvt->nid,
597 &cvt->params.rates,
598 &cvt->params.formats,
599 &cvt->params.maxbps);
600 if (err < 0)
601 dev_err(&hdac->dev,
602 "Failed to query pcm params for nid %d: %d\n",
603 cvt->nid, err);
604
605 return err;
606}
607
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530608static int hdac_hdmi_fill_widget_info(struct device *dev,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530609 struct snd_soc_dapm_widget *w, enum snd_soc_dapm_type id,
610 void *priv, const char *wname, const char *stream,
611 struct snd_kcontrol_new *wc, int numkc,
612 int (*event)(struct snd_soc_dapm_widget *,
613 struct snd_kcontrol *, int), unsigned short event_flags)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530614{
615 w->id = id;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530616 w->name = devm_kstrdup(dev, wname, GFP_KERNEL);
617 if (!w->name)
618 return -ENOMEM;
619
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530620 w->sname = stream;
621 w->reg = SND_SOC_NOPM;
622 w->shift = 0;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530623 w->kcontrol_news = wc;
624 w->num_kcontrols = numkc;
625 w->priv = priv;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530626 w->event = event;
627 w->event_flags = event_flags;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530628
629 return 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530630}
631
632static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530633 const char *sink, const char *control, const char *src,
634 int (*handler)(struct snd_soc_dapm_widget *src,
635 struct snd_soc_dapm_widget *sink))
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530636{
637 route->sink = sink;
638 route->source = src;
639 route->control = control;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530640 route->connected = handler;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530641}
642
Jeeja KP4a3478d2016-02-12 07:46:06 +0530643static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev,
Jeeja KP754695f2017-02-06 12:09:14 +0530644 struct hdac_hdmi_port *port)
Jeeja KP4a3478d2016-02-12 07:46:06 +0530645{
646 struct hdac_hdmi_priv *hdmi = edev->private_data;
647 struct hdac_hdmi_pcm *pcm = NULL;
648
649 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +0530650 if (!pcm->port)
651 continue;
652
653 if (pcm->port == port)
Jeeja KP4a3478d2016-02-12 07:46:06 +0530654 return pcm;
655 }
656
657 return NULL;
658}
659
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530660static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
661 hda_nid_t nid, unsigned int pwr_state)
662{
663 if (get_wcaps(&edev->hdac, nid) & AC_WCAP_POWER) {
664 if (!snd_hdac_check_power_state(&edev->hdac, nid, pwr_state))
665 snd_hdac_codec_write(&edev->hdac, nid, 0,
666 AC_VERB_SET_POWER_STATE, pwr_state);
667 }
668}
669
670static void hdac_hdmi_set_amp(struct hdac_ext_device *edev,
671 hda_nid_t nid, int val)
672{
673 if (get_wcaps(&edev->hdac, nid) & AC_WCAP_OUT_AMP)
674 snd_hdac_codec_write(&edev->hdac, nid, 0,
675 AC_VERB_SET_AMP_GAIN_MUTE, val);
676}
677
678
679static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w,
680 struct snd_kcontrol *kc, int event)
681{
Jeeja KP754695f2017-02-06 12:09:14 +0530682 struct hdac_hdmi_port *port = w->priv;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530683 struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev);
684 struct hdac_hdmi_pcm *pcm;
685
686 dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n",
687 __func__, w->name, event);
688
Jeeja KP754695f2017-02-06 12:09:14 +0530689 pcm = hdac_hdmi_get_pcm(edev, port);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530690 if (!pcm)
691 return -EIO;
692
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530693 /* set the device if pin is mst_capable */
694 if (hdac_hdmi_port_select_set(edev, port) < 0)
695 return -EIO;
696
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530697 switch (event) {
698 case SND_SOC_DAPM_PRE_PMU:
Jeeja KP754695f2017-02-06 12:09:14 +0530699 hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D0);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530700
701 /* Enable out path for this pin widget */
Jeeja KP754695f2017-02-06 12:09:14 +0530702 snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530703 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
704
Jeeja KP754695f2017-02-06 12:09:14 +0530705 hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_UNMUTE);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530706
Jeeja KP754695f2017-02-06 12:09:14 +0530707 return hdac_hdmi_setup_audio_infoframe(edev, pcm, port);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530708
709 case SND_SOC_DAPM_POST_PMD:
Jeeja KP754695f2017-02-06 12:09:14 +0530710 hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_MUTE);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530711
712 /* Disable out path for this pin widget */
Jeeja KP754695f2017-02-06 12:09:14 +0530713 snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530714 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
715
Jeeja KP754695f2017-02-06 12:09:14 +0530716 hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D3);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530717 break;
718
719 }
720
721 return 0;
722}
723
724static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w,
725 struct snd_kcontrol *kc, int event)
726{
727 struct hdac_hdmi_cvt *cvt = w->priv;
728 struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev);
729 struct hdac_hdmi_priv *hdmi = edev->private_data;
730 struct hdac_hdmi_pcm *pcm;
731
732 dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n",
733 __func__, w->name, event);
734
735 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, cvt);
736 if (!pcm)
737 return -EIO;
738
739 switch (event) {
740 case SND_SOC_DAPM_PRE_PMU:
741 hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D0);
742
743 /* Enable transmission */
744 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
745 AC_VERB_SET_DIGI_CONVERT_1, 1);
746
747 /* Category Code (CC) to zero */
748 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
749 AC_VERB_SET_DIGI_CONVERT_2, 0);
750
751 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
752 AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag);
753 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
754 AC_VERB_SET_STREAM_FORMAT, pcm->format);
755 break;
756
757 case SND_SOC_DAPM_POST_PMD:
758 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
759 AC_VERB_SET_CHANNEL_STREAMID, 0);
760 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
761 AC_VERB_SET_STREAM_FORMAT, 0);
762
763 hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D3);
764 break;
765
766 }
767
768 return 0;
769}
770
771static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w,
772 struct snd_kcontrol *kc, int event)
773{
Jeeja KP754695f2017-02-06 12:09:14 +0530774 struct hdac_hdmi_port *port = w->priv;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530775 struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev);
776 int mux_idx;
777
778 dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n",
779 __func__, w->name, event);
780
781 if (!kc)
782 kc = w->kcontrols[0];
783
784 mux_idx = dapm_kcontrol_get_value(kc);
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530785
786 /* set the device if pin is mst_capable */
787 if (hdac_hdmi_port_select_set(edev, port) < 0)
788 return -EIO;
789
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530790 if (mux_idx > 0) {
Jeeja KP754695f2017-02-06 12:09:14 +0530791 snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530792 AC_VERB_SET_CONNECT_SEL, (mux_idx - 1));
793 }
794
795 return 0;
796}
797
Jeeja KP4a3478d2016-02-12 07:46:06 +0530798/*
799 * Based on user selection, map the PINs with the PCMs.
800 */
Jeeja KP754695f2017-02-06 12:09:14 +0530801static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
Jeeja KP4a3478d2016-02-12 07:46:06 +0530802 struct snd_ctl_elem_value *ucontrol)
803{
804 int ret;
805 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
806 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
807 struct snd_soc_dapm_context *dapm = w->dapm;
Jeeja KP754695f2017-02-06 12:09:14 +0530808 struct hdac_hdmi_port *port = w->priv;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530809 struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev);
810 struct hdac_hdmi_priv *hdmi = edev->private_data;
811 struct hdac_hdmi_pcm *pcm = NULL;
812 const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]];
813
814 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
815 if (ret < 0)
816 return ret;
817
Jeeja KP754695f2017-02-06 12:09:14 +0530818 if (port == NULL)
819 return -EINVAL;
820
Jeeja KP4a3478d2016-02-12 07:46:06 +0530821 mutex_lock(&hdmi->pin_mutex);
822 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +0530823 if (!pcm->port && pcm->port == port &&
824 pcm->port->id == port->id)
825 pcm->port = NULL;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530826
827 /*
828 * Jack status is not reported during device probe as the
829 * PCMs are not registered by then. So report it here.
830 */
Jeeja KP754695f2017-02-06 12:09:14 +0530831 if (!strcmp(cvt_name, pcm->cvt->name) && !pcm->port) {
832 pcm->port = port;
833 if (port->eld.monitor_present && port->eld.eld_valid) {
Jeeja KP4a3478d2016-02-12 07:46:06 +0530834 dev_dbg(&edev->hdac.dev,
835 "jack report for pcm=%d\n",
836 pcm->pcm_id);
837
838 snd_jack_report(pcm->jack, SND_JACK_AVOUT);
839 }
840 mutex_unlock(&hdmi->pin_mutex);
841 return ret;
842 }
843 }
844 mutex_unlock(&hdmi->pin_mutex);
845
846 return ret;
847}
848
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530849/*
850 * Ideally the Mux inputs should be based on the num_muxs enumerated, but
851 * the display driver seem to be programming the connection list for the pin
852 * widget runtime.
853 *
854 * So programming all the possible inputs for the mux, the user has to take
855 * care of selecting the right one and leaving all other inputs selected to
856 * "NONE"
857 */
Jeeja KP754695f2017-02-06 12:09:14 +0530858static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev,
859 struct hdac_hdmi_port *port,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530860 struct snd_soc_dapm_widget *widget,
861 const char *widget_name)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530862{
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530863 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530864 struct hdac_hdmi_pin *pin = port->pin;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530865 struct snd_kcontrol_new *kc;
866 struct hdac_hdmi_cvt *cvt;
867 struct soc_enum *se;
868 char kc_name[NAME_SIZE];
869 char mux_items[NAME_SIZE];
870 /* To hold inputs to the Pin mux */
871 char *items[HDA_MAX_CONNECTIONS];
872 int i = 0;
873 int num_items = hdmi->num_cvt + 1;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530874
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530875 kc = devm_kzalloc(&edev->hdac.dev, sizeof(*kc), GFP_KERNEL);
876 if (!kc)
877 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530878
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530879 se = devm_kzalloc(&edev->hdac.dev, sizeof(*se), GFP_KERNEL);
880 if (!se)
881 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530882
Jeeja KP754695f2017-02-06 12:09:14 +0530883 sprintf(kc_name, "Pin %d port %d Input", pin->nid, port->id);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530884 kc->name = devm_kstrdup(&edev->hdac.dev, kc_name, GFP_KERNEL);
885 if (!kc->name)
886 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530887
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530888 kc->private_value = (long)se;
889 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
890 kc->access = 0;
891 kc->info = snd_soc_info_enum_double;
Jeeja KP754695f2017-02-06 12:09:14 +0530892 kc->put = hdac_hdmi_set_pin_port_mux;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530893 kc->get = snd_soc_dapm_get_enum_double;
894
895 se->reg = SND_SOC_NOPM;
896
897 /* enum texts: ["NONE", "cvt #", "cvt #", ...] */
898 se->items = num_items;
899 se->mask = roundup_pow_of_two(se->items) - 1;
900
901 sprintf(mux_items, "NONE");
902 items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL);
903 if (!items[i])
904 return -ENOMEM;
905
906 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
907 i++;
908 sprintf(mux_items, "cvt %d", cvt->nid);
909 items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL);
910 if (!items[i])
911 return -ENOMEM;
912 }
913
914 se->texts = devm_kmemdup(&edev->hdac.dev, items,
915 (num_items * sizeof(char *)), GFP_KERNEL);
916 if (!se->texts)
917 return -ENOMEM;
918
919 return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget,
Jeeja KP754695f2017-02-06 12:09:14 +0530920 snd_soc_dapm_mux, port, widget_name, NULL, kc, 1,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530921 hdac_hdmi_pin_mux_widget_event,
922 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_REG);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530923}
924
925/* Add cvt <- input <- mux route map */
926static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev,
927 struct snd_soc_dapm_widget *widgets,
928 struct snd_soc_dapm_route *route, int rindex)
929{
930 struct hdac_hdmi_priv *hdmi = edev->private_data;
931 const struct snd_kcontrol_new *kc;
932 struct soc_enum *se;
Jeeja KP754695f2017-02-06 12:09:14 +0530933 int mux_index = hdmi->num_cvt + hdmi->num_ports;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530934 int i, j;
935
Jeeja KP754695f2017-02-06 12:09:14 +0530936 for (i = 0; i < hdmi->num_ports; i++) {
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530937 kc = widgets[mux_index].kcontrol_news;
938 se = (struct soc_enum *)kc->private_value;
939 for (j = 0; j < hdmi->num_cvt; j++) {
940 hdac_hdmi_fill_route(&route[rindex],
941 widgets[mux_index].name,
942 se->texts[j + 1],
943 widgets[j].name, NULL);
944
945 rindex++;
946 }
947
948 mux_index++;
949 }
950}
951
952/*
953 * Widgets are added in the below sequence
954 * Converter widgets for num converters enumerated
Jeeja KP754695f2017-02-06 12:09:14 +0530955 * Pin-port widgets for num ports for Pins enumerated
956 * Pin-port mux widgets to represent connenction list of pin widget
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530957 *
Jeeja KP754695f2017-02-06 12:09:14 +0530958 * For each port, one Mux and One output widget is added
959 * Total widgets elements = num_cvt + (num_ports * 2);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530960 *
961 * Routes are added as below:
Jeeja KP754695f2017-02-06 12:09:14 +0530962 * pin-port mux -> pin (based on num_ports)
963 * cvt -> "Input sel control" -> pin-port_mux
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530964 *
965 * Total route elements:
Jeeja KP754695f2017-02-06 12:09:14 +0530966 * num_ports + (pin_muxes * num_cvt)
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530967 */
968static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
969{
970 struct snd_soc_dapm_widget *widgets;
971 struct snd_soc_dapm_route *route;
972 struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev);
973 struct hdac_hdmi_priv *hdmi = edev->private_data;
974 struct snd_soc_dai_driver *dai_drv = dapm->component->dai_drv;
975 char widget_name[NAME_SIZE];
976 struct hdac_hdmi_cvt *cvt;
977 struct hdac_hdmi_pin *pin;
Jeeja KP754695f2017-02-06 12:09:14 +0530978 int ret, i = 0, num_routes = 0, j;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530979
980 if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
981 return -EINVAL;
982
Jeeja KP754695f2017-02-06 12:09:14 +0530983 widgets = devm_kzalloc(dapm->dev, (sizeof(*widgets) *
984 ((2 * hdmi->num_ports) + hdmi->num_cvt)),
985 GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530986
987 if (!widgets)
988 return -ENOMEM;
989
990 /* DAPM widgets to represent each converter widget */
991 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
992 sprintf(widget_name, "Converter %d", cvt->nid);
993 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530994 snd_soc_dapm_aif_in, cvt,
995 widget_name, dai_drv[i].playback.stream_name, NULL, 0,
996 hdac_hdmi_cvt_output_widget_event,
997 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530998 if (ret < 0)
999 return ret;
1000 i++;
1001 }
1002
1003 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301004 for (j = 0; j < pin->num_ports; j++) {
1005 sprintf(widget_name, "hif%d-%d Output",
1006 pin->nid, pin->ports[j].id);
1007 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
1008 snd_soc_dapm_output, &pin->ports[j],
1009 widget_name, NULL, NULL, 0,
1010 hdac_hdmi_pin_output_widget_event,
1011 SND_SOC_DAPM_PRE_PMU |
1012 SND_SOC_DAPM_POST_PMD);
1013 if (ret < 0)
1014 return ret;
1015 i++;
1016 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301017 }
1018
1019 /* DAPM widgets to represent the connection list to pin widget */
1020 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301021 for (j = 0; j < pin->num_ports; j++) {
1022 sprintf(widget_name, "Pin%d-Port%d Mux",
1023 pin->nid, pin->ports[j].id);
1024 ret = hdac_hdmi_create_pin_port_muxs(edev,
1025 &pin->ports[j], &widgets[i],
1026 widget_name);
1027 if (ret < 0)
1028 return ret;
1029 i++;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301030
Jeeja KP754695f2017-02-06 12:09:14 +05301031 /* For cvt to pin_mux mapping */
1032 num_routes += hdmi->num_cvt;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301033
Jeeja KP754695f2017-02-06 12:09:14 +05301034 /* For pin_mux to pin mapping */
1035 num_routes++;
1036 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301037 }
1038
1039 route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes),
1040 GFP_KERNEL);
1041 if (!route)
1042 return -ENOMEM;
1043
1044 i = 0;
1045 /* Add pin <- NULL <- mux route map */
1046 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301047 for (j = 0; j < pin->num_ports; j++) {
1048 int sink_index = i + hdmi->num_cvt;
1049 int src_index = sink_index + pin->num_ports *
1050 hdmi->num_pin;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301051
Jeeja KP754695f2017-02-06 12:09:14 +05301052 hdac_hdmi_fill_route(&route[i],
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301053 widgets[sink_index].name, NULL,
1054 widgets[src_index].name, NULL);
Jeeja KP754695f2017-02-06 12:09:14 +05301055 i++;
1056 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301057 }
1058
1059 hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i);
1060
1061 snd_soc_dapm_new_controls(dapm, widgets,
Jeeja KP754695f2017-02-06 12:09:14 +05301062 ((2 * hdmi->num_ports) + hdmi->num_cvt));
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301063
1064 snd_soc_dapm_add_routes(dapm, route, num_routes);
1065 snd_soc_dapm_new_widgets(dapm->card);
1066
1067 return 0;
1068
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301069}
1070
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301071static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301072{
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301073 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +05301074 struct hdac_hdmi_dai_port_map *dai_map;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301075 struct hdac_hdmi_cvt *cvt;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301076 int dai_id = 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301077
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301078 if (list_empty(&hdmi->cvt_list))
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301079 return -EINVAL;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301080
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301081 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
1082 dai_map = &hdmi->dai_map[dai_id];
1083 dai_map->dai_id = dai_id;
1084 dai_map->cvt = cvt;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301085
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301086 dai_id++;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301087
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301088 if (dai_id == HDA_MAX_CVTS) {
1089 dev_warn(&edev->hdac.dev,
1090 "Max dais supported: %d\n", dai_id);
1091 break;
1092 }
1093 }
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301094
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301095 return 0;
1096}
1097
1098static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
1099{
1100 struct hdac_hdmi_priv *hdmi = edev->private_data;
1101 struct hdac_hdmi_cvt *cvt;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301102 char name[NAME_SIZE];
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301103
1104 cvt = kzalloc(sizeof(*cvt), GFP_KERNEL);
1105 if (!cvt)
1106 return -ENOMEM;
1107
1108 cvt->nid = nid;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301109 sprintf(name, "cvt %d", cvt->nid);
1110 cvt->name = kstrdup(name, GFP_KERNEL);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301111
1112 list_add_tail(&cvt->head, &hdmi->cvt_list);
1113 hdmi->num_cvt++;
1114
1115 return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
1116}
1117
Jeeja KP754695f2017-02-06 12:09:14 +05301118static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
1119 struct hdac_hdmi_port *port)
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +05301120{
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301121 unsigned int ver, mnl;
1122
Jeeja KP754695f2017-02-06 12:09:14 +05301123 ver = (port->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301124 >> DRM_ELD_VER_SHIFT;
1125
1126 if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
1127 dev_err(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver);
1128 return -EINVAL;
1129 }
1130
Jeeja KP754695f2017-02-06 12:09:14 +05301131 mnl = (port->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301132 DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
1133
1134 if (mnl > ELD_MAX_MNL) {
1135 dev_err(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl);
1136 return -EINVAL;
1137 }
1138
Jeeja KP754695f2017-02-06 12:09:14 +05301139 port->eld.info.spk_alloc = port->eld.eld_buffer[DRM_ELD_SPEAKER];
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301140
1141 return 0;
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +05301142}
1143
Jeeja KP754695f2017-02-06 12:09:14 +05301144static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
1145 struct hdac_hdmi_port *port)
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301146{
1147 struct hdac_ext_device *edev = pin->edev;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301148 struct hdac_hdmi_priv *hdmi = edev->private_data;
1149 struct hdac_hdmi_pcm *pcm;
Jeeja KP754695f2017-02-06 12:09:14 +05301150 int size = 0;
Jeeja KP2acd8302017-02-06 12:09:18 +05301151 int port_id = -1;
Jeeja KP754695f2017-02-06 12:09:14 +05301152
1153 if (!hdmi)
1154 return;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301155
Jeeja KP2acd8302017-02-06 12:09:18 +05301156 /*
1157 * In case of non MST pin, get_eld info API expectes port
1158 * to be -1.
1159 */
Jeeja KP4a3478d2016-02-12 07:46:06 +05301160 mutex_lock(&hdmi->pin_mutex);
Jeeja KP754695f2017-02-06 12:09:14 +05301161 port->eld.monitor_present = false;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301162
Jeeja KP2acd8302017-02-06 12:09:18 +05301163 if (pin->mst_capable)
1164 port_id = port->id;
1165
1166 size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, port_id,
Jeeja KP754695f2017-02-06 12:09:14 +05301167 &port->eld.monitor_present,
1168 port->eld.eld_buffer,
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301169 ELD_MAX_SIZE);
1170
1171 if (size > 0) {
1172 size = min(size, ELD_MAX_SIZE);
Jeeja KP754695f2017-02-06 12:09:14 +05301173 if (hdac_hdmi_parse_eld(edev, port) < 0)
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301174 size = -EINVAL;
1175 }
1176
1177 if (size > 0) {
Jeeja KP754695f2017-02-06 12:09:14 +05301178 port->eld.eld_valid = true;
1179 port->eld.eld_size = size;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301180 } else {
Jeeja KP754695f2017-02-06 12:09:14 +05301181 port->eld.eld_valid = false;
1182 port->eld.eld_size = 0;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301183 }
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301184
Jeeja KP754695f2017-02-06 12:09:14 +05301185 pcm = hdac_hdmi_get_pcm(edev, port);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301186
Jeeja KP754695f2017-02-06 12:09:14 +05301187 if (!port->eld.monitor_present || !port->eld.eld_valid) {
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301188
Jeeja KP754695f2017-02-06 12:09:14 +05301189 dev_dbg(&edev->hdac.dev, "%s: disconnect for pin:port %d:%d\n",
1190 __func__, pin->nid, port->id);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301191
1192 /*
1193 * PCMs are not registered during device probe, so don't
1194 * report jack here. It will be done in usermode mux
1195 * control select.
1196 */
1197 if (pcm) {
1198 dev_dbg(&edev->hdac.dev,
1199 "jack report for pcm=%d\n", pcm->pcm_id);
1200
1201 snd_jack_report(pcm->jack, 0);
1202 }
1203
1204 mutex_unlock(&hdmi->pin_mutex);
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301205 return;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301206 }
1207
Jeeja KP754695f2017-02-06 12:09:14 +05301208 if (port->eld.monitor_present && port->eld.eld_valid) {
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301209 if (pcm) {
1210 dev_dbg(&edev->hdac.dev,
1211 "jack report for pcm=%d\n",
1212 pcm->pcm_id);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301213
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301214 snd_jack_report(pcm->jack, SND_JACK_AVOUT);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301215 }
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301216
1217 print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
Jeeja KP754695f2017-02-06 12:09:14 +05301218 port->eld.eld_buffer, port->eld.eld_size, false);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301219
Jeeja KP754695f2017-02-06 12:09:14 +05301220 }
Jeeja KP4a3478d2016-02-12 07:46:06 +05301221 mutex_unlock(&hdmi->pin_mutex);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301222}
1223
Jeeja KP754695f2017-02-06 12:09:14 +05301224static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi,
1225 struct hdac_hdmi_pin *pin)
1226{
1227 struct hdac_hdmi_port *ports;
1228 int max_ports = HDA_MAX_PORTS;
1229 int i;
1230
1231 /*
1232 * FIXME: max_port may vary for each platform, so pass this as
1233 * as driver data or query from i915 interface when this API is
1234 * implemented.
1235 */
1236
1237 ports = kcalloc(max_ports, sizeof(*ports), GFP_KERNEL);
1238 if (!ports)
1239 return -ENOMEM;
1240
1241 for (i = 0; i < max_ports; i++) {
1242 ports[i].id = i;
1243 ports[i].pin = pin;
1244 }
1245 pin->ports = ports;
1246 pin->num_ports = max_ports;
1247 return 0;
1248}
1249
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301250static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
1251{
1252 struct hdac_hdmi_priv *hdmi = edev->private_data;
1253 struct hdac_hdmi_pin *pin;
Jeeja KP754695f2017-02-06 12:09:14 +05301254 int ret;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301255
1256 pin = kzalloc(sizeof(*pin), GFP_KERNEL);
1257 if (!pin)
1258 return -ENOMEM;
1259
1260 pin->nid = nid;
Jeeja KP2acd8302017-02-06 12:09:18 +05301261 pin->mst_capable = false;
Jeeja KP754695f2017-02-06 12:09:14 +05301262 pin->edev = edev;
1263 ret = hdac_hdmi_add_ports(hdmi, pin);
1264 if (ret < 0)
1265 return ret;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301266
1267 list_add_tail(&pin->head, &hdmi->pin_list);
1268 hdmi->num_pin++;
Jeeja KP754695f2017-02-06 12:09:14 +05301269 hdmi->num_ports += pin->num_ports;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301270
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301271 return 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301272}
1273
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301274#define INTEL_VENDOR_NID 0x08
1275#define INTEL_GET_VENDOR_VERB 0xf81
1276#define INTEL_SET_VENDOR_VERB 0x781
1277#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
1278#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
1279
1280static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac)
1281{
1282 unsigned int vendor_param;
1283
1284 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1285 INTEL_GET_VENDOR_VERB, 0);
1286 if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
1287 return;
1288
1289 vendor_param |= INTEL_EN_ALL_PIN_CVTS;
1290 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1291 INTEL_SET_VENDOR_VERB, vendor_param);
1292 if (vendor_param == -1)
1293 return;
1294}
1295
1296static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
1297{
1298 unsigned int vendor_param;
1299
1300 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1301 INTEL_GET_VENDOR_VERB, 0);
1302 if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
1303 return;
1304
1305 /* enable DP1.2 mode */
1306 vendor_param |= INTEL_EN_DP12;
1307 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1308 INTEL_SET_VENDOR_VERB, vendor_param);
1309 if (vendor_param == -1)
1310 return;
1311
1312}
1313
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301314static struct snd_soc_dai_ops hdmi_dai_ops = {
1315 .startup = hdac_hdmi_pcm_open,
1316 .shutdown = hdac_hdmi_pcm_close,
1317 .hw_params = hdac_hdmi_set_hw_params,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +05301318 .set_tdm_slot = hdac_hdmi_set_tdm_slot,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301319};
1320
1321/*
1322 * Each converter can support a stream independently. So a dai is created
1323 * based on the number of converter queried.
1324 */
1325static int hdac_hdmi_create_dais(struct hdac_device *hdac,
1326 struct snd_soc_dai_driver **dais,
1327 struct hdac_hdmi_priv *hdmi, int num_dais)
1328{
1329 struct snd_soc_dai_driver *hdmi_dais;
1330 struct hdac_hdmi_cvt *cvt;
1331 char name[NAME_SIZE], dai_name[NAME_SIZE];
1332 int i = 0;
1333 u32 rates, bps;
1334 unsigned int rate_max = 384000, rate_min = 8000;
1335 u64 formats;
1336 int ret;
1337
1338 hdmi_dais = devm_kzalloc(&hdac->dev,
1339 (sizeof(*hdmi_dais) * num_dais),
1340 GFP_KERNEL);
1341 if (!hdmi_dais)
1342 return -ENOMEM;
1343
1344 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
1345 ret = snd_hdac_query_supported_pcm(hdac, cvt->nid,
1346 &rates, &formats, &bps);
1347 if (ret)
1348 return ret;
1349
1350 sprintf(dai_name, "intel-hdmi-hifi%d", i+1);
1351 hdmi_dais[i].name = devm_kstrdup(&hdac->dev,
1352 dai_name, GFP_KERNEL);
1353
1354 if (!hdmi_dais[i].name)
1355 return -ENOMEM;
1356
1357 snprintf(name, sizeof(name), "hifi%d", i+1);
1358 hdmi_dais[i].playback.stream_name =
1359 devm_kstrdup(&hdac->dev, name, GFP_KERNEL);
1360 if (!hdmi_dais[i].playback.stream_name)
1361 return -ENOMEM;
1362
1363 /*
1364 * Set caps based on capability queried from the converter.
1365 * It will be constrained runtime based on ELD queried.
1366 */
1367 hdmi_dais[i].playback.formats = formats;
1368 hdmi_dais[i].playback.rates = rates;
1369 hdmi_dais[i].playback.rate_max = rate_max;
1370 hdmi_dais[i].playback.rate_min = rate_min;
1371 hdmi_dais[i].playback.channels_min = 2;
1372 hdmi_dais[i].playback.channels_max = 2;
1373 hdmi_dais[i].ops = &hdmi_dai_ops;
1374
1375 i++;
1376 }
1377
1378 *dais = hdmi_dais;
1379
1380 return 0;
1381}
1382
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301383/*
1384 * Parse all nodes and store the cvt/pin nids in array
1385 * Add one time initialization for pin and cvt widgets
1386 */
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301387static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
1388 struct snd_soc_dai_driver **dais, int *num_dais)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301389{
1390 hda_nid_t nid;
Sudip Mukherjee3c83ac22015-12-01 14:29:35 +05301391 int i, num_nodes;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301392 struct hdac_device *hdac = &edev->hdac;
1393 struct hdac_hdmi_priv *hdmi = edev->private_data;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301394 int ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301395
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301396 hdac_hdmi_skl_enable_all_pins(hdac);
1397 hdac_hdmi_skl_enable_dp12(hdac);
1398
Sudip Mukherjee3c83ac22015-12-01 14:29:35 +05301399 num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid);
Subhransu S. Prusty541140d2015-12-09 21:46:08 +05301400 if (!nid || num_nodes <= 0) {
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301401 dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n");
1402 return -EINVAL;
1403 }
1404
Sudip Mukherjee3c83ac22015-12-01 14:29:35 +05301405 hdac->num_nodes = num_nodes;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301406 hdac->start_nid = nid;
1407
1408 for (i = 0; i < hdac->num_nodes; i++, nid++) {
1409 unsigned int caps;
1410 unsigned int type;
1411
1412 caps = get_wcaps(hdac, nid);
1413 type = get_wcaps_type(caps);
1414
1415 if (!(caps & AC_WCAP_DIGITAL))
1416 continue;
1417
1418 switch (type) {
1419
1420 case AC_WID_AUD_OUT:
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301421 ret = hdac_hdmi_add_cvt(edev, nid);
1422 if (ret < 0)
1423 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301424 break;
1425
1426 case AC_WID_PIN:
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301427 ret = hdac_hdmi_add_pin(edev, nid);
1428 if (ret < 0)
1429 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301430 break;
1431 }
1432 }
1433
1434 hdac->end_nid = nid;
1435
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301436 if (!hdmi->num_pin || !hdmi->num_cvt)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301437 return -EIO;
1438
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301439 ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt);
1440 if (ret) {
1441 dev_err(&hdac->dev, "Failed to create dais with err: %d\n",
1442 ret);
1443 return ret;
1444 }
1445
1446 *num_dais = hdmi->num_cvt;
1447
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301448 return hdac_hdmi_init_dai_map(edev);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301449}
1450
Pandiyan, Dhinakaranf9318942016-09-21 13:02:48 -07001451static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301452{
1453 struct hdac_ext_device *edev = aptr;
1454 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +05301455 struct hdac_hdmi_pin *pin = NULL;
1456 struct hdac_hdmi_port *hport = NULL;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301457 struct snd_soc_codec *codec = edev->scodec;
Jeeja KP2acd8302017-02-06 12:09:18 +05301458 int i;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301459
1460 /* Don't know how this mapping is derived */
1461 hda_nid_t pin_nid = port + 0x04;
1462
Jeeja KP754695f2017-02-06 12:09:14 +05301463 dev_dbg(&edev->hdac.dev, "%s: for pin:%d port=%d\n", __func__,
1464 pin_nid, pipe);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301465
1466 /*
1467 * skip notification during system suspend (but not in runtime PM);
1468 * the state will be updated at resume. Also since the ELD and
1469 * connection states are updated in anyway at the end of the resume,
1470 * we can skip it when received during PM process.
1471 */
1472 if (snd_power_get_state(codec->component.card->snd_card) !=
1473 SNDRV_CTL_POWER_D0)
1474 return;
1475
1476 if (atomic_read(&edev->hdac.in_pm))
1477 return;
1478
1479 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301480 if (pin->nid != pin_nid)
1481 continue;
1482
1483 /* In case of non MST pin, pipe is -1 */
1484 if (pipe == -1) {
Jeeja KP2acd8302017-02-06 12:09:18 +05301485 pin->mst_capable = false;
Jeeja KP754695f2017-02-06 12:09:14 +05301486 /* if not MST, default is port[0] */
1487 hport = &pin->ports[0];
Jeeja KP2acd8302017-02-06 12:09:18 +05301488 goto out;
1489 } else {
1490 for (i = 0; i < pin->num_ports; i++) {
1491 pin->mst_capable = true;
1492 if (pin->ports[i].id == pipe) {
1493 hport = &pin->ports[i];
1494 goto out;
1495 }
1496 }
Jeeja KP754695f2017-02-06 12:09:14 +05301497 }
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301498 }
Jeeja KP754695f2017-02-06 12:09:14 +05301499
Jeeja KP2acd8302017-02-06 12:09:18 +05301500out:
1501 if (pin && hport)
Jeeja KP754695f2017-02-06 12:09:14 +05301502 hdac_hdmi_present_sense(pin, hport);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301503}
1504
1505static struct i915_audio_component_audio_ops aops = {
1506 .pin_eld_notify = hdac_hdmi_eld_notify_cb,
1507};
1508
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301509static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card,
1510 int device)
1511{
1512 struct snd_soc_pcm_runtime *rtd;
1513
1514 list_for_each_entry(rtd, &card->rtd_list, list) {
1515 if (rtd->pcm && (rtd->pcm->device == device))
1516 return rtd->pcm;
1517 }
1518
1519 return NULL;
1520}
1521
Jeeja KP4a3478d2016-02-12 07:46:06 +05301522int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device)
1523{
1524 char jack_name[NAME_SIZE];
1525 struct snd_soc_codec *codec = dai->codec;
1526 struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
1527 struct snd_soc_dapm_context *dapm =
1528 snd_soc_component_get_dapm(&codec->component);
1529 struct hdac_hdmi_priv *hdmi = edev->private_data;
1530 struct hdac_hdmi_pcm *pcm;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301531 struct snd_pcm *snd_pcm;
1532 int err;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301533
1534 /*
1535 * this is a new PCM device, create new pcm and
1536 * add to the pcm list
1537 */
1538 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
1539 if (!pcm)
1540 return -ENOMEM;
1541 pcm->pcm_id = device;
1542 pcm->cvt = hdmi->dai_map[dai->id].cvt;
Jeeja KPab1eea12017-01-24 21:49:05 +05301543 mutex_init(&pcm->lock);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301544
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301545 snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device);
1546 if (snd_pcm) {
1547 err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap);
1548 if (err < 0) {
1549 dev_err(&edev->hdac.dev,
1550 "chmap control add failed with err: %d for pcm: %d\n",
1551 err, device);
1552 kfree(pcm);
1553 return err;
1554 }
1555 }
1556
Jeeja KP4a3478d2016-02-12 07:46:06 +05301557 list_add_tail(&pcm->head, &hdmi->pcm_list);
1558
1559 sprintf(jack_name, "HDMI/DP, pcm=%d Jack", device);
1560
1561 return snd_jack_new(dapm->card->snd_card, jack_name,
1562 SND_JACK_AVOUT, &pcm->jack, true, false);
1563}
1564EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init);
1565
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301566static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev,
1567 struct hdac_hdmi_priv *hdmi, bool detect_pin_caps)
1568{
1569 int i;
1570 struct hdac_hdmi_pin *pin;
1571
1572 list_for_each_entry(pin, &hdmi->pin_list, head) {
1573 if (detect_pin_caps) {
1574
1575 if (hdac_hdmi_get_port_len(edev, pin->nid) == 0)
1576 pin->mst_capable = false;
1577 else
1578 pin->mst_capable = true;
1579 }
1580
1581 for (i = 0; i < pin->num_ports; i++) {
1582 if (!pin->mst_capable && i > 0)
1583 continue;
1584
1585 hdac_hdmi_present_sense(pin, &pin->ports[i]);
1586 }
1587 }
1588}
1589
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301590static int hdmi_codec_probe(struct snd_soc_codec *codec)
1591{
1592 struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
1593 struct hdac_hdmi_priv *hdmi = edev->private_data;
1594 struct snd_soc_dapm_context *dapm =
1595 snd_soc_component_get_dapm(&codec->component);
Vinod Koulb2047e92016-05-12 08:58:55 +05301596 struct hdac_ext_link *hlink = NULL;
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301597 int ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301598
1599 edev->scodec = codec;
1600
Vinod Koulb2047e92016-05-12 08:58:55 +05301601 /*
1602 * hold the ref while we probe, also no need to drop the ref on
1603 * exit, we call pm_runtime_suspend() so that will do for us
1604 */
1605 hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301606 if (!hlink) {
1607 dev_err(&edev->hdac.dev, "hdac link not found\n");
1608 return -EIO;
1609 }
1610
Vinod Koulb2047e92016-05-12 08:58:55 +05301611 snd_hdac_ext_bus_link_get(edev->ebus, hlink);
1612
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301613 ret = create_fill_widget_route_map(dapm);
1614 if (ret < 0)
1615 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301616
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301617 aops.audio_ptr = edev;
1618 ret = snd_hdac_i915_register_notifier(&aops);
1619 if (ret < 0) {
1620 dev_err(&edev->hdac.dev, "notifier register failed: err: %d\n",
1621 ret);
1622 return ret;
1623 }
1624
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301625 hdac_hdmi_present_sense_all_pins(edev, hdmi, true);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301626 /* Imp: Store the card pointer in hda_codec */
1627 edev->card = dapm->card->snd_card;
1628
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301629 /*
1630 * hdac_device core already sets the state to active and calls
1631 * get_noresume. So enable runtime and set the device to suspend.
1632 */
1633 pm_runtime_enable(&edev->hdac.dev);
1634 pm_runtime_put(&edev->hdac.dev);
1635 pm_runtime_suspend(&edev->hdac.dev);
1636
1637 return 0;
1638}
1639
1640static int hdmi_codec_remove(struct snd_soc_codec *codec)
1641{
1642 struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
1643
1644 pm_runtime_disable(&edev->hdac.dev);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301645 return 0;
1646}
1647
Jeeja KP571d5072016-02-22 07:50:33 +05301648#ifdef CONFIG_PM
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301649static int hdmi_codec_prepare(struct device *dev)
1650{
1651 struct hdac_ext_device *edev = to_hda_ext_device(dev);
1652 struct hdac_device *hdac = &edev->hdac;
1653
1654 pm_runtime_get_sync(&edev->hdac.dev);
1655
1656 /*
1657 * Power down afg.
1658 * codec_read is preferred over codec_write to set the power state.
1659 * This way verb is send to set the power state and response
1660 * is received. So setting power state is ensured without using loop
1661 * to read the state.
1662 */
1663 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1664 AC_PWRST_D3);
1665
1666 return 0;
1667}
1668
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301669static void hdmi_codec_complete(struct device *dev)
Jeeja KP571d5072016-02-22 07:50:33 +05301670{
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301671 struct hdac_ext_device *edev = to_hda_ext_device(dev);
Jeeja KP571d5072016-02-22 07:50:33 +05301672 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP571d5072016-02-22 07:50:33 +05301673 struct hdac_device *hdac = &edev->hdac;
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301674
1675 /* Power up afg */
1676 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1677 AC_PWRST_D0);
Jeeja KP571d5072016-02-22 07:50:33 +05301678
1679 hdac_hdmi_skl_enable_all_pins(&edev->hdac);
1680 hdac_hdmi_skl_enable_dp12(&edev->hdac);
1681
Jeeja KP571d5072016-02-22 07:50:33 +05301682 /*
1683 * As the ELD notify callback request is not entertained while the
1684 * device is in suspend state. Need to manually check detection of
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301685 * all pins here. pin capablity change is not support, so use the
1686 * already set pin caps.
Jeeja KP571d5072016-02-22 07:50:33 +05301687 */
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301688 hdac_hdmi_present_sense_all_pins(edev, hdmi, false);
Jeeja KP571d5072016-02-22 07:50:33 +05301689
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301690 pm_runtime_put_sync(&edev->hdac.dev);
Jeeja KP571d5072016-02-22 07:50:33 +05301691}
1692#else
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301693#define hdmi_codec_prepare NULL
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301694#define hdmi_codec_complete NULL
Jeeja KP571d5072016-02-22 07:50:33 +05301695#endif
1696
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301697static struct snd_soc_codec_driver hdmi_hda_codec = {
1698 .probe = hdmi_codec_probe,
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301699 .remove = hdmi_codec_remove,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301700 .idle_bias_off = true,
1701};
1702
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301703static void hdac_hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx,
1704 unsigned char *chmap)
1705{
1706 struct hdac_ext_device *edev = to_ehdac_device(hdac);
1707 struct hdac_hdmi_priv *hdmi = edev->private_data;
1708 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301709
Jeeja KPab1eea12017-01-24 21:49:05 +05301710 memcpy(chmap, pcm->chmap, ARRAY_SIZE(pcm->chmap));
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301711}
1712
1713static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
1714 unsigned char *chmap, int prepared)
1715{
1716 struct hdac_ext_device *edev = to_ehdac_device(hdac);
1717 struct hdac_hdmi_priv *hdmi = edev->private_data;
1718 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Jeeja KP754695f2017-02-06 12:09:14 +05301719 struct hdac_hdmi_port *port = pcm->port;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301720
Jeeja KPab1eea12017-01-24 21:49:05 +05301721 mutex_lock(&pcm->lock);
1722 pcm->chmap_set = true;
1723 memcpy(pcm->chmap, chmap, ARRAY_SIZE(pcm->chmap));
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301724 if (prepared)
Jeeja KP754695f2017-02-06 12:09:14 +05301725 hdac_hdmi_setup_audio_infoframe(edev, pcm, port);
Jeeja KPab1eea12017-01-24 21:49:05 +05301726 mutex_unlock(&pcm->lock);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301727}
1728
1729static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
1730{
1731 struct hdac_ext_device *edev = to_ehdac_device(hdac);
1732 struct hdac_hdmi_priv *hdmi = edev->private_data;
1733 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Jeeja KP754695f2017-02-06 12:09:14 +05301734 struct hdac_hdmi_port *port = pcm->port;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301735
Jeeja KP754695f2017-02-06 12:09:14 +05301736 return port ? true:false;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301737}
1738
1739static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
1740{
1741 struct hdac_ext_device *edev = to_ehdac_device(hdac);
1742 struct hdac_hdmi_priv *hdmi = edev->private_data;
1743 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Jeeja KP754695f2017-02-06 12:09:14 +05301744 struct hdac_hdmi_port *port = pcm->port;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301745
Jeeja KP754695f2017-02-06 12:09:14 +05301746 if (!port || !port->eld.eld_valid)
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301747 return 0;
1748
Jeeja KP754695f2017-02-06 12:09:14 +05301749 return port->eld.info.spk_alloc;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301750}
1751
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301752static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
1753{
1754 struct hdac_device *codec = &edev->hdac;
1755 struct hdac_hdmi_priv *hdmi_priv;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301756 struct snd_soc_dai_driver *hdmi_dais = NULL;
Vinod Koulb2047e92016-05-12 08:58:55 +05301757 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301758 int num_dais = 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301759 int ret = 0;
1760
Vinod Koulb2047e92016-05-12 08:58:55 +05301761 /* hold the ref while we probe */
1762 hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301763 if (!hlink) {
1764 dev_err(&edev->hdac.dev, "hdac link not found\n");
1765 return -EIO;
1766 }
1767
Vinod Koulb2047e92016-05-12 08:58:55 +05301768 snd_hdac_ext_bus_link_get(edev->ebus, hlink);
1769
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301770 hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
1771 if (hdmi_priv == NULL)
1772 return -ENOMEM;
1773
1774 edev->private_data = hdmi_priv;
Subhransu S. Prustybcced702016-04-14 10:07:30 +05301775 snd_hdac_register_chmap_ops(codec, &hdmi_priv->chmap);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301776 hdmi_priv->chmap.ops.get_chmap = hdac_hdmi_get_chmap;
1777 hdmi_priv->chmap.ops.set_chmap = hdac_hdmi_set_chmap;
1778 hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached;
1779 hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301780
1781 dev_set_drvdata(&codec->dev, edev);
1782
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301783 INIT_LIST_HEAD(&hdmi_priv->pin_list);
1784 INIT_LIST_HEAD(&hdmi_priv->cvt_list);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301785 INIT_LIST_HEAD(&hdmi_priv->pcm_list);
1786 mutex_init(&hdmi_priv->pin_mutex);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301787
Ramesh Babuaeaccef2016-02-17 21:34:01 +05301788 /*
1789 * Turned off in the runtime_suspend during the first explicit
1790 * pm_runtime_suspend call.
1791 */
1792 ret = snd_hdac_display_power(edev->hdac.bus, true);
1793 if (ret < 0) {
1794 dev_err(&edev->hdac.dev,
1795 "Cannot turn on display power on i915 err: %d\n",
1796 ret);
1797 return ret;
1798 }
1799
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301800 ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais);
1801 if (ret < 0) {
1802 dev_err(&codec->dev,
1803 "Failed in parse and map nid with err: %d\n", ret);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301804 return ret;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301805 }
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301806
1807 /* ASoC specific initialization */
Vinod Koulb2047e92016-05-12 08:58:55 +05301808 ret = snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
1809 hdmi_dais, num_dais);
1810
1811 snd_hdac_ext_bus_link_put(edev->ebus, hlink);
1812
1813 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301814}
1815
1816static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
1817{
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301818 struct hdac_hdmi_priv *hdmi = edev->private_data;
1819 struct hdac_hdmi_pin *pin, *pin_next;
1820 struct hdac_hdmi_cvt *cvt, *cvt_next;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301821 struct hdac_hdmi_pcm *pcm, *pcm_next;
Jeeja KP754695f2017-02-06 12:09:14 +05301822 int i;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301823
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301824 snd_soc_unregister_codec(&edev->hdac.dev);
1825
Jeeja KP4a3478d2016-02-12 07:46:06 +05301826 list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) {
1827 pcm->cvt = NULL;
Jeeja KP754695f2017-02-06 12:09:14 +05301828 pcm->port = NULL;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301829 list_del(&pcm->head);
1830 kfree(pcm);
1831 }
1832
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301833 list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) {
1834 list_del(&cvt->head);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301835 kfree(cvt->name);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301836 kfree(cvt);
1837 }
1838
1839 list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301840 for (i = 0; i < pin->num_ports; i++)
1841 pin->ports[i].pin = NULL;
1842 kfree(pin->ports);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301843 list_del(&pin->head);
1844 kfree(pin);
1845 }
1846
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301847 return 0;
1848}
1849
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301850#ifdef CONFIG_PM
1851static int hdac_hdmi_runtime_suspend(struct device *dev)
1852{
1853 struct hdac_ext_device *edev = to_hda_ext_device(dev);
1854 struct hdac_device *hdac = &edev->hdac;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301855 struct hdac_bus *bus = hdac->bus;
Vinod Koulb2047e92016-05-12 08:58:55 +05301856 struct hdac_ext_bus *ebus = hbus_to_ebus(bus);
1857 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301858 int err;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301859
1860 dev_dbg(dev, "Enter: %s\n", __func__);
1861
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301862 /* controller may not have been initialized for the first time */
1863 if (!bus)
1864 return 0;
1865
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301866 /*
1867 * Power down afg.
1868 * codec_read is preferred over codec_write to set the power state.
1869 * This way verb is send to set the power state and response
1870 * is received. So setting power state is ensured without using loop
1871 * to read the state.
1872 */
1873 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1874 AC_PWRST_D3);
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301875 err = snd_hdac_display_power(bus, false);
1876 if (err < 0) {
1877 dev_err(bus->dev, "Cannot turn on display power on i915\n");
1878 return err;
1879 }
1880
Vinod Koulb2047e92016-05-12 08:58:55 +05301881 hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301882 if (!hlink) {
1883 dev_err(dev, "hdac link not found\n");
1884 return -EIO;
1885 }
1886
Vinod Koulb2047e92016-05-12 08:58:55 +05301887 snd_hdac_ext_bus_link_put(ebus, hlink);
1888
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301889 return 0;
1890}
1891
1892static int hdac_hdmi_runtime_resume(struct device *dev)
1893{
1894 struct hdac_ext_device *edev = to_hda_ext_device(dev);
1895 struct hdac_device *hdac = &edev->hdac;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301896 struct hdac_bus *bus = hdac->bus;
Vinod Koulb2047e92016-05-12 08:58:55 +05301897 struct hdac_ext_bus *ebus = hbus_to_ebus(bus);
1898 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301899 int err;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301900
1901 dev_dbg(dev, "Enter: %s\n", __func__);
1902
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301903 /* controller may not have been initialized for the first time */
1904 if (!bus)
1905 return 0;
1906
Vinod Koulb2047e92016-05-12 08:58:55 +05301907 hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301908 if (!hlink) {
1909 dev_err(dev, "hdac link not found\n");
1910 return -EIO;
1911 }
1912
Vinod Koulb2047e92016-05-12 08:58:55 +05301913 snd_hdac_ext_bus_link_get(ebus, hlink);
1914
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301915 err = snd_hdac_display_power(bus, true);
1916 if (err < 0) {
1917 dev_err(bus->dev, "Cannot turn on display power on i915\n");
1918 return err;
1919 }
1920
Subhransu S. Prustyab85f5b2016-02-17 21:34:02 +05301921 hdac_hdmi_skl_enable_all_pins(&edev->hdac);
1922 hdac_hdmi_skl_enable_dp12(&edev->hdac);
1923
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301924 /* Power up afg */
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301925 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1926 AC_PWRST_D0);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301927
1928 return 0;
1929}
1930#else
1931#define hdac_hdmi_runtime_suspend NULL
1932#define hdac_hdmi_runtime_resume NULL
1933#endif
1934
1935static const struct dev_pm_ops hdac_hdmi_pm = {
1936 SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301937 .prepare = hdmi_codec_prepare,
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301938 .complete = hdmi_codec_complete,
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301939};
1940
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301941static const struct hda_device_id hdmi_list[] = {
1942 HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
Jeeja KPe2304802016-03-11 10:12:55 +05301943 HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0),
Shreyas NCcc216882016-07-11 22:02:09 +05301944 HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0),
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301945 {}
1946};
1947
1948MODULE_DEVICE_TABLE(hdaudio, hdmi_list);
1949
1950static struct hdac_ext_driver hdmi_driver = {
1951 . hdac = {
1952 .driver = {
1953 .name = "HDMI HDA Codec",
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301954 .pm = &hdac_hdmi_pm,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301955 },
1956 .id_table = hdmi_list,
1957 },
1958 .probe = hdac_hdmi_dev_probe,
1959 .remove = hdac_hdmi_dev_remove,
1960};
1961
1962static int __init hdmi_init(void)
1963{
1964 return snd_hda_ext_driver_register(&hdmi_driver);
1965}
1966
1967static void __exit hdmi_exit(void)
1968{
1969 snd_hda_ext_driver_unregister(&hdmi_driver);
1970}
1971
1972module_init(hdmi_init);
1973module_exit(hdmi_exit);
1974
1975MODULE_LICENSE("GPL v2");
1976MODULE_DESCRIPTION("HDMI HD codec");
1977MODULE_AUTHOR("Samreen Nilofer<samreen.nilofer@intel.com>");
1978MODULE_AUTHOR("Subhransu S. Prusty<subhransu.s.prusty@intel.com>");