blob: 660e0587f3999394296c37f8975c7f27b078d7ed [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;
Rakesh Ughreja3787a392018-06-01 22:53:49 -050088 struct hdac_device *hdev;
Jeeja KP754695f2017-02-06 12:09:14 +053089};
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;
Jeeja KP0324e512017-02-07 19:09:55 +053098 const char *jack_pin;
99 struct snd_soc_dapm_context *dapm;
100 const char *output_pin;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530101};
102
Jeeja KP4a3478d2016-02-12 07:46:06 +0530103struct hdac_hdmi_pcm {
104 struct list_head head;
105 int pcm_id;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530106 struct list_head port_list;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530107 struct hdac_hdmi_cvt *cvt;
Jeeja KP62490012017-02-07 19:09:49 +0530108 struct snd_soc_jack *jack;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530109 int stream_tag;
110 int channels;
111 int format;
Jeeja KPab1eea12017-01-24 21:49:05 +0530112 bool chmap_set;
113 unsigned char chmap[8]; /* ALSA API channel-map */
114 struct mutex lock;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530115 int jack_event;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530116};
117
Jeeja KP754695f2017-02-06 12:09:14 +0530118struct hdac_hdmi_dai_port_map {
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530119 int dai_id;
Jeeja KP754695f2017-02-06 12:09:14 +0530120 struct hdac_hdmi_port *port;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530121 struct hdac_hdmi_cvt *cvt;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530122};
123
Bard liao019033c2018-11-11 05:18:46 +0800124/*
125 * pin to port mapping table where the value indicate the pin number and
126 * the index indicate the port number with 1 base.
127 */
128static const int icl_pin2port_map[] = {0x4, 0x6, 0x8, 0xa, 0xb};
129
Pradeep Tewani5622bc92017-07-20 11:40:56 +0530130struct hdac_hdmi_drv_data {
131 unsigned int vendor_nid;
Bard liao019033c2018-11-11 05:18:46 +0800132 const int *port_map; /* pin to port mapping table */
133 int port_num;
Pradeep Tewani5622bc92017-07-20 11:40:56 +0530134};
135
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530136struct hdac_hdmi_priv {
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500137 struct hdac_device *hdev;
138 struct snd_soc_component *component;
139 struct snd_card *card;
Jeeja KP754695f2017-02-06 12:09:14 +0530140 struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS];
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530141 struct list_head pin_list;
142 struct list_head cvt_list;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530143 struct list_head pcm_list;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +0530144 int num_pin;
145 int num_cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530146 int num_ports;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530147 struct mutex pin_mutex;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530148 struct hdac_chmap chmap;
Pradeep Tewani5622bc92017-07-20 11:40:56 +0530149 struct hdac_hdmi_drv_data *drv_data;
Kuninori Morimoto1e02dac2017-12-20 01:48:13 +0000150 struct snd_soc_dai_driver *dai_drv;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530151};
152
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500153#define hdev_to_hdmi_priv(_hdev) dev_get_drvdata(&(_hdev)->dev)
Ughreja, Rakesh Ab09b1c32017-12-01 14:43:17 +0530154
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530155static struct hdac_hdmi_pcm *
156hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi,
157 struct hdac_hdmi_cvt *cvt)
158{
159 struct hdac_hdmi_pcm *pcm = NULL;
Jeeja KP1de777f2017-01-10 17:57:48 +0530160
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530161 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
162 if (pcm->cvt == cvt)
163 break;
164 }
165
166 return pcm;
167}
Jeeja KP1de777f2017-01-10 17:57:48 +0530168
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530169static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
170 struct hdac_hdmi_port *port, bool is_connect)
171{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500172 struct hdac_device *hdev = port->pin->hdev;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530173
Jeeja KP0324e512017-02-07 19:09:55 +0530174 if (is_connect)
175 snd_soc_dapm_enable_pin(port->dapm, port->jack_pin);
176 else
177 snd_soc_dapm_disable_pin(port->dapm, port->jack_pin);
178
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530179 if (is_connect) {
180 /*
181 * Report Jack connect event when a device is connected
182 * for the first time where same PCM is attached to multiple
183 * ports.
184 */
185 if (pcm->jack_event == 0) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500186 dev_dbg(&hdev->dev,
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530187 "jack report for pcm=%d\n",
188 pcm->pcm_id);
Jeeja KP62490012017-02-07 19:09:49 +0530189 snd_soc_jack_report(pcm->jack, SND_JACK_AVOUT,
190 SND_JACK_AVOUT);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530191 }
192 pcm->jack_event++;
193 } else {
194 /*
195 * Report Jack disconnect event when a device is disconnected
196 * is the only last connected device when same PCM is attached
197 * to multiple ports.
198 */
199 if (pcm->jack_event == 1)
Jeeja KP62490012017-02-07 19:09:49 +0530200 snd_soc_jack_report(pcm->jack, 0, SND_JACK_AVOUT);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530201 if (pcm->jack_event > 0)
202 pcm->jack_event--;
203 }
Jeeja KP0324e512017-02-07 19:09:55 +0530204
205 snd_soc_dapm_sync(port->dapm);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530206}
207
Jeeja KPfc181b02017-02-07 19:09:45 +0530208/* MST supported verbs */
209/*
210 * Get the no devices that can be connected to a port on the Pin widget.
211 */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500212static int hdac_hdmi_get_port_len(struct hdac_device *hdev, hda_nid_t nid)
Jeeja KPfc181b02017-02-07 19:09:45 +0530213{
214 unsigned int caps;
215 unsigned int type, param;
216
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500217 caps = get_wcaps(hdev, nid);
Jeeja KPfc181b02017-02-07 19:09:45 +0530218 type = get_wcaps_type(caps);
219
220 if (!(caps & AC_WCAP_DIGITAL) || (type != AC_WID_PIN))
221 return 0;
222
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500223 param = snd_hdac_read_parm_uncached(hdev, nid, AC_PAR_DEVLIST_LEN);
Jeeja KPfc181b02017-02-07 19:09:45 +0530224 if (param == -1)
225 return param;
226
227 return param & AC_DEV_LIST_LEN_MASK;
228}
229
230/*
231 * Get the port entry select on the pin. Return the port entry
232 * id selected on the pin. Return 0 means the first port entry
233 * is selected or MST is not supported.
234 */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500235static int hdac_hdmi_port_select_get(struct hdac_device *hdev,
Jeeja KPfc181b02017-02-07 19:09:45 +0530236 struct hdac_hdmi_port *port)
237{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500238 return snd_hdac_codec_read(hdev, port->pin->nid,
Jeeja KPfc181b02017-02-07 19:09:45 +0530239 0, AC_VERB_GET_DEVICE_SEL, 0);
240}
241
242/*
243 * Sets the selected port entry for the configuring Pin widget verb.
244 * returns error if port set is not equal to port get otherwise success
245 */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500246static int hdac_hdmi_port_select_set(struct hdac_device *hdev,
Jeeja KPfc181b02017-02-07 19:09:45 +0530247 struct hdac_hdmi_port *port)
248{
249 int num_ports;
250
251 if (!port->pin->mst_capable)
252 return 0;
253
254 /* AC_PAR_DEVLIST_LEN is 0 based. */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500255 num_ports = hdac_hdmi_get_port_len(hdev, port->pin->nid);
Jeeja KPfc181b02017-02-07 19:09:45 +0530256 if (num_ports < 0)
257 return -EIO;
258 /*
259 * Device List Length is a 0 based integer value indicating the
260 * number of sink device that a MST Pin Widget can support.
261 */
262 if (num_ports + 1 < port->id)
263 return 0;
264
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500265 snd_hdac_codec_write(hdev, port->pin->nid, 0,
Jeeja KPfc181b02017-02-07 19:09:45 +0530266 AC_VERB_SET_DEVICE_SEL, port->id);
267
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500268 if (port->id != hdac_hdmi_port_select_get(hdev, port))
Jeeja KPfc181b02017-02-07 19:09:45 +0530269 return -EIO;
270
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500271 dev_dbg(&hdev->dev, "Selected the port=%d\n", port->id);
Jeeja KPfc181b02017-02-07 19:09:45 +0530272
273 return 0;
274}
275
Subhransu S. Prusty28890992016-04-14 10:07:34 +0530276static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi,
277 int pcm_idx)
278{
279 struct hdac_hdmi_pcm *pcm;
280
281 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
282 if (pcm->pcm_id == pcm_idx)
283 return pcm;
284 }
285
286 return NULL;
287}
288
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530289static unsigned int sad_format(const u8 *sad)
290{
291 return ((sad[0] >> 0x3) & 0x1f);
292}
293
294static unsigned int sad_sample_bits_lpcm(const u8 *sad)
295{
296 return (sad[2] & 7);
297}
298
299static int hdac_hdmi_eld_limit_formats(struct snd_pcm_runtime *runtime,
300 void *eld)
301{
302 u64 formats = SNDRV_PCM_FMTBIT_S16;
303 int i;
304 const u8 *sad, *eld_buf = eld;
305
306 sad = drm_eld_sad(eld_buf);
307 if (!sad)
308 goto format_constraint;
309
310 for (i = drm_eld_sad_count(eld_buf); i > 0; i--, sad += 3) {
311 if (sad_format(sad) == 1) { /* AUDIO_CODING_TYPE_LPCM */
312
313 /*
314 * the controller support 20 and 24 bits in 32 bit
315 * container so we set S32
316 */
317 if (sad_sample_bits_lpcm(sad) & 0x6)
318 formats |= SNDRV_PCM_FMTBIT_S32;
319 }
320 }
321
322format_constraint:
323 return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
324 formats);
325
326}
327
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530328static void
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500329hdac_hdmi_set_dip_index(struct hdac_device *hdev, hda_nid_t pin_nid,
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530330 int packet_index, int byte_index)
331{
332 int val;
333
334 val = (packet_index << 5) | (byte_index & 0x1f);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500335 snd_hdac_codec_write(hdev, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530336}
337
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530338struct dp_audio_infoframe {
339 u8 type; /* 0x84 */
340 u8 len; /* 0x1b */
341 u8 ver; /* 0x11 << 2 */
342
343 u8 CC02_CT47; /* match with HDMI infoframe from this on */
344 u8 SS01_SF24;
345 u8 CXT04;
346 u8 CA;
347 u8 LFEPBL01_LSV36_DM_INH7;
348};
349
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500350static int hdac_hdmi_setup_audio_infoframe(struct hdac_device *hdev,
Jeeja KP754695f2017-02-06 12:09:14 +0530351 struct hdac_hdmi_pcm *pcm, struct hdac_hdmi_port *port)
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530352{
353 uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
354 struct hdmi_audio_infoframe frame;
Jeeja KP754695f2017-02-06 12:09:14 +0530355 struct hdac_hdmi_pin *pin = port->pin;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530356 struct dp_audio_infoframe dp_ai;
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500357 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KPab1eea12017-01-24 21:49:05 +0530358 struct hdac_hdmi_cvt *cvt = pcm->cvt;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530359 u8 *dip;
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530360 int ret;
361 int i;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530362 const u8 *eld_buf;
363 u8 conn_type;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530364 int channels, ca;
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530365
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500366 ca = snd_hdac_channel_allocation(hdev, port->eld.info.spk_alloc,
Jeeja KPab1eea12017-01-24 21:49:05 +0530367 pcm->channels, pcm->chmap_set, true, pcm->chmap);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530368
369 channels = snd_hdac_get_active_channels(ca);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500370 hdmi->chmap.ops.set_channel_count(hdev, cvt->nid, channels);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530371
372 snd_hdac_setup_channel_mapping(&hdmi->chmap, pin->nid, false, ca,
Jeeja KPab1eea12017-01-24 21:49:05 +0530373 pcm->channels, pcm->chmap, pcm->chmap_set);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530374
Jeeja KP754695f2017-02-06 12:09:14 +0530375 eld_buf = port->eld.eld_buffer;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530376 conn_type = drm_eld_get_conn_type(eld_buf);
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530377
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530378 switch (conn_type) {
379 case DRM_ELD_CONN_TYPE_HDMI:
380 hdmi_audio_infoframe_init(&frame);
381
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530382 frame.channels = channels;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530383 frame.channel_allocation = ca;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530384
385 ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
386 if (ret < 0)
387 return ret;
388
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530389 break;
390
391 case DRM_ELD_CONN_TYPE_DP:
392 memset(&dp_ai, 0, sizeof(dp_ai));
393 dp_ai.type = 0x84;
394 dp_ai.len = 0x1b;
395 dp_ai.ver = 0x11 << 2;
396 dp_ai.CC02_CT47 = channels - 1;
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530397 dp_ai.CA = ca;
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530398
399 dip = (u8 *)&dp_ai;
400 break;
401
402 default:
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500403 dev_err(&hdev->dev, "Invalid connection type: %d\n", conn_type);
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530404 return -EIO;
405 }
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530406
407 /* stop infoframe transmission */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500408 hdac_hdmi_set_dip_index(hdev, pin->nid, 0x0, 0x0);
409 snd_hdac_codec_write(hdev, pin->nid, 0,
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530410 AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE);
411
412
413 /* Fill infoframe. Index auto-incremented */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500414 hdac_hdmi_set_dip_index(hdev, pin->nid, 0x0, 0x0);
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530415 if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
Subhransu S. Prusty391005e2016-03-10 09:04:07 +0530416 for (i = 0; i < sizeof(buffer); i++)
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500417 snd_hdac_codec_write(hdev, pin->nid, 0,
Subhransu S. Prusty391005e2016-03-10 09:04:07 +0530418 AC_VERB_SET_HDMI_DIP_DATA, buffer[i]);
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530419 } else {
420 for (i = 0; i < sizeof(dp_ai); i++)
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500421 snd_hdac_codec_write(hdev, pin->nid, 0,
Subhransu S. Prusty478f544e2016-02-12 07:46:09 +0530422 AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
423 }
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530424
425 /* Start infoframe */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500426 hdac_hdmi_set_dip_index(hdev, pin->nid, 0x0, 0x0);
427 snd_hdac_codec_write(hdev, pin->nid, 0,
Subhransu S. Prustya657f1d2015-11-10 18:42:09 +0530428 AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST);
429
430 return 0;
431}
432
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530433static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
434 unsigned int tx_mask, unsigned int rx_mask,
435 int slots, int slot_width)
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530436{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500437 struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
438 struct hdac_device *hdev = hdmi->hdev;
Jeeja KP754695f2017-02-06 12:09:14 +0530439 struct hdac_hdmi_dai_port_map *dai_map;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530440 struct hdac_hdmi_pcm *pcm;
441
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500442 dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, tx_mask);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530443
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530444 dai_map = &hdmi->dai_map[dai->id];
445
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530446 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530447
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530448 if (pcm)
449 pcm->stream_tag = (tx_mask << 4);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530450
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530451 return 0;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530452}
453
454static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
455 struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai)
456{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500457 struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
Jeeja KP754695f2017-02-06 12:09:14 +0530458 struct hdac_hdmi_dai_port_map *dai_map;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530459 struct hdac_hdmi_pcm *pcm;
460 int format;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530461
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530462 dai_map = &hdmi->dai_map[dai->id];
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530463
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530464 format = snd_hdac_calc_stream_format(params_rate(hparams),
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530465 params_channels(hparams), params_format(hparams),
Jeeja KP66d6bbc2017-03-24 23:10:26 +0530466 dai->driver->playback.sig_bits, 0);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530467
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530468 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
469 if (!pcm)
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530470 return -EIO;
471
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530472 pcm->format = format;
473 pcm->channels = params_channels(hparams);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530474
475 return 0;
476}
477
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500478static int hdac_hdmi_query_port_connlist(struct hdac_device *hdev,
Jeeja KP754695f2017-02-06 12:09:14 +0530479 struct hdac_hdmi_pin *pin,
480 struct hdac_hdmi_port *port)
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530481{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500482 if (!(get_wcaps(hdev, pin->nid) & AC_WCAP_CONN_LIST)) {
483 dev_warn(&hdev->dev,
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530484 "HDMI: pin %d wcaps %#x does not support connection list\n",
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500485 pin->nid, get_wcaps(hdev, pin->nid));
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530486 return -EINVAL;
487 }
488
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500489 if (hdac_hdmi_port_select_set(hdev, port) < 0)
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530490 return -EIO;
491
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500492 port->num_mux_nids = snd_hdac_get_connections(hdev, pin->nid,
Jeeja KP754695f2017-02-06 12:09:14 +0530493 port->mux_nids, HDA_MAX_CONNECTIONS);
494 if (port->num_mux_nids == 0)
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500495 dev_warn(&hdev->dev,
Jeeja KP754695f2017-02-06 12:09:14 +0530496 "No connections found for pin:port %d:%d\n",
497 pin->nid, port->id);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530498
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500499 dev_dbg(&hdev->dev, "num_mux_nids %d for pin:port %d:%d\n",
Jeeja KP754695f2017-02-06 12:09:14 +0530500 port->num_mux_nids, pin->nid, port->id);
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530501
Jeeja KP754695f2017-02-06 12:09:14 +0530502 return port->num_mux_nids;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530503}
504
505/*
Jeeja KP754695f2017-02-06 12:09:14 +0530506 * Query pcm list and return port to which stream is routed.
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530507 *
Jeeja KP754695f2017-02-06 12:09:14 +0530508 * Also query connection list of the pin, to validate the cvt to port map.
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530509 *
Jeeja KP754695f2017-02-06 12:09:14 +0530510 * Same stream rendering to multiple ports simultaneously can be done
511 * possibly, but not supported for now in driver. So return the first port
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530512 * connected.
513 */
Jeeja KP754695f2017-02-06 12:09:14 +0530514static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500515 struct hdac_device *hdev,
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530516 struct hdac_hdmi_priv *hdmi,
517 struct hdac_hdmi_cvt *cvt)
518{
519 struct hdac_hdmi_pcm *pcm;
Jeeja KP754695f2017-02-06 12:09:14 +0530520 struct hdac_hdmi_port *port = NULL;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530521 int ret, i;
522
523 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
524 if (pcm->cvt == cvt) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530525 if (list_empty(&pcm->port_list))
526 continue;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530527
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530528 list_for_each_entry(port, &pcm->port_list, head) {
529 mutex_lock(&pcm->lock);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500530 ret = hdac_hdmi_query_port_connlist(hdev,
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530531 port->pin, port);
532 mutex_unlock(&pcm->lock);
533 if (ret < 0)
534 continue;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530535
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530536 for (i = 0; i < port->num_mux_nids; i++) {
537 if (port->mux_nids[i] == cvt->nid &&
538 port->eld.monitor_present &&
539 port->eld.eld_valid)
540 return port;
541 }
542 }
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530543 }
544 }
545
546 return NULL;
547}
548
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530549/*
550 * This tries to get a valid pin and set the HW constraints based on the
551 * ELD. Even if a valid pin is not found return success so that device open
552 * doesn't fail.
553 */
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530554static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
555 struct snd_soc_dai *dai)
556{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500557 struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
558 struct hdac_device *hdev = hdmi->hdev;
Jeeja KP754695f2017-02-06 12:09:14 +0530559 struct hdac_hdmi_dai_port_map *dai_map;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530560 struct hdac_hdmi_cvt *cvt;
Jeeja KP754695f2017-02-06 12:09:14 +0530561 struct hdac_hdmi_port *port;
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530562 int ret;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530563
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530564 dai_map = &hdmi->dai_map[dai->id];
565
Subhransu S. Prusty148569f2016-02-12 07:46:07 +0530566 cvt = dai_map->cvt;
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500567 port = hdac_hdmi_get_port_from_cvt(hdev, hdmi, cvt);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530568
569 /*
570 * To make PA and other userland happy.
571 * userland scans devices so returning error does not help.
572 */
Jeeja KP754695f2017-02-06 12:09:14 +0530573 if (!port)
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530574 return 0;
Jeeja KP754695f2017-02-06 12:09:14 +0530575 if ((!port->eld.monitor_present) ||
576 (!port->eld.eld_valid)) {
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530577
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500578 dev_warn(&hdev->dev,
Jeeja KP754695f2017-02-06 12:09:14 +0530579 "Failed: present?:%d ELD valid?:%d pin:port: %d:%d\n",
580 port->eld.monitor_present, port->eld.eld_valid,
581 port->pin->nid, port->id);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +0530582
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530583 return 0;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530584 }
585
Jeeja KP754695f2017-02-06 12:09:14 +0530586 dai_map->port = port;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530587
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530588 ret = hdac_hdmi_eld_limit_formats(substream->runtime,
Jeeja KP754695f2017-02-06 12:09:14 +0530589 port->eld.eld_buffer);
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530590 if (ret < 0)
591 return ret;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530592
Subhransu S. Prusty2428bca2016-02-12 07:46:02 +0530593 return snd_pcm_hw_constraint_eld(substream->runtime,
Jeeja KP754695f2017-02-06 12:09:14 +0530594 port->eld.eld_buffer);
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530595}
596
597static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
598 struct snd_soc_dai *dai)
599{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500600 struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
Jeeja KP754695f2017-02-06 12:09:14 +0530601 struct hdac_hdmi_dai_port_map *dai_map;
Jeeja KPab1eea12017-01-24 21:49:05 +0530602 struct hdac_hdmi_pcm *pcm;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530603
604 dai_map = &hdmi->dai_map[dai->id];
605
Jeeja KPab1eea12017-01-24 21:49:05 +0530606 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530607
Jeeja KPab1eea12017-01-24 21:49:05 +0530608 if (pcm) {
609 mutex_lock(&pcm->lock);
610 pcm->chmap_set = false;
611 memset(pcm->chmap, 0, sizeof(pcm->chmap));
612 pcm->channels = 0;
613 mutex_unlock(&pcm->lock);
Subhransu S. Prusty54dfa1e2016-02-17 21:34:00 +0530614 }
Jeeja KPab1eea12017-01-24 21:49:05 +0530615
Jeeja KP754695f2017-02-06 12:09:14 +0530616 if (dai_map->port)
617 dai_map->port = NULL;
Subhransu S. Prustyb0362ad2015-11-10 18:42:08 +0530618}
619
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530620static int
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +0530621hdac_hdmi_query_cvt_params(struct hdac_device *hdev, struct hdac_hdmi_cvt *cvt)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530622{
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530623 unsigned int chans;
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +0530624 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530625 int err;
626
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +0530627 chans = get_wcaps(hdev, cvt->nid);
Subhransu S. Prustybcced702016-04-14 10:07:30 +0530628 chans = get_wcaps_channels(chans);
629
630 cvt->params.channels_min = 2;
631
632 cvt->params.channels_max = chans;
633 if (chans > hdmi->chmap.channels_max)
634 hdmi->chmap.channels_max = chans;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530635
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +0530636 err = snd_hdac_query_supported_pcm(hdev, cvt->nid,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530637 &cvt->params.rates,
638 &cvt->params.formats,
639 &cvt->params.maxbps);
640 if (err < 0)
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +0530641 dev_err(&hdev->dev,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530642 "Failed to query pcm params for nid %d: %d\n",
643 cvt->nid, err);
644
645 return err;
646}
647
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530648static int hdac_hdmi_fill_widget_info(struct device *dev,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530649 struct snd_soc_dapm_widget *w, enum snd_soc_dapm_type id,
650 void *priv, const char *wname, const char *stream,
651 struct snd_kcontrol_new *wc, int numkc,
652 int (*event)(struct snd_soc_dapm_widget *,
653 struct snd_kcontrol *, int), unsigned short event_flags)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530654{
655 w->id = id;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530656 w->name = devm_kstrdup(dev, wname, GFP_KERNEL);
657 if (!w->name)
658 return -ENOMEM;
659
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530660 w->sname = stream;
661 w->reg = SND_SOC_NOPM;
662 w->shift = 0;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530663 w->kcontrol_news = wc;
664 w->num_kcontrols = numkc;
665 w->priv = priv;
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530666 w->event = event;
667 w->event_flags = event_flags;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530668
669 return 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530670}
671
672static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530673 const char *sink, const char *control, const char *src,
674 int (*handler)(struct snd_soc_dapm_widget *src,
675 struct snd_soc_dapm_widget *sink))
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530676{
677 route->sink = sink;
678 route->source = src;
679 route->control = control;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530680 route->connected = handler;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530681}
682
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500683static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_device *hdev,
Jeeja KP754695f2017-02-06 12:09:14 +0530684 struct hdac_hdmi_port *port)
Jeeja KP4a3478d2016-02-12 07:46:06 +0530685{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500686 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KP4a3478d2016-02-12 07:46:06 +0530687 struct hdac_hdmi_pcm *pcm = NULL;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530688 struct hdac_hdmi_port *p;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530689
690 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530691 if (list_empty(&pcm->port_list))
Jeeja KP754695f2017-02-06 12:09:14 +0530692 continue;
693
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530694 list_for_each_entry(p, &pcm->port_list, head) {
695 if (p->id == port->id && port->pin == p->pin)
696 return pcm;
697 }
Jeeja KP4a3478d2016-02-12 07:46:06 +0530698 }
699
700 return NULL;
701}
702
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500703static void hdac_hdmi_set_power_state(struct hdac_device *hdev,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530704 hda_nid_t nid, unsigned int pwr_state)
705{
Abhijeet Kumar753597f2018-02-15 14:05:38 +0530706 int count;
707 unsigned int state;
708
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500709 if (get_wcaps(hdev, nid) & AC_WCAP_POWER) {
710 if (!snd_hdac_check_power_state(hdev, nid, pwr_state)) {
Abhijeet Kumar753597f2018-02-15 14:05:38 +0530711 for (count = 0; count < 10; count++) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500712 snd_hdac_codec_read(hdev, nid, 0,
Abhijeet Kumar753597f2018-02-15 14:05:38 +0530713 AC_VERB_SET_POWER_STATE,
714 pwr_state);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500715 state = snd_hdac_sync_power_state(hdev,
Abhijeet Kumar753597f2018-02-15 14:05:38 +0530716 nid, pwr_state);
717 if (!(state & AC_PWRST_ERROR))
718 break;
719 }
720 }
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530721 }
722}
723
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500724static void hdac_hdmi_set_amp(struct hdac_device *hdev,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530725 hda_nid_t nid, int val)
726{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500727 if (get_wcaps(hdev, nid) & AC_WCAP_OUT_AMP)
728 snd_hdac_codec_write(hdev, nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530729 AC_VERB_SET_AMP_GAIN_MUTE, val);
730}
731
732
733static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w,
734 struct snd_kcontrol *kc, int event)
735{
Jeeja KP754695f2017-02-06 12:09:14 +0530736 struct hdac_hdmi_port *port = w->priv;
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500737 struct hdac_device *hdev = dev_to_hdac_dev(w->dapm->dev);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530738 struct hdac_hdmi_pcm *pcm;
739
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500740 dev_dbg(&hdev->dev, "%s: widget: %s event: %x\n",
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530741 __func__, w->name, event);
742
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500743 pcm = hdac_hdmi_get_pcm(hdev, port);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530744 if (!pcm)
745 return -EIO;
746
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530747 /* set the device if pin is mst_capable */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500748 if (hdac_hdmi_port_select_set(hdev, port) < 0)
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530749 return -EIO;
750
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530751 switch (event) {
752 case SND_SOC_DAPM_PRE_PMU:
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500753 hdac_hdmi_set_power_state(hdev, port->pin->nid, AC_PWRST_D0);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530754
755 /* Enable out path for this pin widget */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500756 snd_hdac_codec_write(hdev, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530757 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
758
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500759 hdac_hdmi_set_amp(hdev, port->pin->nid, AMP_OUT_UNMUTE);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530760
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500761 return hdac_hdmi_setup_audio_infoframe(hdev, pcm, port);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530762
763 case SND_SOC_DAPM_POST_PMD:
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500764 hdac_hdmi_set_amp(hdev, port->pin->nid, AMP_OUT_MUTE);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530765
766 /* Disable out path for this pin widget */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500767 snd_hdac_codec_write(hdev, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530768 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
769
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500770 hdac_hdmi_set_power_state(hdev, port->pin->nid, AC_PWRST_D3);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530771 break;
772
773 }
774
775 return 0;
776}
777
778static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w,
779 struct snd_kcontrol *kc, int event)
780{
781 struct hdac_hdmi_cvt *cvt = w->priv;
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500782 struct hdac_device *hdev = dev_to_hdac_dev(w->dapm->dev);
783 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530784 struct hdac_hdmi_pcm *pcm;
785
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500786 dev_dbg(&hdev->dev, "%s: widget: %s event: %x\n",
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530787 __func__, w->name, event);
788
789 pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, cvt);
790 if (!pcm)
791 return -EIO;
792
793 switch (event) {
794 case SND_SOC_DAPM_PRE_PMU:
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500795 hdac_hdmi_set_power_state(hdev, cvt->nid, AC_PWRST_D0);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530796
797 /* Enable transmission */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500798 snd_hdac_codec_write(hdev, cvt->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530799 AC_VERB_SET_DIGI_CONVERT_1, 1);
800
801 /* Category Code (CC) to zero */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500802 snd_hdac_codec_write(hdev, cvt->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530803 AC_VERB_SET_DIGI_CONVERT_2, 0);
804
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500805 snd_hdac_codec_write(hdev, cvt->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530806 AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500807 snd_hdac_codec_write(hdev, cvt->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530808 AC_VERB_SET_STREAM_FORMAT, pcm->format);
809 break;
810
811 case SND_SOC_DAPM_POST_PMD:
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500812 snd_hdac_codec_write(hdev, cvt->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530813 AC_VERB_SET_CHANNEL_STREAMID, 0);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500814 snd_hdac_codec_write(hdev, cvt->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530815 AC_VERB_SET_STREAM_FORMAT, 0);
816
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500817 hdac_hdmi_set_power_state(hdev, cvt->nid, AC_PWRST_D3);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530818 break;
819
820 }
821
822 return 0;
823}
824
825static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w,
826 struct snd_kcontrol *kc, int event)
827{
Jeeja KP754695f2017-02-06 12:09:14 +0530828 struct hdac_hdmi_port *port = w->priv;
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500829 struct hdac_device *hdev = dev_to_hdac_dev(w->dapm->dev);
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530830 int mux_idx;
831
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500832 dev_dbg(&hdev->dev, "%s: widget: %s event: %x\n",
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530833 __func__, w->name, event);
834
835 if (!kc)
836 kc = w->kcontrols[0];
837
838 mux_idx = dapm_kcontrol_get_value(kc);
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530839
840 /* set the device if pin is mst_capable */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500841 if (hdac_hdmi_port_select_set(hdev, port) < 0)
Jeeja KP1b46ebd2017-02-07 19:09:47 +0530842 return -EIO;
843
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530844 if (mux_idx > 0) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500845 snd_hdac_codec_write(hdev, port->pin->nid, 0,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530846 AC_VERB_SET_CONNECT_SEL, (mux_idx - 1));
847 }
848
849 return 0;
850}
851
Jeeja KP4a3478d2016-02-12 07:46:06 +0530852/*
853 * Based on user selection, map the PINs with the PCMs.
854 */
Jeeja KP754695f2017-02-06 12:09:14 +0530855static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
Jeeja KP4a3478d2016-02-12 07:46:06 +0530856 struct snd_ctl_elem_value *ucontrol)
857{
858 int ret;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530859 struct hdac_hdmi_port *p, *p_next;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530860 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
861 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
862 struct snd_soc_dapm_context *dapm = w->dapm;
Jeeja KP754695f2017-02-06 12:09:14 +0530863 struct hdac_hdmi_port *port = w->priv;
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500864 struct hdac_device *hdev = dev_to_hdac_dev(dapm->dev);
865 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KP4a3478d2016-02-12 07:46:06 +0530866 struct hdac_hdmi_pcm *pcm = NULL;
867 const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]];
868
869 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
870 if (ret < 0)
871 return ret;
872
Jeeja KP754695f2017-02-06 12:09:14 +0530873 if (port == NULL)
874 return -EINVAL;
875
Jeeja KP4a3478d2016-02-12 07:46:06 +0530876 mutex_lock(&hdmi->pin_mutex);
877 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530878 if (list_empty(&pcm->port_list))
879 continue;
Jeeja KP4a3478d2016-02-12 07:46:06 +0530880
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530881 list_for_each_entry_safe(p, p_next, &pcm->port_list, head) {
882 if (p == port && p->id == port->id &&
883 p->pin == port->pin) {
884 hdac_hdmi_jack_report(pcm, port, false);
885 list_del(&p->head);
Jeeja KP4a3478d2016-02-12 07:46:06 +0530886 }
Jeeja KPe0e5d3e2017-02-07 19:09:48 +0530887 }
888 }
889
890 /*
891 * Jack status is not reported during device probe as the
892 * PCMs are not registered by then. So report it here.
893 */
894 list_for_each_entry(pcm, &hdmi->pcm_list, head) {
895 if (!strcmp(cvt_name, pcm->cvt->name)) {
896 list_add_tail(&port->head, &pcm->port_list);
897 if (port->eld.monitor_present && port->eld.eld_valid) {
898 hdac_hdmi_jack_report(pcm, port, true);
899 mutex_unlock(&hdmi->pin_mutex);
900 return ret;
901 }
Jeeja KP4a3478d2016-02-12 07:46:06 +0530902 }
903 }
904 mutex_unlock(&hdmi->pin_mutex);
905
906 return ret;
907}
908
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530909/*
910 * Ideally the Mux inputs should be based on the num_muxs enumerated, but
911 * the display driver seem to be programming the connection list for the pin
912 * widget runtime.
913 *
914 * So programming all the possible inputs for the mux, the user has to take
915 * care of selecting the right one and leaving all other inputs selected to
916 * "NONE"
917 */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500918static int hdac_hdmi_create_pin_port_muxs(struct hdac_device *hdev,
Jeeja KP754695f2017-02-06 12:09:14 +0530919 struct hdac_hdmi_port *port,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530920 struct snd_soc_dapm_widget *widget,
921 const char *widget_name)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530922{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500923 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KP754695f2017-02-06 12:09:14 +0530924 struct hdac_hdmi_pin *pin = port->pin;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530925 struct snd_kcontrol_new *kc;
926 struct hdac_hdmi_cvt *cvt;
927 struct soc_enum *se;
928 char kc_name[NAME_SIZE];
929 char mux_items[NAME_SIZE];
930 /* To hold inputs to the Pin mux */
931 char *items[HDA_MAX_CONNECTIONS];
932 int i = 0;
933 int num_items = hdmi->num_cvt + 1;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530934
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500935 kc = devm_kzalloc(&hdev->dev, sizeof(*kc), GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530936 if (!kc)
937 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530938
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500939 se = devm_kzalloc(&hdev->dev, sizeof(*se), GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530940 if (!se)
941 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530942
Subhransu S. Prusty70e97a22017-11-07 16:16:24 +0530943 snprintf(kc_name, NAME_SIZE, "Pin %d port %d Input",
944 pin->nid, port->id);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500945 kc->name = devm_kstrdup(&hdev->dev, kc_name, GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530946 if (!kc->name)
947 return -ENOMEM;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +0530948
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530949 kc->private_value = (long)se;
950 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
951 kc->access = 0;
952 kc->info = snd_soc_info_enum_double;
Jeeja KP754695f2017-02-06 12:09:14 +0530953 kc->put = hdac_hdmi_set_pin_port_mux;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530954 kc->get = snd_soc_dapm_get_enum_double;
955
956 se->reg = SND_SOC_NOPM;
957
958 /* enum texts: ["NONE", "cvt #", "cvt #", ...] */
959 se->items = num_items;
960 se->mask = roundup_pow_of_two(se->items) - 1;
961
962 sprintf(mux_items, "NONE");
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500963 items[i] = devm_kstrdup(&hdev->dev, mux_items, GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530964 if (!items[i])
965 return -ENOMEM;
966
967 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
968 i++;
969 sprintf(mux_items, "cvt %d", cvt->nid);
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500970 items[i] = devm_kstrdup(&hdev->dev, mux_items, GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530971 if (!items[i])
972 return -ENOMEM;
973 }
974
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500975 se->texts = devm_kmemdup(&hdev->dev, items,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530976 (num_items * sizeof(char *)), GFP_KERNEL);
977 if (!se->texts)
978 return -ENOMEM;
979
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500980 return hdac_hdmi_fill_widget_info(&hdev->dev, widget,
Jeeja KP754695f2017-02-06 12:09:14 +0530981 snd_soc_dapm_mux, port, widget_name, NULL, kc, 1,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +0530982 hdac_hdmi_pin_mux_widget_event,
983 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_REG);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530984}
985
986/* Add cvt <- input <- mux route map */
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500987static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_device *hdev,
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530988 struct snd_soc_dapm_widget *widgets,
989 struct snd_soc_dapm_route *route, int rindex)
990{
Rakesh Ughreja3787a392018-06-01 22:53:49 -0500991 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530992 const struct snd_kcontrol_new *kc;
993 struct soc_enum *se;
Jeeja KP754695f2017-02-06 12:09:14 +0530994 int mux_index = hdmi->num_cvt + hdmi->num_ports;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530995 int i, j;
996
Jeeja KP754695f2017-02-06 12:09:14 +0530997 for (i = 0; i < hdmi->num_ports; i++) {
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +0530998 kc = widgets[mux_index].kcontrol_news;
999 se = (struct soc_enum *)kc->private_value;
1000 for (j = 0; j < hdmi->num_cvt; j++) {
1001 hdac_hdmi_fill_route(&route[rindex],
1002 widgets[mux_index].name,
1003 se->texts[j + 1],
1004 widgets[j].name, NULL);
1005
1006 rindex++;
1007 }
1008
1009 mux_index++;
1010 }
1011}
1012
1013/*
1014 * Widgets are added in the below sequence
1015 * Converter widgets for num converters enumerated
Jeeja KP754695f2017-02-06 12:09:14 +05301016 * Pin-port widgets for num ports for Pins enumerated
1017 * Pin-port mux widgets to represent connenction list of pin widget
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301018 *
Jeeja KP754695f2017-02-06 12:09:14 +05301019 * For each port, one Mux and One output widget is added
1020 * Total widgets elements = num_cvt + (num_ports * 2);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301021 *
1022 * Routes are added as below:
Jeeja KP754695f2017-02-06 12:09:14 +05301023 * pin-port mux -> pin (based on num_ports)
1024 * cvt -> "Input sel control" -> pin-port_mux
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301025 *
1026 * Total route elements:
Jeeja KP754695f2017-02-06 12:09:14 +05301027 * num_ports + (pin_muxes * num_cvt)
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301028 */
1029static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
1030{
1031 struct snd_soc_dapm_widget *widgets;
1032 struct snd_soc_dapm_route *route;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001033 struct hdac_device *hdev = dev_to_hdac_dev(dapm->dev);
1034 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Kuninori Morimoto1e02dac2017-12-20 01:48:13 +00001035 struct snd_soc_dai_driver *dai_drv = hdmi->dai_drv;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301036 char widget_name[NAME_SIZE];
1037 struct hdac_hdmi_cvt *cvt;
1038 struct hdac_hdmi_pin *pin;
Jeeja KP754695f2017-02-06 12:09:14 +05301039 int ret, i = 0, num_routes = 0, j;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301040
1041 if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
1042 return -EINVAL;
1043
Jeeja KP754695f2017-02-06 12:09:14 +05301044 widgets = devm_kzalloc(dapm->dev, (sizeof(*widgets) *
1045 ((2 * hdmi->num_ports) + hdmi->num_cvt)),
1046 GFP_KERNEL);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301047
1048 if (!widgets)
1049 return -ENOMEM;
1050
1051 /* DAPM widgets to represent each converter widget */
1052 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
1053 sprintf(widget_name, "Converter %d", cvt->nid);
1054 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
Jeeja KPc9bfb5d2017-01-24 21:49:03 +05301055 snd_soc_dapm_aif_in, cvt,
1056 widget_name, dai_drv[i].playback.stream_name, NULL, 0,
1057 hdac_hdmi_cvt_output_widget_event,
1058 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301059 if (ret < 0)
1060 return ret;
1061 i++;
1062 }
1063
1064 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301065 for (j = 0; j < pin->num_ports; j++) {
1066 sprintf(widget_name, "hif%d-%d Output",
1067 pin->nid, pin->ports[j].id);
1068 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
1069 snd_soc_dapm_output, &pin->ports[j],
1070 widget_name, NULL, NULL, 0,
1071 hdac_hdmi_pin_output_widget_event,
1072 SND_SOC_DAPM_PRE_PMU |
1073 SND_SOC_DAPM_POST_PMD);
1074 if (ret < 0)
1075 return ret;
Jeeja KP0324e512017-02-07 19:09:55 +05301076 pin->ports[j].output_pin = widgets[i].name;
Jeeja KP754695f2017-02-06 12:09:14 +05301077 i++;
1078 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301079 }
1080
1081 /* DAPM widgets to represent the connection list to pin widget */
1082 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301083 for (j = 0; j < pin->num_ports; j++) {
1084 sprintf(widget_name, "Pin%d-Port%d Mux",
1085 pin->nid, pin->ports[j].id);
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001086 ret = hdac_hdmi_create_pin_port_muxs(hdev,
Jeeja KP754695f2017-02-06 12:09:14 +05301087 &pin->ports[j], &widgets[i],
1088 widget_name);
1089 if (ret < 0)
1090 return ret;
1091 i++;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301092
Jeeja KP754695f2017-02-06 12:09:14 +05301093 /* For cvt to pin_mux mapping */
1094 num_routes += hdmi->num_cvt;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301095
Jeeja KP754695f2017-02-06 12:09:14 +05301096 /* For pin_mux to pin mapping */
1097 num_routes++;
1098 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301099 }
1100
1101 route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes),
1102 GFP_KERNEL);
1103 if (!route)
1104 return -ENOMEM;
1105
1106 i = 0;
1107 /* Add pin <- NULL <- mux route map */
1108 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301109 for (j = 0; j < pin->num_ports; j++) {
1110 int sink_index = i + hdmi->num_cvt;
1111 int src_index = sink_index + pin->num_ports *
1112 hdmi->num_pin;
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301113
Jeeja KP754695f2017-02-06 12:09:14 +05301114 hdac_hdmi_fill_route(&route[i],
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301115 widgets[sink_index].name, NULL,
1116 widgets[src_index].name, NULL);
Jeeja KP754695f2017-02-06 12:09:14 +05301117 i++;
1118 }
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301119 }
1120
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001121 hdac_hdmi_add_pinmux_cvt_route(hdev, widgets, route, i);
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301122
1123 snd_soc_dapm_new_controls(dapm, widgets,
Jeeja KP754695f2017-02-06 12:09:14 +05301124 ((2 * hdmi->num_ports) + hdmi->num_cvt));
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301125
1126 snd_soc_dapm_add_routes(dapm, route, num_routes);
1127 snd_soc_dapm_new_widgets(dapm->card);
1128
1129 return 0;
1130
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301131}
1132
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001133static int hdac_hdmi_init_dai_map(struct hdac_device *hdev)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301134{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001135 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KP754695f2017-02-06 12:09:14 +05301136 struct hdac_hdmi_dai_port_map *dai_map;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301137 struct hdac_hdmi_cvt *cvt;
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301138 int dai_id = 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301139
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301140 if (list_empty(&hdmi->cvt_list))
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301141 return -EINVAL;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301142
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301143 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
1144 dai_map = &hdmi->dai_map[dai_id];
1145 dai_map->dai_id = dai_id;
1146 dai_map->cvt = cvt;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301147
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301148 dai_id++;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301149
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301150 if (dai_id == HDA_MAX_CVTS) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001151 dev_warn(&hdev->dev,
Subhransu S. Prusty148569f2016-02-12 07:46:07 +05301152 "Max dais supported: %d\n", dai_id);
1153 break;
1154 }
1155 }
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301156
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301157 return 0;
1158}
1159
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001160static int hdac_hdmi_add_cvt(struct hdac_device *hdev, hda_nid_t nid)
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301161{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001162 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301163 struct hdac_hdmi_cvt *cvt;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301164 char name[NAME_SIZE];
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301165
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001166 cvt = devm_kzalloc(&hdev->dev, sizeof(*cvt), GFP_KERNEL);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301167 if (!cvt)
1168 return -ENOMEM;
1169
1170 cvt->nid = nid;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301171 sprintf(name, "cvt %d", cvt->nid);
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001172 cvt->name = devm_kstrdup(&hdev->dev, name, GFP_KERNEL);
1173 if (!cvt->name)
1174 return -ENOMEM;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301175
1176 list_add_tail(&cvt->head, &hdmi->cvt_list);
1177 hdmi->num_cvt++;
1178
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001179 return hdac_hdmi_query_cvt_params(hdev, cvt);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301180}
1181
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001182static int hdac_hdmi_parse_eld(struct hdac_device *hdev,
Jeeja KP754695f2017-02-06 12:09:14 +05301183 struct hdac_hdmi_port *port)
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +05301184{
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301185 unsigned int ver, mnl;
1186
Jeeja KP754695f2017-02-06 12:09:14 +05301187 ver = (port->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301188 >> DRM_ELD_VER_SHIFT;
1189
1190 if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001191 dev_err(&hdev->dev, "HDMI: Unknown ELD version %d\n", ver);
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301192 return -EINVAL;
1193 }
1194
Jeeja KP754695f2017-02-06 12:09:14 +05301195 mnl = (port->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301196 DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
1197
1198 if (mnl > ELD_MAX_MNL) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001199 dev_err(&hdev->dev, "HDMI: MNL Invalid %d\n", mnl);
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301200 return -EINVAL;
1201 }
1202
Jeeja KP754695f2017-02-06 12:09:14 +05301203 port->eld.info.spk_alloc = port->eld.eld_buffer[DRM_ELD_SPEAKER];
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301204
1205 return 0;
Subhransu S. Prustyb7756ed2016-04-14 10:07:28 +05301206}
1207
Jeeja KP754695f2017-02-06 12:09:14 +05301208static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
1209 struct hdac_hdmi_port *port)
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301210{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001211 struct hdac_device *hdev = pin->hdev;
1212 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301213 struct hdac_hdmi_pcm *pcm;
Jeeja KP754695f2017-02-06 12:09:14 +05301214 int size = 0;
Jeeja KP2acd8302017-02-06 12:09:18 +05301215 int port_id = -1;
Jeeja KP754695f2017-02-06 12:09:14 +05301216
1217 if (!hdmi)
1218 return;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301219
Jeeja KP2acd8302017-02-06 12:09:18 +05301220 /*
1221 * In case of non MST pin, get_eld info API expectes port
1222 * to be -1.
1223 */
Jeeja KP4a3478d2016-02-12 07:46:06 +05301224 mutex_lock(&hdmi->pin_mutex);
Jeeja KP754695f2017-02-06 12:09:14 +05301225 port->eld.monitor_present = false;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301226
Jeeja KP2acd8302017-02-06 12:09:18 +05301227 if (pin->mst_capable)
1228 port_id = port->id;
1229
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001230 size = snd_hdac_acomp_get_eld(hdev, pin->nid, port_id,
Jeeja KP754695f2017-02-06 12:09:14 +05301231 &port->eld.monitor_present,
1232 port->eld.eld_buffer,
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301233 ELD_MAX_SIZE);
1234
1235 if (size > 0) {
1236 size = min(size, ELD_MAX_SIZE);
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001237 if (hdac_hdmi_parse_eld(hdev, port) < 0)
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301238 size = -EINVAL;
1239 }
1240
1241 if (size > 0) {
Jeeja KP754695f2017-02-06 12:09:14 +05301242 port->eld.eld_valid = true;
1243 port->eld.eld_size = size;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301244 } else {
Jeeja KP754695f2017-02-06 12:09:14 +05301245 port->eld.eld_valid = false;
1246 port->eld.eld_size = 0;
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301247 }
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301248
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001249 pcm = hdac_hdmi_get_pcm(hdev, port);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301250
Jeeja KP754695f2017-02-06 12:09:14 +05301251 if (!port->eld.monitor_present || !port->eld.eld_valid) {
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301252
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001253 dev_err(&hdev->dev, "%s: disconnect for pin:port %d:%d\n",
Jeeja KP754695f2017-02-06 12:09:14 +05301254 __func__, pin->nid, port->id);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301255
1256 /*
1257 * PCMs are not registered during device probe, so don't
1258 * report jack here. It will be done in usermode mux
1259 * control select.
1260 */
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301261 if (pcm)
1262 hdac_hdmi_jack_report(pcm, port, false);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301263
1264 mutex_unlock(&hdmi->pin_mutex);
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301265 return;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301266 }
1267
Jeeja KP754695f2017-02-06 12:09:14 +05301268 if (port->eld.monitor_present && port->eld.eld_valid) {
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301269 if (pcm)
1270 hdac_hdmi_jack_report(pcm, port, true);
Sandeep Tayalf6fa11a2017-01-18 21:34:41 +05301271
1272 print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
Jeeja KP754695f2017-02-06 12:09:14 +05301273 port->eld.eld_buffer, port->eld.eld_size, false);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301274
Jeeja KP754695f2017-02-06 12:09:14 +05301275 }
Jeeja KP4a3478d2016-02-12 07:46:06 +05301276 mutex_unlock(&hdmi->pin_mutex);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301277}
1278
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001279static int hdac_hdmi_add_ports(struct hdac_device *hdev,
1280 struct hdac_hdmi_pin *pin)
Jeeja KP754695f2017-02-06 12:09:14 +05301281{
1282 struct hdac_hdmi_port *ports;
1283 int max_ports = HDA_MAX_PORTS;
1284 int i;
1285
1286 /*
1287 * FIXME: max_port may vary for each platform, so pass this as
1288 * as driver data or query from i915 interface when this API is
1289 * implemented.
1290 */
1291
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001292 ports = devm_kcalloc(&hdev->dev, max_ports, sizeof(*ports), GFP_KERNEL);
Jeeja KP754695f2017-02-06 12:09:14 +05301293 if (!ports)
1294 return -ENOMEM;
1295
1296 for (i = 0; i < max_ports; i++) {
1297 ports[i].id = i;
1298 ports[i].pin = pin;
1299 }
1300 pin->ports = ports;
1301 pin->num_ports = max_ports;
1302 return 0;
1303}
1304
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001305static int hdac_hdmi_add_pin(struct hdac_device *hdev, hda_nid_t nid)
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301306{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001307 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301308 struct hdac_hdmi_pin *pin;
Jeeja KP754695f2017-02-06 12:09:14 +05301309 int ret;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301310
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001311 pin = devm_kzalloc(&hdev->dev, sizeof(*pin), GFP_KERNEL);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301312 if (!pin)
1313 return -ENOMEM;
1314
1315 pin->nid = nid;
Jeeja KP2acd8302017-02-06 12:09:18 +05301316 pin->mst_capable = false;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001317 pin->hdev = hdev;
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001318 ret = hdac_hdmi_add_ports(hdev, pin);
Jeeja KP754695f2017-02-06 12:09:14 +05301319 if (ret < 0)
1320 return ret;
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301321
1322 list_add_tail(&pin->head, &hdmi->pin_list);
1323 hdmi->num_pin++;
Jeeja KP754695f2017-02-06 12:09:14 +05301324 hdmi->num_ports += pin->num_ports;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301325
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301326 return 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301327}
1328
Bard liao019033c2018-11-11 05:18:46 +08001329#define INTEL_VENDOR_NID_0x2 0x02
1330#define INTEL_VENDOR_NID_0x8 0x08
1331#define INTEL_VENDOR_NID_0xb 0x0b
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301332#define INTEL_GET_VENDOR_VERB 0xf81
1333#define INTEL_SET_VENDOR_VERB 0x781
Bard liao019033c2018-11-11 05:18:46 +08001334#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301335#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
1336
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301337static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdev)
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301338{
1339 unsigned int vendor_param;
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301340 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Pradeep Tewani5622bc92017-07-20 11:40:56 +05301341 unsigned int vendor_nid = hdmi->drv_data->vendor_nid;
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301342
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301343 vendor_param = snd_hdac_codec_read(hdev, vendor_nid, 0,
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301344 INTEL_GET_VENDOR_VERB, 0);
1345 if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
1346 return;
1347
1348 vendor_param |= INTEL_EN_ALL_PIN_CVTS;
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301349 vendor_param = snd_hdac_codec_read(hdev, vendor_nid, 0,
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301350 INTEL_SET_VENDOR_VERB, vendor_param);
1351 if (vendor_param == -1)
1352 return;
1353}
1354
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301355static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdev)
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301356{
1357 unsigned int vendor_param;
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301358 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Pradeep Tewani5622bc92017-07-20 11:40:56 +05301359 unsigned int vendor_nid = hdmi->drv_data->vendor_nid;
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301360
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301361 vendor_param = snd_hdac_codec_read(hdev, vendor_nid, 0,
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301362 INTEL_GET_VENDOR_VERB, 0);
1363 if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
1364 return;
1365
1366 /* enable DP1.2 mode */
1367 vendor_param |= INTEL_EN_DP12;
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301368 vendor_param = snd_hdac_codec_read(hdev, vendor_nid, 0,
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301369 INTEL_SET_VENDOR_VERB, vendor_param);
1370 if (vendor_param == -1)
1371 return;
1372
1373}
1374
Gustavo A. R. Silva61b3b3c2017-07-13 15:38:38 -05001375static const struct snd_soc_dai_ops hdmi_dai_ops = {
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301376 .startup = hdac_hdmi_pcm_open,
1377 .shutdown = hdac_hdmi_pcm_close,
1378 .hw_params = hdac_hdmi_set_hw_params,
Jeeja KPc9bfb5d2017-01-24 21:49:03 +05301379 .set_tdm_slot = hdac_hdmi_set_tdm_slot,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301380};
1381
1382/*
1383 * Each converter can support a stream independently. So a dai is created
1384 * based on the number of converter queried.
1385 */
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301386static int hdac_hdmi_create_dais(struct hdac_device *hdev,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301387 struct snd_soc_dai_driver **dais,
1388 struct hdac_hdmi_priv *hdmi, int num_dais)
1389{
1390 struct snd_soc_dai_driver *hdmi_dais;
1391 struct hdac_hdmi_cvt *cvt;
1392 char name[NAME_SIZE], dai_name[NAME_SIZE];
1393 int i = 0;
1394 u32 rates, bps;
1395 unsigned int rate_max = 384000, rate_min = 8000;
1396 u64 formats;
1397 int ret;
1398
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301399 hdmi_dais = devm_kzalloc(&hdev->dev,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301400 (sizeof(*hdmi_dais) * num_dais),
1401 GFP_KERNEL);
1402 if (!hdmi_dais)
1403 return -ENOMEM;
1404
1405 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301406 ret = snd_hdac_query_supported_pcm(hdev, cvt->nid,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301407 &rates, &formats, &bps);
1408 if (ret)
1409 return ret;
1410
Yong Zhi3b857472018-08-07 12:19:16 -05001411 /* Filter out 44.1, 88.2 and 176.4Khz */
1412 rates &= ~(SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |
1413 SNDRV_PCM_RATE_176400);
1414 if (!rates)
1415 return -EINVAL;
1416
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301417 sprintf(dai_name, "intel-hdmi-hifi%d", i+1);
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301418 hdmi_dais[i].name = devm_kstrdup(&hdev->dev,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301419 dai_name, GFP_KERNEL);
1420
1421 if (!hdmi_dais[i].name)
1422 return -ENOMEM;
1423
1424 snprintf(name, sizeof(name), "hifi%d", i+1);
1425 hdmi_dais[i].playback.stream_name =
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301426 devm_kstrdup(&hdev->dev, name, GFP_KERNEL);
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301427 if (!hdmi_dais[i].playback.stream_name)
1428 return -ENOMEM;
1429
1430 /*
1431 * Set caps based on capability queried from the converter.
1432 * It will be constrained runtime based on ELD queried.
1433 */
1434 hdmi_dais[i].playback.formats = formats;
1435 hdmi_dais[i].playback.rates = rates;
1436 hdmi_dais[i].playback.rate_max = rate_max;
1437 hdmi_dais[i].playback.rate_min = rate_min;
1438 hdmi_dais[i].playback.channels_min = 2;
1439 hdmi_dais[i].playback.channels_max = 2;
Jeeja KP66d6bbc2017-03-24 23:10:26 +05301440 hdmi_dais[i].playback.sig_bits = bps;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301441 hdmi_dais[i].ops = &hdmi_dai_ops;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301442 i++;
1443 }
1444
1445 *dais = hdmi_dais;
Kuninori Morimoto1e02dac2017-12-20 01:48:13 +00001446 hdmi->dai_drv = hdmi_dais;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301447
1448 return 0;
1449}
1450
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301451/*
1452 * Parse all nodes and store the cvt/pin nids in array
1453 * Add one time initialization for pin and cvt widgets
1454 */
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001455static int hdac_hdmi_parse_and_map_nid(struct hdac_device *hdev,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301456 struct snd_soc_dai_driver **dais, int *num_dais)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301457{
1458 hda_nid_t nid;
Sudip Mukherjee3c83ac22015-12-01 14:29:35 +05301459 int i, num_nodes;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001460 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301461 int ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301462
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301463 hdac_hdmi_skl_enable_all_pins(hdev);
1464 hdac_hdmi_skl_enable_dp12(hdev);
Subhransu S. Prusty211caab2016-02-12 07:46:03 +05301465
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301466 num_nodes = snd_hdac_get_sub_nodes(hdev, hdev->afg, &nid);
Subhransu S. Prusty541140d2015-12-09 21:46:08 +05301467 if (!nid || num_nodes <= 0) {
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301468 dev_warn(&hdev->dev, "HDMI: failed to get afg sub nodes\n");
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301469 return -EINVAL;
1470 }
1471
Puneeth Prabhu45a60082017-12-06 16:34:06 +05301472 for (i = 0; i < num_nodes; i++, nid++) {
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301473 unsigned int caps;
1474 unsigned int type;
1475
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301476 caps = get_wcaps(hdev, nid);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301477 type = get_wcaps_type(caps);
1478
1479 if (!(caps & AC_WCAP_DIGITAL))
1480 continue;
1481
1482 switch (type) {
1483
1484 case AC_WID_AUD_OUT:
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001485 ret = hdac_hdmi_add_cvt(hdev, nid);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301486 if (ret < 0)
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001487 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301488 break;
1489
1490 case AC_WID_PIN:
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001491 ret = hdac_hdmi_add_pin(hdev, nid);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05301492 if (ret < 0)
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001493 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301494 break;
1495 }
1496 }
1497
Subhransu S. Prusty1c0a7de2017-11-07 16:16:26 +05301498 if (!hdmi->num_pin || !hdmi->num_cvt) {
1499 ret = -EIO;
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001500 dev_err(&hdev->dev, "Bad pin/cvt setup in %s\n", __func__);
1501 return ret;
Subhransu S. Prusty1c0a7de2017-11-07 16:16:26 +05301502 }
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301503
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301504 ret = hdac_hdmi_create_dais(hdev, dais, hdmi, hdmi->num_cvt);
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301505 if (ret) {
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301506 dev_err(&hdev->dev, "Failed to create dais with err: %d\n",
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001507 ret);
1508 return ret;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301509 }
1510
1511 *num_dais = hdmi->num_cvt;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001512 ret = hdac_hdmi_init_dai_map(hdev);
Subhransu S. Prusty1c0a7de2017-11-07 16:16:26 +05301513 if (ret < 0)
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001514 dev_err(&hdev->dev, "Failed to init DAI map with err: %d\n",
1515 ret);
Subhransu S. Prusty1c0a7de2017-11-07 16:16:26 +05301516 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301517}
1518
Takashi Iwaia57942b2018-07-11 16:23:16 +02001519static int hdac_hdmi_pin2port(void *aptr, int pin)
1520{
Bard liao019033c2018-11-11 05:18:46 +08001521 struct hdac_device *hdev = aptr;
1522 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
1523 const int *map = hdmi->drv_data->port_map;
1524 int i;
1525
1526 if (!hdmi->drv_data->port_num)
1527 return pin - 4; /* map NID 0x05 -> port #1 */
1528
1529 /*
1530 * looking for the pin number in the mapping table and return
1531 * the index which indicate the port number
1532 */
1533 for (i = 0; i < hdmi->drv_data->port_num; i++) {
1534 if (pin == map[i])
1535 return i + 1;
1536 }
1537
1538 /* return -1 if pin number exceeds our expectation */
1539 dev_err(&hdev->dev, "Can't find the port for pin %d\n", pin);
1540 return -1;
Takashi Iwaia57942b2018-07-11 16:23:16 +02001541}
1542
Pandiyan, Dhinakaranf9318942016-09-21 13:02:48 -07001543static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301544{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001545 struct hdac_device *hdev = aptr;
1546 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Jeeja KP754695f2017-02-06 12:09:14 +05301547 struct hdac_hdmi_pin *pin = NULL;
1548 struct hdac_hdmi_port *hport = NULL;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001549 struct snd_soc_component *component = hdmi->component;
Jeeja KP2acd8302017-02-06 12:09:18 +05301550 int i;
Bard liao019033c2018-11-11 05:18:46 +08001551 hda_nid_t pin_nid;
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301552
Bard liao019033c2018-11-11 05:18:46 +08001553 if (!hdmi->drv_data->port_num) {
1554 /* for legacy platforms */
1555 pin_nid = port + 0x04;
1556 } else if (port < hdmi->drv_data->port_num) {
1557 /* get pin number from the pin2port mapping table */
1558 pin_nid = hdmi->drv_data->port_map[port - 1];
1559 } else {
1560 dev_err(&hdev->dev, "Can't find the pin for port %d\n", port);
1561 return;
1562 }
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301563
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001564 dev_dbg(&hdev->dev, "%s: for pin:%d port=%d\n", __func__,
Jeeja KP754695f2017-02-06 12:09:14 +05301565 pin_nid, pipe);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301566
1567 /*
1568 * skip notification during system suspend (but not in runtime PM);
1569 * the state will be updated at resume. Also since the ELD and
1570 * connection states are updated in anyway at the end of the resume,
1571 * we can skip it when received during PM process.
1572 */
Kuninori Morimoto45101122018-01-29 04:36:54 +00001573 if (snd_power_get_state(component->card->snd_card) !=
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301574 SNDRV_CTL_POWER_D0)
1575 return;
1576
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001577 if (atomic_read(&hdev->in_pm))
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301578 return;
1579
1580 list_for_each_entry(pin, &hdmi->pin_list, head) {
Jeeja KP754695f2017-02-06 12:09:14 +05301581 if (pin->nid != pin_nid)
1582 continue;
1583
1584 /* In case of non MST pin, pipe is -1 */
1585 if (pipe == -1) {
Jeeja KP2acd8302017-02-06 12:09:18 +05301586 pin->mst_capable = false;
Jeeja KP754695f2017-02-06 12:09:14 +05301587 /* if not MST, default is port[0] */
1588 hport = &pin->ports[0];
Jeeja KP2acd8302017-02-06 12:09:18 +05301589 } else {
1590 for (i = 0; i < pin->num_ports; i++) {
1591 pin->mst_capable = true;
1592 if (pin->ports[i].id == pipe) {
1593 hport = &pin->ports[i];
Jeeja KP04c8f2b2017-03-01 22:41:23 +05301594 break;
Jeeja KP2acd8302017-02-06 12:09:18 +05301595 }
1596 }
Jeeja KP754695f2017-02-06 12:09:14 +05301597 }
Jeeja KP04c8f2b2017-03-01 22:41:23 +05301598
1599 if (hport)
1600 hdac_hdmi_present_sense(pin, hport);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301601 }
Jeeja KP754695f2017-02-06 12:09:14 +05301602
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301603}
1604
Takashi Iwaiae891ab2018-07-11 15:17:22 +02001605static struct drm_audio_component_audio_ops aops = {
Takashi Iwaia57942b2018-07-11 16:23:16 +02001606 .pin2port = hdac_hdmi_pin2port,
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301607 .pin_eld_notify = hdac_hdmi_eld_notify_cb,
1608};
1609
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301610static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card,
1611 int device)
1612{
1613 struct snd_soc_pcm_runtime *rtd;
1614
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00001615 for_each_card_rtds(card, rtd) {
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301616 if (rtd->pcm && (rtd->pcm->device == device))
1617 return rtd->pcm;
1618 }
1619
1620 return NULL;
1621}
1622
Jeeja KP0324e512017-02-07 19:09:55 +05301623/* create jack pin kcontrols */
1624static int create_fill_jack_kcontrols(struct snd_soc_card *card,
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001625 struct hdac_device *hdev)
Jeeja KP0324e512017-02-07 19:09:55 +05301626{
1627 struct hdac_hdmi_pin *pin;
1628 struct snd_kcontrol_new *kc;
1629 char kc_name[NAME_SIZE], xname[NAME_SIZE];
1630 char *name;
1631 int i = 0, j;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001632 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
1633 struct snd_soc_component *component = hdmi->component;
Jeeja KP0324e512017-02-07 19:09:55 +05301634
Kuninori Morimoto45101122018-01-29 04:36:54 +00001635 kc = devm_kcalloc(component->dev, hdmi->num_ports,
Jeeja KP0324e512017-02-07 19:09:55 +05301636 sizeof(*kc), GFP_KERNEL);
1637
1638 if (!kc)
1639 return -ENOMEM;
1640
1641 list_for_each_entry(pin, &hdmi->pin_list, head) {
1642 for (j = 0; j < pin->num_ports; j++) {
1643 snprintf(xname, sizeof(xname), "hif%d-%d Jack",
1644 pin->nid, pin->ports[j].id);
Kuninori Morimoto45101122018-01-29 04:36:54 +00001645 name = devm_kstrdup(component->dev, xname, GFP_KERNEL);
Jeeja KP0324e512017-02-07 19:09:55 +05301646 if (!name)
1647 return -ENOMEM;
1648 snprintf(kc_name, sizeof(kc_name), "%s Switch", xname);
Kuninori Morimoto45101122018-01-29 04:36:54 +00001649 kc[i].name = devm_kstrdup(component->dev, kc_name,
Jeeja KP0324e512017-02-07 19:09:55 +05301650 GFP_KERNEL);
1651 if (!kc[i].name)
1652 return -ENOMEM;
1653
1654 kc[i].private_value = (unsigned long)name;
1655 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1656 kc[i].access = 0;
1657 kc[i].info = snd_soc_dapm_info_pin_switch;
1658 kc[i].put = snd_soc_dapm_put_pin_switch;
1659 kc[i].get = snd_soc_dapm_get_pin_switch;
1660 i++;
1661 }
1662 }
1663
1664 return snd_soc_add_card_controls(card, kc, i);
1665}
1666
Kuninori Morimoto45101122018-01-29 04:36:54 +00001667int hdac_hdmi_jack_port_init(struct snd_soc_component *component,
Jeeja KP0324e512017-02-07 19:09:55 +05301668 struct snd_soc_dapm_context *dapm)
1669{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001670 struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component);
1671 struct hdac_device *hdev = hdmi->hdev;
Jeeja KP0324e512017-02-07 19:09:55 +05301672 struct hdac_hdmi_pin *pin;
1673 struct snd_soc_dapm_widget *widgets;
1674 struct snd_soc_dapm_route *route;
1675 char w_name[NAME_SIZE];
1676 int i = 0, j, ret;
1677
1678 widgets = devm_kcalloc(dapm->dev, hdmi->num_ports,
1679 sizeof(*widgets), GFP_KERNEL);
1680
1681 if (!widgets)
1682 return -ENOMEM;
1683
1684 route = devm_kcalloc(dapm->dev, hdmi->num_ports,
1685 sizeof(*route), GFP_KERNEL);
1686 if (!route)
1687 return -ENOMEM;
1688
1689 /* create Jack DAPM widget */
1690 list_for_each_entry(pin, &hdmi->pin_list, head) {
1691 for (j = 0; j < pin->num_ports; j++) {
1692 snprintf(w_name, sizeof(w_name), "hif%d-%d Jack",
1693 pin->nid, pin->ports[j].id);
1694
1695 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
1696 snd_soc_dapm_spk, NULL,
1697 w_name, NULL, NULL, 0, NULL, 0);
1698 if (ret < 0)
1699 return ret;
1700
1701 pin->ports[j].jack_pin = widgets[i].name;
1702 pin->ports[j].dapm = dapm;
1703
1704 /* add to route from Jack widget to output */
1705 hdac_hdmi_fill_route(&route[i], pin->ports[j].jack_pin,
1706 NULL, pin->ports[j].output_pin, NULL);
1707
1708 i++;
1709 }
1710 }
1711
1712 /* Add Route from Jack widget to the output widget */
1713 ret = snd_soc_dapm_new_controls(dapm, widgets, hdmi->num_ports);
1714 if (ret < 0)
1715 return ret;
1716
1717 ret = snd_soc_dapm_add_routes(dapm, route, hdmi->num_ports);
1718 if (ret < 0)
1719 return ret;
1720
1721 ret = snd_soc_dapm_new_widgets(dapm->card);
1722 if (ret < 0)
1723 return ret;
1724
1725 /* Add Jack Pin switch Kcontrol */
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001726 ret = create_fill_jack_kcontrols(dapm->card, hdev);
Jeeja KP0324e512017-02-07 19:09:55 +05301727
1728 if (ret < 0)
1729 return ret;
1730
1731 /* default set the Jack Pin switch to OFF */
1732 list_for_each_entry(pin, &hdmi->pin_list, head) {
1733 for (j = 0; j < pin->num_ports; j++)
1734 snd_soc_dapm_disable_pin(pin->ports[j].dapm,
1735 pin->ports[j].jack_pin);
1736 }
1737
1738 return 0;
1739}
1740EXPORT_SYMBOL_GPL(hdac_hdmi_jack_port_init);
1741
Jeeja KP62490012017-02-07 19:09:49 +05301742int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device,
1743 struct snd_soc_jack *jack)
Jeeja KP4a3478d2016-02-12 07:46:06 +05301744{
Kuninori Morimoto45101122018-01-29 04:36:54 +00001745 struct snd_soc_component *component = dai->component;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001746 struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component);
1747 struct hdac_device *hdev = hdmi->hdev;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301748 struct hdac_hdmi_pcm *pcm;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301749 struct snd_pcm *snd_pcm;
1750 int err;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301751
1752 /*
1753 * this is a new PCM device, create new pcm and
1754 * add to the pcm list
1755 */
Pierre-Louis Bossartc7ba4e52019-02-08 17:26:53 -06001756 pcm = devm_kzalloc(&hdev->dev, sizeof(*pcm), GFP_KERNEL);
Jeeja KP4a3478d2016-02-12 07:46:06 +05301757 if (!pcm)
1758 return -ENOMEM;
1759 pcm->pcm_id = device;
1760 pcm->cvt = hdmi->dai_map[dai->id].cvt;
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301761 pcm->jack_event = 0;
Jeeja KP62490012017-02-07 19:09:49 +05301762 pcm->jack = jack;
Jeeja KPab1eea12017-01-24 21:49:05 +05301763 mutex_init(&pcm->lock);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301764 INIT_LIST_HEAD(&pcm->port_list);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301765 snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device);
1766 if (snd_pcm) {
1767 err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap);
1768 if (err < 0) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001769 dev_err(&hdev->dev,
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301770 "chmap control add failed with err: %d for pcm: %d\n",
1771 err, device);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301772 return err;
1773 }
1774 }
1775
Jeeja KP4a3478d2016-02-12 07:46:06 +05301776 list_add_tail(&pcm->head, &hdmi->pcm_list);
1777
Jeeja KP62490012017-02-07 19:09:49 +05301778 return 0;
Jeeja KP4a3478d2016-02-12 07:46:06 +05301779}
1780EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init);
1781
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001782static void hdac_hdmi_present_sense_all_pins(struct hdac_device *hdev,
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301783 struct hdac_hdmi_priv *hdmi, bool detect_pin_caps)
1784{
1785 int i;
1786 struct hdac_hdmi_pin *pin;
1787
1788 list_for_each_entry(pin, &hdmi->pin_list, head) {
1789 if (detect_pin_caps) {
1790
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001791 if (hdac_hdmi_get_port_len(hdev, pin->nid) == 0)
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301792 pin->mst_capable = false;
1793 else
1794 pin->mst_capable = true;
1795 }
1796
1797 for (i = 0; i < pin->num_ports; i++) {
1798 if (!pin->mst_capable && i > 0)
1799 continue;
1800
1801 hdac_hdmi_present_sense(pin, &pin->ports[i]);
1802 }
1803 }
1804}
1805
Kuninori Morimoto45101122018-01-29 04:36:54 +00001806static int hdmi_codec_probe(struct snd_soc_component *component)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301807{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001808 struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component);
1809 struct hdac_device *hdev = hdmi->hdev;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301810 struct snd_soc_dapm_context *dapm =
Kuninori Morimoto45101122018-01-29 04:36:54 +00001811 snd_soc_component_get_dapm(component);
Vinod Koulb2047e92016-05-12 08:58:55 +05301812 struct hdac_ext_link *hlink = NULL;
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301813 int ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301814
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001815 hdmi->component = component;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301816
Vinod Koulb2047e92016-05-12 08:58:55 +05301817 /*
1818 * hold the ref while we probe, also no need to drop the ref on
1819 * exit, we call pm_runtime_suspend() so that will do for us
1820 */
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05001821 hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05301822 if (!hlink) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001823 dev_err(&hdev->dev, "hdac link not found\n");
Vinod Koul500e06b2016-05-31 19:09:55 +05301824 return -EIO;
1825 }
1826
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05001827 snd_hdac_ext_bus_link_get(hdev->bus, hlink);
Vinod Koulb2047e92016-05-12 08:58:55 +05301828
Subhransu S. Prusty79f4e922016-02-12 07:46:05 +05301829 ret = create_fill_widget_route_map(dapm);
1830 if (ret < 0)
1831 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301832
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001833 aops.audio_ptr = hdev;
Takashi Iwaia57942b2018-07-11 16:23:16 +02001834 ret = snd_hdac_acomp_register_notifier(hdev->bus, &aops);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301835 if (ret < 0) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001836 dev_err(&hdev->dev, "notifier register failed: err: %d\n", ret);
Subhransu S. Prustyb8a54542016-02-12 07:46:01 +05301837 return ret;
1838 }
1839
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001840 hdac_hdmi_present_sense_all_pins(hdev, hdmi, true);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301841 /* Imp: Store the card pointer in hda_codec */
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001842 hdmi->card = dapm->card->snd_card;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301843
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301844 /*
Libin Yang01c83272019-04-13 21:18:12 +08001845 * Setup a device_link between card device and HDMI codec device.
1846 * The card device is the consumer and the HDMI codec device is
1847 * the supplier. With this setting, we can make sure that the audio
1848 * domain in display power will be always turned on before operating
1849 * on the HDMI audio codec registers.
1850 * Let's use the flag DL_FLAG_AUTOREMOVE_CONSUMER. This can make
1851 * sure the device link is freed when the machine driver is removed.
1852 */
1853 device_link_add(component->card->dev, &hdev->dev, DL_FLAG_RPM_ACTIVE |
1854 DL_FLAG_AUTOREMOVE_CONSUMER);
1855 /*
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301856 * hdac_device core already sets the state to active and calls
1857 * get_noresume. So enable runtime and set the device to suspend.
1858 */
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001859 pm_runtime_enable(&hdev->dev);
1860 pm_runtime_put(&hdev->dev);
1861 pm_runtime_suspend(&hdev->dev);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301862
1863 return 0;
1864}
1865
Kuninori Morimoto45101122018-01-29 04:36:54 +00001866static void hdmi_codec_remove(struct snd_soc_component *component)
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301867{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001868 struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component);
1869 struct hdac_device *hdev = hdmi->hdev;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05301870
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001871 pm_runtime_disable(&hdev->dev);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301872}
1873
Takashi Iwai687ae9e2019-01-08 11:37:31 +01001874#ifdef CONFIG_PM_SLEEP
1875static int hdmi_codec_resume(struct device *dev)
Jeeja KP571d5072016-02-22 07:50:33 +05301876{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001877 struct hdac_device *hdev = dev_to_hdac_dev(dev);
1878 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Takashi Iwai687ae9e2019-01-08 11:37:31 +01001879 int ret;
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05301880
Takashi Iwai687ae9e2019-01-08 11:37:31 +01001881 ret = pm_runtime_force_resume(dev);
1882 if (ret < 0)
1883 return ret;
Jeeja KP571d5072016-02-22 07:50:33 +05301884 /*
1885 * As the ELD notify callback request is not entertained while the
1886 * device is in suspend state. Need to manually check detection of
Jeeja KPa9ce96b2017-02-07 19:09:46 +05301887 * all pins here. pin capablity change is not support, so use the
1888 * already set pin caps.
Takashi Iwai687ae9e2019-01-08 11:37:31 +01001889 *
1890 * NOTE: this is safe to call even if the codec doesn't actually resume.
1891 * The pin check involves only with DRM audio component hooks, so it
1892 * works even if the HD-audio side is still dreaming peacefully.
Jeeja KP571d5072016-02-22 07:50:33 +05301893 */
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001894 hdac_hdmi_present_sense_all_pins(hdev, hdmi, false);
Takashi Iwai687ae9e2019-01-08 11:37:31 +01001895 return 0;
Jeeja KP571d5072016-02-22 07:50:33 +05301896}
1897#else
Takashi Iwai687ae9e2019-01-08 11:37:31 +01001898#define hdmi_codec_resume NULL
Jeeja KP571d5072016-02-22 07:50:33 +05301899#endif
1900
Kuninori Morimoto45101122018-01-29 04:36:54 +00001901static const struct snd_soc_component_driver hdmi_hda_codec = {
1902 .probe = hdmi_codec_probe,
1903 .remove = hdmi_codec_remove,
1904 .use_pmdown_time = 1,
1905 .endianness = 1,
1906 .non_legacy_dai_naming = 1,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301907};
1908
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301909static void hdac_hdmi_get_chmap(struct hdac_device *hdev, int pcm_idx,
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301910 unsigned char *chmap)
1911{
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301912 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301913 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301914
Jeeja KPab1eea12017-01-24 21:49:05 +05301915 memcpy(chmap, pcm->chmap, ARRAY_SIZE(pcm->chmap));
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301916}
1917
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301918static void hdac_hdmi_set_chmap(struct hdac_device *hdev, int pcm_idx,
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301919 unsigned char *chmap, int prepared)
1920{
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301921 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301922 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301923 struct hdac_hdmi_port *port;
1924
Subhransu S. Prustyeb50fa12017-11-07 16:16:25 +05301925 if (!pcm)
1926 return;
1927
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301928 if (list_empty(&pcm->port_list))
1929 return;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301930
Jeeja KPab1eea12017-01-24 21:49:05 +05301931 mutex_lock(&pcm->lock);
1932 pcm->chmap_set = true;
1933 memcpy(pcm->chmap, chmap, ARRAY_SIZE(pcm->chmap));
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301934 list_for_each_entry(port, &pcm->port_list, head)
1935 if (prepared)
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001936 hdac_hdmi_setup_audio_infoframe(hdev, pcm, port);
Jeeja KPab1eea12017-01-24 21:49:05 +05301937 mutex_unlock(&pcm->lock);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301938}
1939
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301940static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdev, int pcm_idx)
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301941{
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301942 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301943 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301944
Subhransu S. Prustyeb50fa12017-11-07 16:16:25 +05301945 if (!pcm)
1946 return false;
1947
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301948 if (list_empty(&pcm->port_list))
1949 return false;
1950
1951 return true;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301952}
1953
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301954static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdev, int pcm_idx)
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301955{
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301956 struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301957 struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301958 struct hdac_hdmi_port *port;
1959
Subhransu S. Prustyeb50fa12017-11-07 16:16:25 +05301960 if (!pcm)
1961 return 0;
1962
Jeeja KPe0e5d3e2017-02-07 19:09:48 +05301963 if (list_empty(&pcm->port_list))
1964 return 0;
1965
1966 port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head);
1967
Jeeja KP754695f2017-02-06 12:09:14 +05301968 if (!port || !port->eld.eld_valid)
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301969 return 0;
1970
Jeeja KP754695f2017-02-06 12:09:14 +05301971 return port->eld.info.spk_alloc;
Subhransu S. Prusty28890992016-04-14 10:07:34 +05301972}
1973
Bard liao019033c2018-11-11 05:18:46 +08001974static struct hdac_hdmi_drv_data intel_icl_drv_data = {
1975 .vendor_nid = INTEL_VENDOR_NID_0x2,
1976 .port_map = icl_pin2port_map,
1977 .port_num = ARRAY_SIZE(icl_pin2port_map),
1978};
1979
Pradeep Tewani5622bc92017-07-20 11:40:56 +05301980static struct hdac_hdmi_drv_data intel_glk_drv_data = {
Bard liao019033c2018-11-11 05:18:46 +08001981 .vendor_nid = INTEL_VENDOR_NID_0xb,
Pradeep Tewani5622bc92017-07-20 11:40:56 +05301982};
1983
1984static struct hdac_hdmi_drv_data intel_drv_data = {
Bard liao019033c2018-11-11 05:18:46 +08001985 .vendor_nid = INTEL_VENDOR_NID_0x8,
Pradeep Tewani5622bc92017-07-20 11:40:56 +05301986};
1987
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001988static int hdac_hdmi_dev_probe(struct hdac_device *hdev)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301989{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05001990 struct hdac_hdmi_priv *hdmi_priv = NULL;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301991 struct snd_soc_dai_driver *hdmi_dais = NULL;
Vinod Koulb2047e92016-05-12 08:58:55 +05301992 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05301993 int num_dais = 0;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301994 int ret = 0;
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05301995 struct hdac_driver *hdrv = drv_to_hdac_driver(hdev->dev.driver);
1996 const struct hda_device_id *hdac_id = hdac_get_device_id(hdev, hdrv);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05301997
Vinod Koulb2047e92016-05-12 08:58:55 +05301998 /* hold the ref while we probe */
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05001999 hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05302000 if (!hlink) {
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002001 dev_err(&hdev->dev, "hdac link not found\n");
Vinod Koul500e06b2016-05-31 19:09:55 +05302002 return -EIO;
2003 }
2004
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05002005 snd_hdac_ext_bus_link_get(hdev->bus, hlink);
Vinod Koulb2047e92016-05-12 08:58:55 +05302006
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05302007 hdmi_priv = devm_kzalloc(&hdev->dev, sizeof(*hdmi_priv), GFP_KERNEL);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302008 if (hdmi_priv == NULL)
2009 return -ENOMEM;
2010
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05302011 snd_hdac_register_chmap_ops(hdev, &hdmi_priv->chmap);
Subhransu S. Prusty28890992016-04-14 10:07:34 +05302012 hdmi_priv->chmap.ops.get_chmap = hdac_hdmi_get_chmap;
2013 hdmi_priv->chmap.ops.set_chmap = hdac_hdmi_set_chmap;
2014 hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached;
2015 hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc;
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002016 hdmi_priv->hdev = hdev;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302017
Subhransu S. Prustyeb50fa12017-11-07 16:16:25 +05302018 if (!hdac_id)
2019 return -ENODEV;
2020
Pradeep Tewani5622bc92017-07-20 11:40:56 +05302021 if (hdac_id->driver_data)
2022 hdmi_priv->drv_data =
2023 (struct hdac_hdmi_drv_data *)hdac_id->driver_data;
2024 else
2025 hdmi_priv->drv_data = &intel_drv_data;
2026
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002027 dev_set_drvdata(&hdev->dev, hdmi_priv);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302028
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05302029 INIT_LIST_HEAD(&hdmi_priv->pin_list);
2030 INIT_LIST_HEAD(&hdmi_priv->cvt_list);
Jeeja KP4a3478d2016-02-12 07:46:06 +05302031 INIT_LIST_HEAD(&hdmi_priv->pcm_list);
2032 mutex_init(&hdmi_priv->pin_mutex);
Subhransu S. Prusty15b91442015-12-09 21:46:10 +05302033
Ramesh Babuaeaccef2016-02-17 21:34:01 +05302034 /*
2035 * Turned off in the runtime_suspend during the first explicit
2036 * pm_runtime_suspend call.
2037 */
Takashi Iwai4f799e72018-12-09 10:04:25 +01002038 snd_hdac_display_power(hdev->bus, hdev->addr, true);
2039
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002040 ret = hdac_hdmi_parse_and_map_nid(hdev, &hdmi_dais, &num_dais);
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05302041 if (ret < 0) {
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05302042 dev_err(&hdev->dev,
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05302043 "Failed in parse and map nid with err: %d\n", ret);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302044 return ret;
Subhransu S. Prusty17a42c42016-02-12 07:46:04 +05302045 }
Puneeth Prabhu0fb02ba2017-12-06 16:34:05 +05302046 snd_hdac_refresh_widgets(hdev, true);
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302047
2048 /* ASoC specific initialization */
Kuninori Morimoto45101122018-01-29 04:36:54 +00002049 ret = devm_snd_soc_register_component(&hdev->dev, &hdmi_hda_codec,
Vinod Koulb2047e92016-05-12 08:58:55 +05302050 hdmi_dais, num_dais);
2051
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05002052 snd_hdac_ext_bus_link_put(hdev->bus, hlink);
Vinod Koulb2047e92016-05-12 08:58:55 +05302053
2054 return ret;
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302055}
2056
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002057static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302058{
Takashi Iwai77a49672018-12-09 10:06:59 +01002059 snd_hdac_display_power(hdev->bus, hdev->addr, false);
2060
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302061 return 0;
2062}
2063
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302064#ifdef CONFIG_PM
2065static int hdac_hdmi_runtime_suspend(struct device *dev)
2066{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002067 struct hdac_device *hdev = dev_to_hdac_dev(dev);
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05302068 struct hdac_bus *bus = hdev->bus;
Vinod Koulb2047e92016-05-12 08:58:55 +05302069 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302070
2071 dev_dbg(dev, "Enter: %s\n", __func__);
2072
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05302073 /* controller may not have been initialized for the first time */
2074 if (!bus)
2075 return 0;
2076
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05302077 /*
2078 * Power down afg.
2079 * codec_read is preferred over codec_write to set the power state.
2080 * This way verb is send to set the power state and response
2081 * is received. So setting power state is ensured without using loop
2082 * to read the state.
2083 */
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05302084 snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05302085 AC_PWRST_D3);
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05302086
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05002087 hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05302088 if (!hlink) {
2089 dev_err(dev, "hdac link not found\n");
2090 return -EIO;
2091 }
2092
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05002093 snd_hdac_ext_bus_link_put(bus, hlink);
Vinod Koulb2047e92016-05-12 08:58:55 +05302094
Takashi Iwai4f799e72018-12-09 10:04:25 +01002095 snd_hdac_display_power(bus, hdev->addr, false);
Pierre-Louis Bossart4c104732018-11-09 13:39:23 -06002096
Takashi Iwai4f799e72018-12-09 10:04:25 +01002097 return 0;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302098}
2099
2100static int hdac_hdmi_runtime_resume(struct device *dev)
2101{
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002102 struct hdac_device *hdev = dev_to_hdac_dev(dev);
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05302103 struct hdac_bus *bus = hdev->bus;
Vinod Koulb2047e92016-05-12 08:58:55 +05302104 struct hdac_ext_link *hlink = NULL;
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302105
2106 dev_dbg(dev, "Enter: %s\n", __func__);
2107
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05302108 /* controller may not have been initialized for the first time */
2109 if (!bus)
2110 return 0;
2111
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05002112 hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev));
Vinod Koul500e06b2016-05-31 19:09:55 +05302113 if (!hlink) {
2114 dev_err(dev, "hdac link not found\n");
2115 return -EIO;
2116 }
2117
Rakesh Ughreja76f56fa2018-06-01 22:53:50 -05002118 snd_hdac_ext_bus_link_get(bus, hlink);
Vinod Koulb2047e92016-05-12 08:58:55 +05302119
Takashi Iwai4f799e72018-12-09 10:04:25 +01002120 snd_hdac_display_power(bus, hdev->addr, true);
Subhransu S. Prusty07f083a2015-11-10 18:42:10 +05302121
Rakesh Ughreja3787a392018-06-01 22:53:49 -05002122 hdac_hdmi_skl_enable_all_pins(hdev);
2123 hdac_hdmi_skl_enable_dp12(hdev);
Subhransu S. Prustyab85f5b2016-02-17 21:34:02 +05302124
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302125 /* Power up afg */
Ughreja, Rakesh Af0c5ebe2017-12-01 14:43:19 +05302126 snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
Subhransu S. Prusty1b377cc2016-04-01 13:36:26 +05302127 AC_PWRST_D0);
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302128
2129 return 0;
2130}
2131#else
2132#define hdac_hdmi_runtime_suspend NULL
2133#define hdac_hdmi_runtime_resume NULL
2134#endif
2135
2136static const struct dev_pm_ops hdac_hdmi_pm = {
2137 SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
Takashi Iwai687ae9e2019-01-08 11:37:31 +01002138 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume)
Subhransu S. Prustye342ac02015-11-10 18:42:07 +05302139};
2140
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302141static const struct hda_device_id hdmi_list[] = {
2142 HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
Jeeja KPe2304802016-03-11 10:12:55 +05302143 HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0),
Shreyas NCcc216882016-07-11 22:02:09 +05302144 HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0),
Guneshwor Singh5fb6e0a2017-12-21 08:45:29 +05302145 HDA_CODEC_EXT_ENTRY(0x8086280c, 0x100000, "Cannonlake HDMI",
2146 &intel_glk_drv_data),
Pradeep Tewani5622bc92017-07-20 11:40:56 +05302147 HDA_CODEC_EXT_ENTRY(0x8086280d, 0x100000, "Geminilake HDMI",
2148 &intel_glk_drv_data),
Bard liao019033c2018-11-11 05:18:46 +08002149 HDA_CODEC_EXT_ENTRY(0x8086280f, 0x100000, "Icelake HDMI",
2150 &intel_icl_drv_data),
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302151 {}
2152};
2153
2154MODULE_DEVICE_TABLE(hdaudio, hdmi_list);
2155
Rakesh Ughrejae1df9312018-06-01 22:53:51 -05002156static struct hdac_driver hdmi_driver = {
2157 .driver = {
2158 .name = "HDMI HDA Codec",
2159 .pm = &hdac_hdmi_pm,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302160 },
Rakesh Ughrejae1df9312018-06-01 22:53:51 -05002161 .id_table = hdmi_list,
Subhransu S. Prusty18382ea2015-11-10 18:42:06 +05302162 .probe = hdac_hdmi_dev_probe,
2163 .remove = hdac_hdmi_dev_remove,
2164};
2165
2166static int __init hdmi_init(void)
2167{
2168 return snd_hda_ext_driver_register(&hdmi_driver);
2169}
2170
2171static void __exit hdmi_exit(void)
2172{
2173 snd_hda_ext_driver_unregister(&hdmi_driver);
2174}
2175
2176module_init(hdmi_init);
2177module_exit(hdmi_exit);
2178
2179MODULE_LICENSE("GPL v2");
2180MODULE_DESCRIPTION("HDMI HD codec");
2181MODULE_AUTHOR("Samreen Nilofer<samreen.nilofer@intel.com>");
2182MODULE_AUTHOR("Subhransu S. Prusty<subhransu.s.prusty@intel.com>");