blob: 0f2c1e823281b7ca250c2f9f3f4e7d0ece551dab [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 {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +053092 struct list_head head;
Jeeja KP754695f2017-02-06 12:09:14 +053093 int id;
94 struct hdac_hdmi_pin *pin;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053095 int num_mux_nids;
96 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +053097 struct hdac_hdmi_eld eld;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +053098};
99
Jeeja KP4a3478d2016-02-12 07:46:06 +0530100struct hdac_hdmi_pcm {
101 struct list_head head;
102 int pcm_id;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530103 struct list_head port_list;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530104 struct hdac_hdmi_cvt *cvt;
Jeeja KP62490012017-02-07 19:09:49 +0530105 struct snd_soc_jack *jack;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530106 int stream_tag;
107 int channels;
108 int format;
Jeeja KPab1eea12017-01-24 21:49:05 +0530109 bool chmap_set;
110 unsigned char chmap[8]; /* ALSA API channel-map */
111 struct mutex lock;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530112 int jack_event;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530113};
114
Jeeja KP754695f2017-02-06 12:09:14 +0530115struct hdac_hdmi_dai_port_map {
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530116 int dai_id;
Jeeja KP754695f2017-02-06 12:09:14 +0530117 struct hdac_hdmi_port *port;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530118 struct hdac_hdmi_cvt *cvt;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530119};
120
121struct hdac_hdmi_priv {
Jeeja KP754695f2017-02-06 12:09:14 +0530122 struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS];
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530123 struct list_head pin_list;
124 struct list_head cvt_list;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530125 struct list_head pcm_list;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530126 int num_pin;
127 int num_cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530128 int num_ports;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530129 struct mutex pin_mutex;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530130 struct hdac_chmap chmap;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530131};
132
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530133static struct hdac_hdmi_pcm *
134hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi,
135 struct hdac_hdmi_cvt *cvt)
136{
137 struct hdac_hdmi_pcm *pcm = NULL;
Jeeja KP1de777f2017-01-10 17:57:48 +0530138
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530139 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
140 if (pcm->cvt == cvt)
141 break;
142 }
143
144 return pcm;
145}
Jeeja KP1de777f2017-01-10 17:57:48 +0530146
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530147static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
148 struct hdac_hdmi_port *port, bool is_connect)
149{
150 struct hdac_ext_device *edev = port->pin->edev;
151
152 if (is_connect) {
153 /*
154 * Report Jack connect event when a device is connected
155 * for the first time where same PCM is attached to multiple
156 * ports.
157 */
158 if (pcm->jack_event == 0) {
159 dev_dbg(&edev->hdac.dev,
160 "jack report for pcm=%d\n",
161 pcm->pcm_id);
Jeeja KP62490012017-02-07 19:09:49 +0530162 snd_soc_jack_report(pcm->jack, SND_JACK_AVOUT,
163 SND_JACK_AVOUT);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530164 }
165 pcm->jack_event++;
166 } else {
167 /*
168 * Report Jack disconnect event when a device is disconnected
169 * is the only last connected device when same PCM is attached
170 * to multiple ports.
171 */
172 if (pcm->jack_event == 1)
Jeeja KP62490012017-02-07 19:09:49 +0530173 snd_soc_jack_report(pcm->jack, 0, SND_JACK_AVOUT);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530174 if (pcm->jack_event > 0)
175 pcm->jack_event--;
176 }
177}
178
Jeeja KPfc181b02017-02-07 19:09:45 +0530179/* MST supported verbs */
180/*
181 * Get the no devices that can be connected to a port on the Pin widget.
182 */
183static int hdac_hdmi_get_port_len(struct hdac_ext_device *hdac, hda_nid_t nid)
184{
185 unsigned int caps;
186 unsigned int type, param;
187
188 caps = get_wcaps(&hdac->hdac, nid);
189 type = get_wcaps_type(caps);
190
191 if (!(caps & AC_WCAP_DIGITAL) || (type != AC_WID_PIN))
192 return 0;
193
194 param = snd_hdac_read_parm_uncached(&hdac->hdac, nid,
195 AC_PAR_DEVLIST_LEN);
196 if (param == -1)
197 return param;
198
199 return param & AC_DEV_LIST_LEN_MASK;
200}
201
202/*
203 * Get the port entry select on the pin. Return the port entry
204 * id selected on the pin. Return 0 means the first port entry
205 * is selected or MST is not supported.
206 */
207static int hdac_hdmi_port_select_get(struct hdac_ext_device *hdac,
208 struct hdac_hdmi_port *port)
209{
210 return snd_hdac_codec_read(&hdac->hdac, port->pin->nid,
211 0, AC_VERB_GET_DEVICE_SEL, 0);
212}
213
214/*
215 * Sets the selected port entry for the configuring Pin widget verb.
216 * returns error if port set is not equal to port get otherwise success
217 */
218static int hdac_hdmi_port_select_set(struct hdac_ext_device *hdac,
219 struct hdac_hdmi_port *port)
220{
221 int num_ports;
222
223 if (!port->pin->mst_capable)
224 return 0;
225
226 /* AC_PAR_DEVLIST_LEN is 0 based. */
227 num_ports = hdac_hdmi_get_port_len(hdac, port->pin->nid);
228
229 if (num_ports < 0)
230 return -EIO;
231 /*
232 * Device List Length is a 0 based integer value indicating the
233 * number of sink device that a MST Pin Widget can support.
234 */
235 if (num_ports + 1 < port->id)
236 return 0;
237
238 snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
239 AC_VERB_SET_DEVICE_SEL, port->id);
240
241 if (port->id != hdac_hdmi_port_select_get(hdac, port))
242 return -EIO;
243
244 dev_dbg(&hdac->hdac.dev, "Selected the port=%d\n", port->id);
245
246 return 0;
247}
248
Subhransu S. Prusty28890992016-04-14 10:07:34 +0530249static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi,
250 int pcm_idx)
251{
252 struct hdac_hdmi_pcm *pcm;
253
254 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
255 if (pcm->pcm_id == pcm_idx)
256 return pcm;
257 }
258
259 return NULL;
260}
261
Subhransu S. Prustye342ac02015-11-10 18:42:07 +0530262static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
263{
Geliang Tang51b2c422015-12-28 22:47:13 +0800264 struct hdac_device *hdac = dev_to_hdac_dev(dev);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +0530265
Geliang Tang51b2c422015-12-28 22:47:13 +0800266 return to_ehdac_device(hdac);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +0530267}
268
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530269static unsigned int sad_format(const u8 *sad)
270{
271 return ((sad[0] >> 0x3) & 0x1f);
272}
273
274static unsigned int sad_sample_bits_lpcm(const u8 *sad)
275{
276 return (sad[2] & 7);
277}
278
279static int hdac_hdmi_eld_limit_formats(struct snd_pcm_runtime *runtime,
280 void *eld)
281{
282 u64 formats = SNDRV_PCM_FMTBIT_S16;
283 int i;
284 const u8 *sad, *eld_buf = eld;
285
286 sad = drm_eld_sad(eld_buf);
287 if (!sad)
288 goto format_constraint;
289
290 for (i = drm_eld_sad_count(eld_buf); i > 0; i--, sad += 3) {
291 if (sad_format(sad) == 1) { /* AUDIO_CODING_TYPE_LPCM */
292
293 /*
294 * the controller support 20 and 24 bits in 32 bit
295 * container so we set S32
296 */
297 if (sad_sample_bits_lpcm(sad) & 0x6)
298 formats |= SNDRV_PCM_FMTBIT_S32;
299 }
300 }
301
302format_constraint:
303 return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
304 formats);
305
306}
307
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530308static void
309hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid,
310 int packet_index, int byte_index)
311{
312 int val;
313
314 val = (packet_index << 5) | (byte_index & 0x1f);
315
316 snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
317 AC_VERB_SET_HDMI_DIP_INDEX, val);
318}
319
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530320struct dp_audio_infoframe {
321 u8 type; /* 0x84 */
322 u8 len; /* 0x1b */
323 u8 ver; /* 0x11 << 2 */
324
325 u8 CC02_CT47; /* match with HDMI infoframe from this on */
326 u8 SS01_SF24;
327 u8 CXT04;
328 u8 CA;
329 u8 LFEPBL01_LSV36_DM_INH7;
330};
331
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530332static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
Jeeja KP754695f2017-02-06 12:09:14 +0530333 struct hdac_hdmi_pcm *pcm, struct hdac_hdmi_port *port)
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530334{
335 uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
336 struct hdmi_audio_infoframe frame;
Jeeja KP754695f2017-02-06 12:09:14 +0530337 struct hdac_hdmi_pin *pin = port->pin;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530338 struct dp_audio_infoframe dp_ai;
339 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KPab1eea12017-01-24 21:49:05 +0530340 struct hdac_hdmi_cvt *cvt = pcm->cvt;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530341 u8 *dip;
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530342 int ret;
343 int i;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530344 const u8 *eld_buf;
345 u8 conn_type;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530346 int channels, ca;
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530347
Jeeja KP754695f2017-02-06 12:09:14 +0530348 ca = snd_hdac_channel_allocation(&hdac->hdac, port->eld.info.spk_alloc,
Jeeja KPab1eea12017-01-24 21:49:05 +0530349 pcm->channels, pcm->chmap_set, true, pcm->chmap);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530350
351 channels = snd_hdac_get_active_channels(ca);
Jeeja KPab1eea12017-01-24 21:49:05 +0530352 hdmi->chmap.ops.set_channel_count(&hdac->hdac, cvt->nid, channels);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530353
354 snd_hdac_setup_channel_mapping(&hdmi->chmap, pin->nid, false, ca,
Jeeja KPab1eea12017-01-24 21:49:05 +0530355 pcm->channels, pcm->chmap, pcm->chmap_set);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530356
Jeeja KP754695f2017-02-06 12:09:14 +0530357 eld_buf = port->eld.eld_buffer;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530358 conn_type = drm_eld_get_conn_type(eld_buf);
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530359
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530360 switch (conn_type) {
361 case DRM_ELD_CONN_TYPE_HDMI:
362 hdmi_audio_infoframe_init(&frame);
363
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530364 frame.channels = channels;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530365 frame.channel_allocation = ca;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530366
367 ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
368 if (ret < 0)
369 return ret;
370
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530371 break;
372
373 case DRM_ELD_CONN_TYPE_DP:
374 memset(&dp_ai, 0, sizeof(dp_ai));
375 dp_ai.type = 0x84;
376 dp_ai.len = 0x1b;
377 dp_ai.ver = 0x11 << 2;
378 dp_ai.CC02_CT47 = channels - 1;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530379 dp_ai.CA = ca;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530380
381 dip = (u8 *)&dp_ai;
382 break;
383
384 default:
385 dev_err(&hdac->hdac.dev, "Invalid connection type: %d\n",
386 conn_type);
387 return -EIO;
388 }
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530389
390 /* stop infoframe transmission */
Jeeja KPab1eea12017-01-24 21:49:05 +0530391 hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0);
392 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530393 AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE);
394
395
396 /* Fill infoframe. Index auto-incremented */
Jeeja KPab1eea12017-01-24 21:49:05 +0530397 hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0);
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530398 if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
Subhransu S. Prusty391005e2016-03-10 09:04:07 +0530399 for (i = 0; i < sizeof(buffer); i++)
Jeeja KPab1eea12017-01-24 21:49:05 +0530400 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prusty391005e2016-03-10 09:04:07 +0530401 AC_VERB_SET_HDMI_DIP_DATA, buffer[i]);
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530402 } else {
403 for (i = 0; i < sizeof(dp_ai); i++)
Jeeja KPab1eea12017-01-24 21:49:05 +0530404 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530405 AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
406 }
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530407
408 /* Start infoframe */
Jeeja KPab1eea12017-01-24 21:49:05 +0530409 hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0);
410 snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530411 AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST);
412
413 return 0;
414}
415
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530416static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
417 unsigned int tx_mask, unsigned int rx_mask,
418 int slots, int slot_width)
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530419{
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530420 struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai);
421 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530422 struct hdac_hdmi_dai_port_map *dai_map;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530423 struct hdac_hdmi_pcm *pcm;
424
425 dev_dbg(&edev->hdac.dev, "%s: strm_tag: %d\n", __func__, tx_mask);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530426
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530427 dai_map = &hdmi->dai_map[dai->id];
428
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530429 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530430
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530431 if (pcm)
432 pcm->stream_tag = (tx_mask << 4);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530433
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530434 return 0;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530435}
436
437static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
438 struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai)
439{
440 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530441 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530442 struct hdac_hdmi_dai_port_map *dai_map;
443 struct hdac_hdmi_port *port;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530444 struct hdac_hdmi_pcm *pcm;
445 int format;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530446
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530447 dai_map = &hdmi->dai_map[dai->id];
Jeeja KP754695f2017-02-06 12:09:14 +0530448 port = dai_map->port;
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530449
Jeeja KP754695f2017-02-06 12:09:14 +0530450 if (!port)
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530451 return -ENODEV;
452
Jeeja KP754695f2017-02-06 12:09:14 +0530453 if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) {
454 dev_err(&hdac->hdac.dev,
455 "device is not configured for this pin:port%d:%d\n",
456 port->pin->nid, port->id);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530457 return -ENODEV;
458 }
459
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530460 format = snd_hdac_calc_stream_format(params_rate(hparams),
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530461 params_channels(hparams), params_format(hparams),
462 24, 0);
463
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530464 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
465 if (!pcm)
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530466 return -EIO;
467
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530468 pcm->format = format;
469 pcm->channels = params_channels(hparams);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530470
471 return 0;
472}
473
Jeeja KP754695f2017-02-06 12:09:14 +0530474static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *hdac,
475 struct hdac_hdmi_pin *pin,
476 struct hdac_hdmi_port *port)
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530477{
478 if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
479 dev_warn(&hdac->hdac.dev,
480 "HDMI: pin %d wcaps %#x does not support connection list\n",
481 pin->nid, get_wcaps(&hdac->hdac, pin->nid));
482 return -EINVAL;
483 }
484
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530485 if (hdac_hdmi_port_select_set(hdac, port) < 0)
486 return -EIO;
487
Jeeja KP754695f2017-02-06 12:09:14 +0530488 port->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
489 port->mux_nids, HDA_MAX_CONNECTIONS);
490 if (port->num_mux_nids == 0)
491 dev_warn(&hdac->hdac.dev,
492 "No connections found for pin:port %d:%d\n",
493 pin->nid, port->id);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530494
Jeeja KP754695f2017-02-06 12:09:14 +0530495 dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin:port %d:%d\n",
496 port->num_mux_nids, pin->nid, port->id);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530497
Jeeja KP754695f2017-02-06 12:09:14 +0530498 return port->num_mux_nids;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530499}
500
501/*
Jeeja KP754695f2017-02-06 12:09:14 +0530502 * Query pcm list and return port to which stream is routed.
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530503 *
Jeeja KP754695f2017-02-06 12:09:14 +0530504 * Also query connection list of the pin, to validate the cvt to port map.
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530505 *
Jeeja KP754695f2017-02-06 12:09:14 +0530506 * Same stream rendering to multiple ports simultaneously can be done
507 * possibly, but not supported for now in driver. So return the first port
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530508 * connected.
509 */
Jeeja KP754695f2017-02-06 12:09:14 +0530510static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530511 struct hdac_ext_device *edev,
512 struct hdac_hdmi_priv *hdmi,
513 struct hdac_hdmi_cvt *cvt)
514{
515 struct hdac_hdmi_pcm *pcm;
Jeeja KP754695f2017-02-06 12:09:14 +0530516 struct hdac_hdmi_port *port = NULL;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530517 int ret, i;
518
519 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
520 if (pcm->cvt == cvt) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530521 if (list_empty(&pcm->port_list))
522 continue;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530523
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530524 list_for_each_entry(port, &pcm->port_list, head) {
525 mutex_lock(&pcm->lock);
526 ret = hdac_hdmi_query_port_connlist(edev,
527 port->pin, port);
528 mutex_unlock(&pcm->lock);
529 if (ret < 0)
530 continue;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530531
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530532 for (i = 0; i < port->num_mux_nids; i++) {
533 if (port->mux_nids[i] == cvt->nid &&
534 port->eld.monitor_present &&
535 port->eld.eld_valid)
536 return port;
537 }
538 }
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530539 }
540 }
541
542 return NULL;
543}
544
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530545/*
546 * This tries to get a valid pin and set the HW constraints based on the
547 * ELD. Even if a valid pin is not found return success so that device open
548 * doesn't fail.
549 */
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530550static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
551 struct snd_soc_dai *dai)
552{
553 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
554 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530555 struct hdac_hdmi_dai_port_map *dai_map;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530556 struct hdac_hdmi_cvt *cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530557 struct hdac_hdmi_port *port;
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530558 int ret;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530559
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530560 dai_map = &hdmi->dai_map[dai->id];
561
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530562 cvt = dai_map->cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530563 port = hdac_hdmi_get_port_from_cvt(hdac, hdmi, cvt);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530564
565 /*
566 * To make PA and other userland happy.
567 * userland scans devices so returning error does not help.
568 */
Jeeja KP754695f2017-02-06 12:09:14 +0530569 if (!port)
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530570 return 0;
Jeeja KP754695f2017-02-06 12:09:14 +0530571 if ((!port->eld.monitor_present) ||
572 (!port->eld.eld_valid)) {
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530573
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530574 dev_warn(&hdac->hdac.dev,
Jeeja KP754695f2017-02-06 12:09:14 +0530575 "Failed: present?:%d ELD valid?:%d pin:port: %d:%d\n",
576 port->eld.monitor_present, port->eld.eld_valid,
577 port->pin->nid, port->id);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +0530578
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530579 return 0;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530580 }
581
Jeeja KP754695f2017-02-06 12:09:14 +0530582 dai_map->port = port;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530583
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530584 ret = hdac_hdmi_eld_limit_formats(substream->runtime,
Jeeja KP754695f2017-02-06 12:09:14 +0530585 port->eld.eld_buffer);
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530586 if (ret < 0)
587 return ret;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530588
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530589 return snd_pcm_hw_constraint_eld(substream->runtime,
Jeeja KP754695f2017-02-06 12:09:14 +0530590 port->eld.eld_buffer);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530591}
592
593static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
594 struct snd_soc_dai *dai)
595{
596 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
597 struct hdac_hdmi_priv *hdmi = hdac->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530598 struct hdac_hdmi_dai_port_map *dai_map;
Jeeja KPab1eea12017-01-24 21:49:05 +0530599 struct hdac_hdmi_pcm *pcm;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530600
601 dai_map = &hdmi->dai_map[dai->id];
602
Jeeja KPab1eea12017-01-24 21:49:05 +0530603 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530604
Jeeja KPab1eea12017-01-24 21:49:05 +0530605 if (pcm) {
606 mutex_lock(&pcm->lock);
607 pcm->chmap_set = false;
608 memset(pcm->chmap, 0, sizeof(pcm->chmap));
609 pcm->channels = 0;
610 mutex_unlock(&pcm->lock);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530611 }
Jeeja KPab1eea12017-01-24 21:49:05 +0530612
Jeeja KP754695f2017-02-06 12:09:14 +0530613 if (dai_map->port)
614 dai_map->port = NULL;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530615}
616
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530617static int
618hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
619{
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530620 unsigned int chans;
621 struct hdac_ext_device *edev = to_ehdac_device(hdac);
622 struct hdac_hdmi_priv *hdmi = edev->private_data;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530623 int err;
624
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530625 chans = get_wcaps(hdac, cvt->nid);
626 chans = get_wcaps_channels(chans);
627
628 cvt->params.channels_min = 2;
629
630 cvt->params.channels_max = chans;
631 if (chans > hdmi->chmap.channels_max)
632 hdmi->chmap.channels_max = chans;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530633
634 err = snd_hdac_query_supported_pcm(hdac, cvt->nid,
635 &cvt->params.rates,
636 &cvt->params.formats,
637 &cvt->params.maxbps);
638 if (err < 0)
639 dev_err(&hdac->dev,
640 "Failed to query pcm params for nid %d: %d\n",
641 cvt->nid, err);
642
643 return err;
644}
645
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530646static int hdac_hdmi_fill_widget_info(struct device *dev,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530647 struct snd_soc_dapm_widget *w, enum snd_soc_dapm_type id,
648 void *priv, const char *wname, const char *stream,
649 struct snd_kcontrol_new *wc, int numkc,
650 int (*event)(struct snd_soc_dapm_widget *,
651 struct snd_kcontrol *, int), unsigned short event_flags)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530652{
653 w->id = id;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530654 w->name = devm_kstrdup(dev, wname, GFP_KERNEL);
655 if (!w->name)
656 return -ENOMEM;
657
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530658 w->sname = stream;
659 w->reg = SND_SOC_NOPM;
660 w->shift = 0;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530661 w->kcontrol_news = wc;
662 w->num_kcontrols = numkc;
663 w->priv = priv;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530664 w->event = event;
665 w->event_flags = event_flags;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530666
667 return 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530668}
669
670static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530671 const char *sink, const char *control, const char *src,
672 int (*handler)(struct snd_soc_dapm_widget *src,
673 struct snd_soc_dapm_widget *sink))
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530674{
675 route->sink = sink;
676 route->source = src;
677 route->control = control;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530678 route->connected = handler;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530679}
680
Jeeja KP4a3478d2016-02-12 07:46:06 +0530681static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev,
Jeeja KP754695f2017-02-06 12:09:14 +0530682 struct hdac_hdmi_port *port)
Jeeja KP4a3478d2016-02-12 07:46:06 +0530683{
684 struct hdac_hdmi_priv *hdmi = edev->private_data;
685 struct hdac_hdmi_pcm *pcm = NULL;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530686 struct hdac_hdmi_port *p;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530687
688 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530689 if (list_empty(&pcm->port_list))
Jeeja KP754695f2017-02-06 12:09:14 +0530690 continue;
691
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530692 list_for_each_entry(p, &pcm->port_list, head) {
693 if (p->id == port->id && port->pin == p->pin)
694 return pcm;
695 }
Jeeja KP4a3478d2016-02-12 07:46:06 +0530696 }
697
698 return NULL;
699}
700
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530701static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
702 hda_nid_t nid, unsigned int pwr_state)
703{
704 if (get_wcaps(&edev->hdac, nid) & AC_WCAP_POWER) {
705 if (!snd_hdac_check_power_state(&edev->hdac, nid, pwr_state))
706 snd_hdac_codec_write(&edev->hdac, nid, 0,
707 AC_VERB_SET_POWER_STATE, pwr_state);
708 }
709}
710
711static void hdac_hdmi_set_amp(struct hdac_ext_device *edev,
712 hda_nid_t nid, int val)
713{
714 if (get_wcaps(&edev->hdac, nid) & AC_WCAP_OUT_AMP)
715 snd_hdac_codec_write(&edev->hdac, nid, 0,
716 AC_VERB_SET_AMP_GAIN_MUTE, val);
717}
718
719
720static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w,
721 struct snd_kcontrol *kc, int event)
722{
Jeeja KP754695f2017-02-06 12:09:14 +0530723 struct hdac_hdmi_port *port = w->priv;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530724 struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev);
725 struct hdac_hdmi_pcm *pcm;
726
727 dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n",
728 __func__, w->name, event);
729
Jeeja KP754695f2017-02-06 12:09:14 +0530730 pcm = hdac_hdmi_get_pcm(edev, port);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530731 if (!pcm)
732 return -EIO;
733
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530734 /* set the device if pin is mst_capable */
735 if (hdac_hdmi_port_select_set(edev, port) < 0)
736 return -EIO;
737
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530738 switch (event) {
739 case SND_SOC_DAPM_PRE_PMU:
Jeeja KP754695f2017-02-06 12:09:14 +0530740 hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D0);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530741
742 /* Enable out path for this pin widget */
Jeeja KP754695f2017-02-06 12:09:14 +0530743 snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530744 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
745
Jeeja KP754695f2017-02-06 12:09:14 +0530746 hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_UNMUTE);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530747
Jeeja KP754695f2017-02-06 12:09:14 +0530748 return hdac_hdmi_setup_audio_infoframe(edev, pcm, port);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530749
750 case SND_SOC_DAPM_POST_PMD:
Jeeja KP754695f2017-02-06 12:09:14 +0530751 hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_MUTE);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530752
753 /* Disable out path for this pin widget */
Jeeja KP754695f2017-02-06 12:09:14 +0530754 snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530755 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
756
Jeeja KP754695f2017-02-06 12:09:14 +0530757 hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D3);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530758 break;
759
760 }
761
762 return 0;
763}
764
765static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w,
766 struct snd_kcontrol *kc, int event)
767{
768 struct hdac_hdmi_cvt *cvt = w->priv;
769 struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev);
770 struct hdac_hdmi_priv *hdmi = edev->private_data;
771 struct hdac_hdmi_pcm *pcm;
772
773 dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n",
774 __func__, w->name, event);
775
776 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, cvt);
777 if (!pcm)
778 return -EIO;
779
780 switch (event) {
781 case SND_SOC_DAPM_PRE_PMU:
782 hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D0);
783
784 /* Enable transmission */
785 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
786 AC_VERB_SET_DIGI_CONVERT_1, 1);
787
788 /* Category Code (CC) to zero */
789 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
790 AC_VERB_SET_DIGI_CONVERT_2, 0);
791
792 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
793 AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag);
794 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
795 AC_VERB_SET_STREAM_FORMAT, pcm->format);
796 break;
797
798 case SND_SOC_DAPM_POST_PMD:
799 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
800 AC_VERB_SET_CHANNEL_STREAMID, 0);
801 snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
802 AC_VERB_SET_STREAM_FORMAT, 0);
803
804 hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D3);
805 break;
806
807 }
808
809 return 0;
810}
811
812static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w,
813 struct snd_kcontrol *kc, int event)
814{
Jeeja KP754695f2017-02-06 12:09:14 +0530815 struct hdac_hdmi_port *port = w->priv;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530816 struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev);
817 int mux_idx;
818
819 dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n",
820 __func__, w->name, event);
821
822 if (!kc)
823 kc = w->kcontrols[0];
824
825 mux_idx = dapm_kcontrol_get_value(kc);
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530826
827 /* set the device if pin is mst_capable */
828 if (hdac_hdmi_port_select_set(edev, port) < 0)
829 return -EIO;
830
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530831 if (mux_idx > 0) {
Jeeja KP754695f2017-02-06 12:09:14 +0530832 snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530833 AC_VERB_SET_CONNECT_SEL, (mux_idx - 1));
834 }
835
836 return 0;
837}
838
Jeeja KP4a3478d2016-02-12 07:46:06 +0530839/*
840 * Based on user selection, map the PINs with the PCMs.
841 */
Jeeja KP754695f2017-02-06 12:09:14 +0530842static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
Jeeja KP4a3478d2016-02-12 07:46:06 +0530843 struct snd_ctl_elem_value *ucontrol)
844{
845 int ret;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530846 struct hdac_hdmi_port *p, *p_next;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530847 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
848 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
849 struct snd_soc_dapm_context *dapm = w->dapm;
Jeeja KP754695f2017-02-06 12:09:14 +0530850 struct hdac_hdmi_port *port = w->priv;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530851 struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev);
852 struct hdac_hdmi_priv *hdmi = edev->private_data;
853 struct hdac_hdmi_pcm *pcm = NULL;
854 const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]];
855
856 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
857 if (ret < 0)
858 return ret;
859
Jeeja KP754695f2017-02-06 12:09:14 +0530860 if (port == NULL)
861 return -EINVAL;
862
Jeeja KP4a3478d2016-02-12 07:46:06 +0530863 mutex_lock(&hdmi->pin_mutex);
864 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530865 if (list_empty(&pcm->port_list))
866 continue;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530867
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530868 list_for_each_entry_safe(p, p_next, &pcm->port_list, head) {
869 if (p == port && p->id == port->id &&
870 p->pin == port->pin) {
871 hdac_hdmi_jack_report(pcm, port, false);
872 list_del(&p->head);
Jeeja KP4a3478d2016-02-12 07:46:06 +0530873 }
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530874 }
875 }
876
877 /*
878 * Jack status is not reported during device probe as the
879 * PCMs are not registered by then. So report it here.
880 */
881 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
882 if (!strcmp(cvt_name, pcm->cvt->name)) {
883 list_add_tail(&port->head, &pcm->port_list);
884 if (port->eld.monitor_present && port->eld.eld_valid) {
885 hdac_hdmi_jack_report(pcm, port, true);
886 mutex_unlock(&hdmi->pin_mutex);
887 return ret;
888 }
Jeeja KP4a3478d2016-02-12 07:46:06 +0530889 }
890 }
891 mutex_unlock(&hdmi->pin_mutex);
892
893 return ret;
894}
895
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530896/*
897 * Ideally the Mux inputs should be based on the num_muxs enumerated, but
898 * the display driver seem to be programming the connection list for the pin
899 * widget runtime.
900 *
901 * So programming all the possible inputs for the mux, the user has to take
902 * care of selecting the right one and leaving all other inputs selected to
903 * "NONE"
904 */
Jeeja KP754695f2017-02-06 12:09:14 +0530905static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev,
906 struct hdac_hdmi_port *port,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530907 struct snd_soc_dapm_widget *widget,
908 const char *widget_name)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530909{
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530910 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +0530911 struct hdac_hdmi_pin *pin = port->pin;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530912 struct snd_kcontrol_new *kc;
913 struct hdac_hdmi_cvt *cvt;
914 struct soc_enum *se;
915 char kc_name[NAME_SIZE];
916 char mux_items[NAME_SIZE];
917 /* To hold inputs to the Pin mux */
918 char *items[HDA_MAX_CONNECTIONS];
919 int i = 0;
920 int num_items = hdmi->num_cvt + 1;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530921
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530922 kc = devm_kzalloc(&edev->hdac.dev, sizeof(*kc), GFP_KERNEL);
923 if (!kc)
924 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530925
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530926 se = devm_kzalloc(&edev->hdac.dev, sizeof(*se), GFP_KERNEL);
927 if (!se)
928 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530929
Jeeja KP754695f2017-02-06 12:09:14 +0530930 sprintf(kc_name, "Pin %d port %d Input", pin->nid, port->id);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530931 kc->name = devm_kstrdup(&edev->hdac.dev, kc_name, GFP_KERNEL);
932 if (!kc->name)
933 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530934
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530935 kc->private_value = (long)se;
936 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
937 kc->access = 0;
938 kc->info = snd_soc_info_enum_double;
Jeeja KP754695f2017-02-06 12:09:14 +0530939 kc->put = hdac_hdmi_set_pin_port_mux;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530940 kc->get = snd_soc_dapm_get_enum_double;
941
942 se->reg = SND_SOC_NOPM;
943
944 /* enum texts: ["NONE", "cvt #", "cvt #", ...] */
945 se->items = num_items;
946 se->mask = roundup_pow_of_two(se->items) - 1;
947
948 sprintf(mux_items, "NONE");
949 items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL);
950 if (!items[i])
951 return -ENOMEM;
952
953 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
954 i++;
955 sprintf(mux_items, "cvt %d", cvt->nid);
956 items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL);
957 if (!items[i])
958 return -ENOMEM;
959 }
960
961 se->texts = devm_kmemdup(&edev->hdac.dev, items,
962 (num_items * sizeof(char *)), GFP_KERNEL);
963 if (!se->texts)
964 return -ENOMEM;
965
966 return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget,
Jeeja KP754695f2017-02-06 12:09:14 +0530967 snd_soc_dapm_mux, port, widget_name, NULL, kc, 1,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530968 hdac_hdmi_pin_mux_widget_event,
969 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_REG);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530970}
971
972/* Add cvt <- input <- mux route map */
973static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev,
974 struct snd_soc_dapm_widget *widgets,
975 struct snd_soc_dapm_route *route, int rindex)
976{
977 struct hdac_hdmi_priv *hdmi = edev->private_data;
978 const struct snd_kcontrol_new *kc;
979 struct soc_enum *se;
Jeeja KP754695f2017-02-06 12:09:14 +0530980 int mux_index = hdmi->num_cvt + hdmi->num_ports;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530981 int i, j;
982
Jeeja KP754695f2017-02-06 12:09:14 +0530983 for (i = 0; i < hdmi->num_ports; i++) {
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530984 kc = widgets[mux_index].kcontrol_news;
985 se = (struct soc_enum *)kc->private_value;
986 for (j = 0; j < hdmi->num_cvt; j++) {
987 hdac_hdmi_fill_route(&route[rindex],
988 widgets[mux_index].name,
989 se->texts[j + 1],
990 widgets[j].name, NULL);
991
992 rindex++;
993 }
994
995 mux_index++;
996 }
997}
998
999/*
1000 * Widgets are added in the below sequence
1001 * Converter widgets for num converters enumerated
Jeeja KP754695f2017-02-06 12:09:14 +05301002 * Pin-port widgets for num ports for Pins enumerated
1003 * Pin-port mux widgets to represent connenction list of pin widget
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301004 *
Jeeja KP754695f2017-02-06 12:09:14 +05301005 * For each port, one Mux and One output widget is added
1006 * Total widgets elements = num_cvt + (num_ports * 2);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301007 *
1008 * Routes are added as below:
Jeeja KP754695f2017-02-06 12:09:14 +05301009 * pin-port mux -> pin (based on num_ports)
1010 * cvt -> "Input sel control" -> pin-port_mux
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301011 *
1012 * Total route elements:
Jeeja KP754695f2017-02-06 12:09:14 +05301013 * num_ports + (pin_muxes * num_cvt)
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301014 */
1015static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
1016{
1017 struct snd_soc_dapm_widget *widgets;
1018 struct snd_soc_dapm_route *route;
1019 struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev);
1020 struct hdac_hdmi_priv *hdmi = edev->private_data;
1021 struct snd_soc_dai_driver *dai_drv = dapm->component->dai_drv;
1022 char widget_name[NAME_SIZE];
1023 struct hdac_hdmi_cvt *cvt;
1024 struct hdac_hdmi_pin *pin;
Jeeja KP754695f2017-02-06 12:09:14 +05301025 int ret, i = 0, num_routes = 0, j;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301026
1027 if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
1028 return -EINVAL;
1029
Jeeja KP754695f2017-02-06 12:09:14 +05301030 widgets = devm_kzalloc(dapm->dev, (sizeof(*widgets) *
1031 ((2 * hdmi->num_ports) + hdmi->num_cvt)),
1032 GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301033
1034 if (!widgets)
1035 return -ENOMEM;
1036
1037 /* DAPM widgets to represent each converter widget */
1038 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
1039 sprintf(widget_name, "Converter %d", cvt->nid);
1040 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
Jeeja KPc9bfb5d2017-01-24 21:49:03 +05301041 snd_soc_dapm_aif_in, cvt,
1042 widget_name, dai_drv[i].playback.stream_name, NULL, 0,
1043 hdac_hdmi_cvt_output_widget_event,
1044 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301045 if (ret < 0)
1046 return ret;
1047 i++;
1048 }
1049
1050 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301051 for (j = 0; j < pin->num_ports; j++) {
1052 sprintf(widget_name, "hif%d-%d Output",
1053 pin->nid, pin->ports[j].id);
1054 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
1055 snd_soc_dapm_output, &pin->ports[j],
1056 widget_name, NULL, NULL, 0,
1057 hdac_hdmi_pin_output_widget_event,
1058 SND_SOC_DAPM_PRE_PMU |
1059 SND_SOC_DAPM_POST_PMD);
1060 if (ret < 0)
1061 return ret;
1062 i++;
1063 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301064 }
1065
1066 /* DAPM widgets to represent the connection list to pin widget */
1067 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301068 for (j = 0; j < pin->num_ports; j++) {
1069 sprintf(widget_name, "Pin%d-Port%d Mux",
1070 pin->nid, pin->ports[j].id);
1071 ret = hdac_hdmi_create_pin_port_muxs(edev,
1072 &pin->ports[j], &widgets[i],
1073 widget_name);
1074 if (ret < 0)
1075 return ret;
1076 i++;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301077
Jeeja KP754695f2017-02-06 12:09:14 +05301078 /* For cvt to pin_mux mapping */
1079 num_routes += hdmi->num_cvt;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301080
Jeeja KP754695f2017-02-06 12:09:14 +05301081 /* For pin_mux to pin mapping */
1082 num_routes++;
1083 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301084 }
1085
1086 route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes),
1087 GFP_KERNEL);
1088 if (!route)
1089 return -ENOMEM;
1090
1091 i = 0;
1092 /* Add pin <- NULL <- mux route map */
1093 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301094 for (j = 0; j < pin->num_ports; j++) {
1095 int sink_index = i + hdmi->num_cvt;
1096 int src_index = sink_index + pin->num_ports *
1097 hdmi->num_pin;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301098
Jeeja KP754695f2017-02-06 12:09:14 +05301099 hdac_hdmi_fill_route(&route[i],
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301100 widgets[sink_index].name, NULL,
1101 widgets[src_index].name, NULL);
Jeeja KP754695f2017-02-06 12:09:14 +05301102 i++;
1103 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301104 }
1105
1106 hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i);
1107
1108 snd_soc_dapm_new_controls(dapm, widgets,
Jeeja KP754695f2017-02-06 12:09:14 +05301109 ((2 * hdmi->num_ports) + hdmi->num_cvt));
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301110
1111 snd_soc_dapm_add_routes(dapm, route, num_routes);
1112 snd_soc_dapm_new_widgets(dapm->card);
1113
1114 return 0;
1115
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301116}
1117
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301118static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301119{
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301120 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +05301121 struct hdac_hdmi_dai_port_map *dai_map;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301122 struct hdac_hdmi_cvt *cvt;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301123 int dai_id = 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301124
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301125 if (list_empty(&hdmi->cvt_list))
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301126 return -EINVAL;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301127
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301128 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
1129 dai_map = &hdmi->dai_map[dai_id];
1130 dai_map->dai_id = dai_id;
1131 dai_map->cvt = cvt;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301132
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301133 dai_id++;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301134
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301135 if (dai_id == HDA_MAX_CVTS) {
1136 dev_warn(&edev->hdac.dev,
1137 "Max dais supported: %d\n", dai_id);
1138 break;
1139 }
1140 }
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301141
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301142 return 0;
1143}
1144
1145static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
1146{
1147 struct hdac_hdmi_priv *hdmi = edev->private_data;
1148 struct hdac_hdmi_cvt *cvt;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301149 char name[NAME_SIZE];
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301150
1151 cvt = kzalloc(sizeof(*cvt), GFP_KERNEL);
1152 if (!cvt)
1153 return -ENOMEM;
1154
1155 cvt->nid = nid;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301156 sprintf(name, "cvt %d", cvt->nid);
1157 cvt->name = kstrdup(name, GFP_KERNEL);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301158
1159 list_add_tail(&cvt->head, &hdmi->cvt_list);
1160 hdmi->num_cvt++;
1161
1162 return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
1163}
1164
Jeeja KP754695f2017-02-06 12:09:14 +05301165static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
1166 struct hdac_hdmi_port *port)
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +05301167{
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301168 unsigned int ver, mnl;
1169
Jeeja KP754695f2017-02-06 12:09:14 +05301170 ver = (port->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301171 >> DRM_ELD_VER_SHIFT;
1172
1173 if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
1174 dev_err(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver);
1175 return -EINVAL;
1176 }
1177
Jeeja KP754695f2017-02-06 12:09:14 +05301178 mnl = (port->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301179 DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
1180
1181 if (mnl > ELD_MAX_MNL) {
1182 dev_err(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl);
1183 return -EINVAL;
1184 }
1185
Jeeja KP754695f2017-02-06 12:09:14 +05301186 port->eld.info.spk_alloc = port->eld.eld_buffer[DRM_ELD_SPEAKER];
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301187
1188 return 0;
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +05301189}
1190
Jeeja KP754695f2017-02-06 12:09:14 +05301191static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
1192 struct hdac_hdmi_port *port)
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301193{
1194 struct hdac_ext_device *edev = pin->edev;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301195 struct hdac_hdmi_priv *hdmi = edev->private_data;
1196 struct hdac_hdmi_pcm *pcm;
Jeeja KP754695f2017-02-06 12:09:14 +05301197 int size = 0;
Jeeja KP2acd8302017-02-06 12:09:18 +05301198 int port_id = -1;
Jeeja KP754695f2017-02-06 12:09:14 +05301199
1200 if (!hdmi)
1201 return;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301202
Jeeja KP2acd8302017-02-06 12:09:18 +05301203 /*
1204 * In case of non MST pin, get_eld info API expectes port
1205 * to be -1.
1206 */
Jeeja KP4a3478d2016-02-12 07:46:06 +05301207 mutex_lock(&hdmi->pin_mutex);
Jeeja KP754695f2017-02-06 12:09:14 +05301208 port->eld.monitor_present = false;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301209
Jeeja KP2acd8302017-02-06 12:09:18 +05301210 if (pin->mst_capable)
1211 port_id = port->id;
1212
1213 size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, port_id,
Jeeja KP754695f2017-02-06 12:09:14 +05301214 &port->eld.monitor_present,
1215 port->eld.eld_buffer,
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301216 ELD_MAX_SIZE);
1217
1218 if (size > 0) {
1219 size = min(size, ELD_MAX_SIZE);
Jeeja KP754695f2017-02-06 12:09:14 +05301220 if (hdac_hdmi_parse_eld(edev, port) < 0)
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301221 size = -EINVAL;
1222 }
1223
1224 if (size > 0) {
Jeeja KP754695f2017-02-06 12:09:14 +05301225 port->eld.eld_valid = true;
1226 port->eld.eld_size = size;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301227 } else {
Jeeja KP754695f2017-02-06 12:09:14 +05301228 port->eld.eld_valid = false;
1229 port->eld.eld_size = 0;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301230 }
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301231
Jeeja KP754695f2017-02-06 12:09:14 +05301232 pcm = hdac_hdmi_get_pcm(edev, port);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301233
Jeeja KP754695f2017-02-06 12:09:14 +05301234 if (!port->eld.monitor_present || !port->eld.eld_valid) {
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301235
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301236 dev_err(&edev->hdac.dev, "%s: disconnect for pin:port %d:%d\n",
Jeeja KP754695f2017-02-06 12:09:14 +05301237 __func__, pin->nid, port->id);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301238
1239 /*
1240 * PCMs are not registered during device probe, so don't
1241 * report jack here. It will be done in usermode mux
1242 * control select.
1243 */
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301244 if (pcm)
1245 hdac_hdmi_jack_report(pcm, port, false);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301246
1247 mutex_unlock(&hdmi->pin_mutex);
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301248 return;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301249 }
1250
Jeeja KP754695f2017-02-06 12:09:14 +05301251 if (port->eld.monitor_present && port->eld.eld_valid) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301252 if (pcm)
1253 hdac_hdmi_jack_report(pcm, port, true);
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301254
1255 print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
Jeeja KP754695f2017-02-06 12:09:14 +05301256 port->eld.eld_buffer, port->eld.eld_size, false);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301257
Jeeja KP754695f2017-02-06 12:09:14 +05301258 }
Jeeja KP4a3478d2016-02-12 07:46:06 +05301259 mutex_unlock(&hdmi->pin_mutex);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301260}
1261
Jeeja KP754695f2017-02-06 12:09:14 +05301262static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi,
1263 struct hdac_hdmi_pin *pin)
1264{
1265 struct hdac_hdmi_port *ports;
1266 int max_ports = HDA_MAX_PORTS;
1267 int i;
1268
1269 /*
1270 * FIXME: max_port may vary for each platform, so pass this as
1271 * as driver data or query from i915 interface when this API is
1272 * implemented.
1273 */
1274
1275 ports = kcalloc(max_ports, sizeof(*ports), GFP_KERNEL);
1276 if (!ports)
1277 return -ENOMEM;
1278
1279 for (i = 0; i < max_ports; i++) {
1280 ports[i].id = i;
1281 ports[i].pin = pin;
1282 }
1283 pin->ports = ports;
1284 pin->num_ports = max_ports;
1285 return 0;
1286}
1287
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301288static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
1289{
1290 struct hdac_hdmi_priv *hdmi = edev->private_data;
1291 struct hdac_hdmi_pin *pin;
Jeeja KP754695f2017-02-06 12:09:14 +05301292 int ret;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301293
1294 pin = kzalloc(sizeof(*pin), GFP_KERNEL);
1295 if (!pin)
1296 return -ENOMEM;
1297
1298 pin->nid = nid;
Jeeja KP2acd8302017-02-06 12:09:18 +05301299 pin->mst_capable = false;
Jeeja KP754695f2017-02-06 12:09:14 +05301300 pin->edev = edev;
1301 ret = hdac_hdmi_add_ports(hdmi, pin);
1302 if (ret < 0)
1303 return ret;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301304
1305 list_add_tail(&pin->head, &hdmi->pin_list);
1306 hdmi->num_pin++;
Jeeja KP754695f2017-02-06 12:09:14 +05301307 hdmi->num_ports += pin->num_ports;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301308
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301309 return 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301310}
1311
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301312#define INTEL_VENDOR_NID 0x08
1313#define INTEL_GET_VENDOR_VERB 0xf81
1314#define INTEL_SET_VENDOR_VERB 0x781
1315#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
1316#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
1317
1318static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac)
1319{
1320 unsigned int vendor_param;
1321
1322 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1323 INTEL_GET_VENDOR_VERB, 0);
1324 if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
1325 return;
1326
1327 vendor_param |= INTEL_EN_ALL_PIN_CVTS;
1328 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1329 INTEL_SET_VENDOR_VERB, vendor_param);
1330 if (vendor_param == -1)
1331 return;
1332}
1333
1334static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
1335{
1336 unsigned int vendor_param;
1337
1338 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1339 INTEL_GET_VENDOR_VERB, 0);
1340 if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
1341 return;
1342
1343 /* enable DP1.2 mode */
1344 vendor_param |= INTEL_EN_DP12;
1345 vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
1346 INTEL_SET_VENDOR_VERB, vendor_param);
1347 if (vendor_param == -1)
1348 return;
1349
1350}
1351
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301352static struct snd_soc_dai_ops hdmi_dai_ops = {
1353 .startup = hdac_hdmi_pcm_open,
1354 .shutdown = hdac_hdmi_pcm_close,
1355 .hw_params = hdac_hdmi_set_hw_params,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +05301356 .set_tdm_slot = hdac_hdmi_set_tdm_slot,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301357};
1358
1359/*
1360 * Each converter can support a stream independently. So a dai is created
1361 * based on the number of converter queried.
1362 */
1363static int hdac_hdmi_create_dais(struct hdac_device *hdac,
1364 struct snd_soc_dai_driver **dais,
1365 struct hdac_hdmi_priv *hdmi, int num_dais)
1366{
1367 struct snd_soc_dai_driver *hdmi_dais;
1368 struct hdac_hdmi_cvt *cvt;
1369 char name[NAME_SIZE], dai_name[NAME_SIZE];
1370 int i = 0;
1371 u32 rates, bps;
1372 unsigned int rate_max = 384000, rate_min = 8000;
1373 u64 formats;
1374 int ret;
1375
1376 hdmi_dais = devm_kzalloc(&hdac->dev,
1377 (sizeof(*hdmi_dais) * num_dais),
1378 GFP_KERNEL);
1379 if (!hdmi_dais)
1380 return -ENOMEM;
1381
1382 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
1383 ret = snd_hdac_query_supported_pcm(hdac, cvt->nid,
1384 &rates, &formats, &bps);
1385 if (ret)
1386 return ret;
1387
1388 sprintf(dai_name, "intel-hdmi-hifi%d", i+1);
1389 hdmi_dais[i].name = devm_kstrdup(&hdac->dev,
1390 dai_name, GFP_KERNEL);
1391
1392 if (!hdmi_dais[i].name)
1393 return -ENOMEM;
1394
1395 snprintf(name, sizeof(name), "hifi%d", i+1);
1396 hdmi_dais[i].playback.stream_name =
1397 devm_kstrdup(&hdac->dev, name, GFP_KERNEL);
1398 if (!hdmi_dais[i].playback.stream_name)
1399 return -ENOMEM;
1400
1401 /*
1402 * Set caps based on capability queried from the converter.
1403 * It will be constrained runtime based on ELD queried.
1404 */
1405 hdmi_dais[i].playback.formats = formats;
1406 hdmi_dais[i].playback.rates = rates;
1407 hdmi_dais[i].playback.rate_max = rate_max;
1408 hdmi_dais[i].playback.rate_min = rate_min;
1409 hdmi_dais[i].playback.channels_min = 2;
1410 hdmi_dais[i].playback.channels_max = 2;
1411 hdmi_dais[i].ops = &hdmi_dai_ops;
1412
1413 i++;
1414 }
1415
1416 *dais = hdmi_dais;
1417
1418 return 0;
1419}
1420
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301421/*
1422 * Parse all nodes and store the cvt/pin nids in array
1423 * Add one time initialization for pin and cvt widgets
1424 */
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301425static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
1426 struct snd_soc_dai_driver **dais, int *num_dais)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301427{
1428 hda_nid_t nid;
Sudip Mukherjee3c83ac22015-12-01 14:29:35 +05301429 int i, num_nodes;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301430 struct hdac_device *hdac = &edev->hdac;
1431 struct hdac_hdmi_priv *hdmi = edev->private_data;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301432 int ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301433
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301434 hdac_hdmi_skl_enable_all_pins(hdac);
1435 hdac_hdmi_skl_enable_dp12(hdac);
1436
Sudip Mukherjee3c83ac22015-12-01 14:29:35 +05301437 num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid);
Subhransu S. Prusty541140d2015-12-09 21:46:08 +05301438 if (!nid || num_nodes <= 0) {
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301439 dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n");
1440 return -EINVAL;
1441 }
1442
Sudip Mukherjee3c83ac22015-12-01 14:29:35 +05301443 hdac->num_nodes = num_nodes;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301444 hdac->start_nid = nid;
1445
1446 for (i = 0; i < hdac->num_nodes; i++, nid++) {
1447 unsigned int caps;
1448 unsigned int type;
1449
1450 caps = get_wcaps(hdac, nid);
1451 type = get_wcaps_type(caps);
1452
1453 if (!(caps & AC_WCAP_DIGITAL))
1454 continue;
1455
1456 switch (type) {
1457
1458 case AC_WID_AUD_OUT:
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301459 ret = hdac_hdmi_add_cvt(edev, nid);
1460 if (ret < 0)
1461 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301462 break;
1463
1464 case AC_WID_PIN:
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301465 ret = hdac_hdmi_add_pin(edev, nid);
1466 if (ret < 0)
1467 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301468 break;
1469 }
1470 }
1471
1472 hdac->end_nid = nid;
1473
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301474 if (!hdmi->num_pin || !hdmi->num_cvt)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301475 return -EIO;
1476
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301477 ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt);
1478 if (ret) {
1479 dev_err(&hdac->dev, "Failed to create dais with err: %d\n",
1480 ret);
1481 return ret;
1482 }
1483
1484 *num_dais = hdmi->num_cvt;
1485
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301486 return hdac_hdmi_init_dai_map(edev);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301487}
1488
Pandiyan, Dhinakaranf9318942016-09-21 13:02:48 -07001489static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301490{
1491 struct hdac_ext_device *edev = aptr;
1492 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP754695f2017-02-06 12:09:14 +05301493 struct hdac_hdmi_pin *pin = NULL;
1494 struct hdac_hdmi_port *hport = NULL;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301495 struct snd_soc_codec *codec = edev->scodec;
Jeeja KP2acd8302017-02-06 12:09:18 +05301496 int i;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301497
1498 /* Don't know how this mapping is derived */
1499 hda_nid_t pin_nid = port + 0x04;
1500
Jeeja KP754695f2017-02-06 12:09:14 +05301501 dev_dbg(&edev->hdac.dev, "%s: for pin:%d port=%d\n", __func__,
1502 pin_nid, pipe);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301503
1504 /*
1505 * skip notification during system suspend (but not in runtime PM);
1506 * the state will be updated at resume. Also since the ELD and
1507 * connection states are updated in anyway at the end of the resume,
1508 * we can skip it when received during PM process.
1509 */
1510 if (snd_power_get_state(codec->component.card->snd_card) !=
1511 SNDRV_CTL_POWER_D0)
1512 return;
1513
1514 if (atomic_read(&edev->hdac.in_pm))
1515 return;
1516
1517 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301518 if (pin->nid != pin_nid)
1519 continue;
1520
1521 /* In case of non MST pin, pipe is -1 */
1522 if (pipe == -1) {
Jeeja KP2acd8302017-02-06 12:09:18 +05301523 pin->mst_capable = false;
Jeeja KP754695f2017-02-06 12:09:14 +05301524 /* if not MST, default is port[0] */
1525 hport = &pin->ports[0];
Jeeja KP2acd8302017-02-06 12:09:18 +05301526 goto out;
1527 } else {
1528 for (i = 0; i < pin->num_ports; i++) {
1529 pin->mst_capable = true;
1530 if (pin->ports[i].id == pipe) {
1531 hport = &pin->ports[i];
1532 goto out;
1533 }
1534 }
Jeeja KP754695f2017-02-06 12:09:14 +05301535 }
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301536 }
Jeeja KP754695f2017-02-06 12:09:14 +05301537
Jeeja KP2acd8302017-02-06 12:09:18 +05301538out:
1539 if (pin && hport)
Jeeja KP754695f2017-02-06 12:09:14 +05301540 hdac_hdmi_present_sense(pin, hport);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301541}
1542
1543static struct i915_audio_component_audio_ops aops = {
1544 .pin_eld_notify = hdac_hdmi_eld_notify_cb,
1545};
1546
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301547static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card,
1548 int device)
1549{
1550 struct snd_soc_pcm_runtime *rtd;
1551
1552 list_for_each_entry(rtd, &card->rtd_list, list) {
1553 if (rtd->pcm && (rtd->pcm->device == device))
1554 return rtd->pcm;
1555 }
1556
1557 return NULL;
1558}
1559
Jeeja KP62490012017-02-07 19:09:49 +05301560int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device,
1561 struct snd_soc_jack *jack)
Jeeja KP4a3478d2016-02-12 07:46:06 +05301562{
Jeeja KP4a3478d2016-02-12 07:46:06 +05301563 struct snd_soc_codec *codec = dai->codec;
1564 struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301565 struct hdac_hdmi_priv *hdmi = edev->private_data;
1566 struct hdac_hdmi_pcm *pcm;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301567 struct snd_pcm *snd_pcm;
1568 int err;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301569
1570 /*
1571 * this is a new PCM device, create new pcm and
1572 * add to the pcm list
1573 */
1574 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
1575 if (!pcm)
1576 return -ENOMEM;
1577 pcm->pcm_id = device;
1578 pcm->cvt = hdmi->dai_map[dai->id].cvt;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301579 pcm->jack_event = 0;
Jeeja KP62490012017-02-07 19:09:49 +05301580 pcm->jack = jack;
Jeeja KPab1eea12017-01-24 21:49:05 +05301581 mutex_init(&pcm->lock);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301582 INIT_LIST_HEAD(&pcm->port_list);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301583 snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device);
1584 if (snd_pcm) {
1585 err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap);
1586 if (err < 0) {
1587 dev_err(&edev->hdac.dev,
1588 "chmap control add failed with err: %d for pcm: %d\n",
1589 err, device);
1590 kfree(pcm);
1591 return err;
1592 }
1593 }
1594
Jeeja KP4a3478d2016-02-12 07:46:06 +05301595 list_add_tail(&pcm->head, &hdmi->pcm_list);
1596
Jeeja KP62490012017-02-07 19:09:49 +05301597 return 0;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301598}
1599EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init);
1600
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301601static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev,
1602 struct hdac_hdmi_priv *hdmi, bool detect_pin_caps)
1603{
1604 int i;
1605 struct hdac_hdmi_pin *pin;
1606
1607 list_for_each_entry(pin, &hdmi->pin_list, head) {
1608 if (detect_pin_caps) {
1609
1610 if (hdac_hdmi_get_port_len(edev, pin->nid) == 0)
1611 pin->mst_capable = false;
1612 else
1613 pin->mst_capable = true;
1614 }
1615
1616 for (i = 0; i < pin->num_ports; i++) {
1617 if (!pin->mst_capable && i > 0)
1618 continue;
1619
1620 hdac_hdmi_present_sense(pin, &pin->ports[i]);
1621 }
1622 }
1623}
1624
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301625static int hdmi_codec_probe(struct snd_soc_codec *codec)
1626{
1627 struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
1628 struct hdac_hdmi_priv *hdmi = edev->private_data;
1629 struct snd_soc_dapm_context *dapm =
1630 snd_soc_component_get_dapm(&codec->component);
Vinod Koulb2047e92016-05-12 08:58:55 +05301631 struct hdac_ext_link *hlink = NULL;
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301632 int ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301633
1634 edev->scodec = codec;
1635
Vinod Koulb2047e92016-05-12 08:58:55 +05301636 /*
1637 * hold the ref while we probe, also no need to drop the ref on
1638 * exit, we call pm_runtime_suspend() so that will do for us
1639 */
1640 hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301641 if (!hlink) {
1642 dev_err(&edev->hdac.dev, "hdac link not found\n");
1643 return -EIO;
1644 }
1645
Vinod Koulb2047e92016-05-12 08:58:55 +05301646 snd_hdac_ext_bus_link_get(edev->ebus, hlink);
1647
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301648 ret = create_fill_widget_route_map(dapm);
1649 if (ret < 0)
1650 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301651
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301652 aops.audio_ptr = edev;
1653 ret = snd_hdac_i915_register_notifier(&aops);
1654 if (ret < 0) {
1655 dev_err(&edev->hdac.dev, "notifier register failed: err: %d\n",
1656 ret);
1657 return ret;
1658 }
1659
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301660 hdac_hdmi_present_sense_all_pins(edev, hdmi, true);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301661 /* Imp: Store the card pointer in hda_codec */
1662 edev->card = dapm->card->snd_card;
1663
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301664 /*
1665 * hdac_device core already sets the state to active and calls
1666 * get_noresume. So enable runtime and set the device to suspend.
1667 */
1668 pm_runtime_enable(&edev->hdac.dev);
1669 pm_runtime_put(&edev->hdac.dev);
1670 pm_runtime_suspend(&edev->hdac.dev);
1671
1672 return 0;
1673}
1674
1675static int hdmi_codec_remove(struct snd_soc_codec *codec)
1676{
1677 struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
1678
1679 pm_runtime_disable(&edev->hdac.dev);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301680 return 0;
1681}
1682
Jeeja KP571d5072016-02-22 07:50:33 +05301683#ifdef CONFIG_PM
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301684static int hdmi_codec_prepare(struct device *dev)
1685{
1686 struct hdac_ext_device *edev = to_hda_ext_device(dev);
1687 struct hdac_device *hdac = &edev->hdac;
1688
1689 pm_runtime_get_sync(&edev->hdac.dev);
1690
1691 /*
1692 * Power down afg.
1693 * codec_read is preferred over codec_write to set the power state.
1694 * This way verb is send to set the power state and response
1695 * is received. So setting power state is ensured without using loop
1696 * to read the state.
1697 */
1698 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1699 AC_PWRST_D3);
1700
1701 return 0;
1702}
1703
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301704static void hdmi_codec_complete(struct device *dev)
Jeeja KP571d5072016-02-22 07:50:33 +05301705{
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301706 struct hdac_ext_device *edev = to_hda_ext_device(dev);
Jeeja KP571d5072016-02-22 07:50:33 +05301707 struct hdac_hdmi_priv *hdmi = edev->private_data;
Jeeja KP571d5072016-02-22 07:50:33 +05301708 struct hdac_device *hdac = &edev->hdac;
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301709
1710 /* Power up afg */
1711 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1712 AC_PWRST_D0);
Jeeja KP571d5072016-02-22 07:50:33 +05301713
1714 hdac_hdmi_skl_enable_all_pins(&edev->hdac);
1715 hdac_hdmi_skl_enable_dp12(&edev->hdac);
1716
Jeeja KP571d5072016-02-22 07:50:33 +05301717 /*
1718 * As the ELD notify callback request is not entertained while the
1719 * device is in suspend state. Need to manually check detection of
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301720 * all pins here. pin capablity change is not support, so use the
1721 * already set pin caps.
Jeeja KP571d5072016-02-22 07:50:33 +05301722 */
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301723 hdac_hdmi_present_sense_all_pins(edev, hdmi, false);
Jeeja KP571d5072016-02-22 07:50:33 +05301724
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301725 pm_runtime_put_sync(&edev->hdac.dev);
Jeeja KP571d5072016-02-22 07:50:33 +05301726}
1727#else
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301728#define hdmi_codec_prepare NULL
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301729#define hdmi_codec_complete NULL
Jeeja KP571d5072016-02-22 07:50:33 +05301730#endif
1731
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301732static struct snd_soc_codec_driver hdmi_hda_codec = {
1733 .probe = hdmi_codec_probe,
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301734 .remove = hdmi_codec_remove,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301735 .idle_bias_off = true,
1736};
1737
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301738static void hdac_hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx,
1739 unsigned char *chmap)
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);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301744
Jeeja KPab1eea12017-01-24 21:49:05 +05301745 memcpy(chmap, pcm->chmap, ARRAY_SIZE(pcm->chmap));
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301746}
1747
1748static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
1749 unsigned char *chmap, int prepared)
1750{
1751 struct hdac_ext_device *edev = to_ehdac_device(hdac);
1752 struct hdac_hdmi_priv *hdmi = edev->private_data;
1753 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301754 struct hdac_hdmi_port *port;
1755
1756 if (list_empty(&pcm->port_list))
1757 return;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301758
Jeeja KPab1eea12017-01-24 21:49:05 +05301759 mutex_lock(&pcm->lock);
1760 pcm->chmap_set = true;
1761 memcpy(pcm->chmap, chmap, ARRAY_SIZE(pcm->chmap));
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301762 list_for_each_entry(port, &pcm->port_list, head)
1763 if (prepared)
1764 hdac_hdmi_setup_audio_infoframe(edev, pcm, port);
Jeeja KPab1eea12017-01-24 21:49:05 +05301765 mutex_unlock(&pcm->lock);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301766}
1767
1768static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
1769{
1770 struct hdac_ext_device *edev = to_ehdac_device(hdac);
1771 struct hdac_hdmi_priv *hdmi = edev->private_data;
1772 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301773
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301774 if (list_empty(&pcm->port_list))
1775 return false;
1776
1777 return true;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301778}
1779
1780static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
1781{
1782 struct hdac_ext_device *edev = to_ehdac_device(hdac);
1783 struct hdac_hdmi_priv *hdmi = edev->private_data;
1784 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301785 struct hdac_hdmi_port *port;
1786
1787 if (list_empty(&pcm->port_list))
1788 return 0;
1789
1790 port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head);
1791
1792 if (!port)
1793 return 0;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301794
Jeeja KP754695f2017-02-06 12:09:14 +05301795 if (!port || !port->eld.eld_valid)
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301796 return 0;
1797
Jeeja KP754695f2017-02-06 12:09:14 +05301798 return port->eld.info.spk_alloc;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301799}
1800
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301801static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
1802{
1803 struct hdac_device *codec = &edev->hdac;
1804 struct hdac_hdmi_priv *hdmi_priv;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301805 struct snd_soc_dai_driver *hdmi_dais = NULL;
Vinod Koulb2047e92016-05-12 08:58:55 +05301806 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301807 int num_dais = 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301808 int ret = 0;
1809
Vinod Koulb2047e92016-05-12 08:58:55 +05301810 /* hold the ref while we probe */
1811 hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301812 if (!hlink) {
1813 dev_err(&edev->hdac.dev, "hdac link not found\n");
1814 return -EIO;
1815 }
1816
Vinod Koulb2047e92016-05-12 08:58:55 +05301817 snd_hdac_ext_bus_link_get(edev->ebus, hlink);
1818
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301819 hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
1820 if (hdmi_priv == NULL)
1821 return -ENOMEM;
1822
1823 edev->private_data = hdmi_priv;
Subhransu S. Prustybcced702016-04-14 10:07:30 +05301824 snd_hdac_register_chmap_ops(codec, &hdmi_priv->chmap);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301825 hdmi_priv->chmap.ops.get_chmap = hdac_hdmi_get_chmap;
1826 hdmi_priv->chmap.ops.set_chmap = hdac_hdmi_set_chmap;
1827 hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached;
1828 hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301829
1830 dev_set_drvdata(&codec->dev, edev);
1831
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301832 INIT_LIST_HEAD(&hdmi_priv->pin_list);
1833 INIT_LIST_HEAD(&hdmi_priv->cvt_list);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301834 INIT_LIST_HEAD(&hdmi_priv->pcm_list);
1835 mutex_init(&hdmi_priv->pin_mutex);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301836
Ramesh Babuaeaccef2016-02-17 21:34:01 +05301837 /*
1838 * Turned off in the runtime_suspend during the first explicit
1839 * pm_runtime_suspend call.
1840 */
1841 ret = snd_hdac_display_power(edev->hdac.bus, true);
1842 if (ret < 0) {
1843 dev_err(&edev->hdac.dev,
1844 "Cannot turn on display power on i915 err: %d\n",
1845 ret);
1846 return ret;
1847 }
1848
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301849 ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais);
1850 if (ret < 0) {
1851 dev_err(&codec->dev,
1852 "Failed in parse and map nid with err: %d\n", ret);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301853 return ret;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301854 }
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301855
1856 /* ASoC specific initialization */
Vinod Koulb2047e92016-05-12 08:58:55 +05301857 ret = snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
1858 hdmi_dais, num_dais);
1859
1860 snd_hdac_ext_bus_link_put(edev->ebus, hlink);
1861
1862 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301863}
1864
1865static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
1866{
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301867 struct hdac_hdmi_priv *hdmi = edev->private_data;
1868 struct hdac_hdmi_pin *pin, *pin_next;
1869 struct hdac_hdmi_cvt *cvt, *cvt_next;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301870 struct hdac_hdmi_pcm *pcm, *pcm_next;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301871 struct hdac_hdmi_port *port;
Jeeja KP754695f2017-02-06 12:09:14 +05301872 int i;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301873
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301874 snd_soc_unregister_codec(&edev->hdac.dev);
1875
Jeeja KP4a3478d2016-02-12 07:46:06 +05301876 list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) {
1877 pcm->cvt = NULL;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301878 if (list_empty(&pcm->port_list))
1879 continue;
1880
1881 list_for_each_entry(port, &pcm->port_list, head)
1882 port = NULL;
1883
Jeeja KP4a3478d2016-02-12 07:46:06 +05301884 list_del(&pcm->head);
1885 kfree(pcm);
1886 }
1887
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301888 list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) {
1889 list_del(&cvt->head);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301890 kfree(cvt->name);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301891 kfree(cvt);
1892 }
1893
1894 list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301895 for (i = 0; i < pin->num_ports; i++)
1896 pin->ports[i].pin = NULL;
1897 kfree(pin->ports);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301898 list_del(&pin->head);
1899 kfree(pin);
1900 }
1901
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301902 return 0;
1903}
1904
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301905#ifdef CONFIG_PM
1906static int hdac_hdmi_runtime_suspend(struct device *dev)
1907{
1908 struct hdac_ext_device *edev = to_hda_ext_device(dev);
1909 struct hdac_device *hdac = &edev->hdac;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301910 struct hdac_bus *bus = hdac->bus;
Vinod Koulb2047e92016-05-12 08:58:55 +05301911 struct hdac_ext_bus *ebus = hbus_to_ebus(bus);
1912 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301913 int err;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301914
1915 dev_dbg(dev, "Enter: %s\n", __func__);
1916
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301917 /* controller may not have been initialized for the first time */
1918 if (!bus)
1919 return 0;
1920
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301921 /*
1922 * Power down afg.
1923 * codec_read is preferred over codec_write to set the power state.
1924 * This way verb is send to set the power state and response
1925 * is received. So setting power state is ensured without using loop
1926 * to read the state.
1927 */
1928 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1929 AC_PWRST_D3);
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301930 err = snd_hdac_display_power(bus, false);
1931 if (err < 0) {
1932 dev_err(bus->dev, "Cannot turn on display power on i915\n");
1933 return err;
1934 }
1935
Vinod Koulb2047e92016-05-12 08:58:55 +05301936 hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301937 if (!hlink) {
1938 dev_err(dev, "hdac link not found\n");
1939 return -EIO;
1940 }
1941
Vinod Koulb2047e92016-05-12 08:58:55 +05301942 snd_hdac_ext_bus_link_put(ebus, hlink);
1943
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301944 return 0;
1945}
1946
1947static int hdac_hdmi_runtime_resume(struct device *dev)
1948{
1949 struct hdac_ext_device *edev = to_hda_ext_device(dev);
1950 struct hdac_device *hdac = &edev->hdac;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301951 struct hdac_bus *bus = hdac->bus;
Vinod Koulb2047e92016-05-12 08:58:55 +05301952 struct hdac_ext_bus *ebus = hbus_to_ebus(bus);
1953 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301954 int err;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301955
1956 dev_dbg(dev, "Enter: %s\n", __func__);
1957
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301958 /* controller may not have been initialized for the first time */
1959 if (!bus)
1960 return 0;
1961
Vinod Koulb2047e92016-05-12 08:58:55 +05301962 hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301963 if (!hlink) {
1964 dev_err(dev, "hdac link not found\n");
1965 return -EIO;
1966 }
1967
Vinod Koulb2047e92016-05-12 08:58:55 +05301968 snd_hdac_ext_bus_link_get(ebus, hlink);
1969
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05301970 err = snd_hdac_display_power(bus, true);
1971 if (err < 0) {
1972 dev_err(bus->dev, "Cannot turn on display power on i915\n");
1973 return err;
1974 }
1975
Subhransu S. Prustyab85f5b2016-02-17 21:34:02 +05301976 hdac_hdmi_skl_enable_all_pins(&edev->hdac);
1977 hdac_hdmi_skl_enable_dp12(&edev->hdac);
1978
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301979 /* Power up afg */
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301980 snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
1981 AC_PWRST_D0);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301982
1983 return 0;
1984}
1985#else
1986#define hdac_hdmi_runtime_suspend NULL
1987#define hdac_hdmi_runtime_resume NULL
1988#endif
1989
1990static const struct dev_pm_ops hdac_hdmi_pm = {
1991 SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301992 .prepare = hdmi_codec_prepare,
Subhransu S. Prusty0fee1792016-04-01 13:36:25 +05301993 .complete = hdmi_codec_complete,
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301994};
1995
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301996static const struct hda_device_id hdmi_list[] = {
1997 HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
Jeeja KPe2304802016-03-11 10:12:55 +05301998 HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0),
Shreyas NCcc216882016-07-11 22:02:09 +05301999 HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0),
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302000 {}
2001};
2002
2003MODULE_DEVICE_TABLE(hdaudio, hdmi_list);
2004
2005static struct hdac_ext_driver hdmi_driver = {
2006 . hdac = {
2007 .driver = {
2008 .name = "HDMI HDA Codec",
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302009 .pm = &hdac_hdmi_pm,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302010 },
2011 .id_table = hdmi_list,
2012 },
2013 .probe = hdac_hdmi_dev_probe,
2014 .remove = hdac_hdmi_dev_remove,
2015};
2016
2017static int __init hdmi_init(void)
2018{
2019 return snd_hda_ext_driver_register(&hdmi_driver);
2020}
2021
2022static void __exit hdmi_exit(void)
2023{
2024 snd_hda_ext_driver_unregister(&hdmi_driver);
2025}
2026
2027module_init(hdmi_init);
2028module_exit(hdmi_exit);
2029
2030MODULE_LICENSE("GPL v2");
2031MODULE_DESCRIPTION("HDMI HD codec");
2032MODULE_AUTHOR("Samreen Nilofer<samreen.nilofer@intel.com>");
2033MODULE_AUTHOR("Subhransu S. Prusty<subhransu.s.prusty@intel.com>");