xref: /openbmc/linux/sound/soc/intel/boards/kbl_da7219_max98357a.c (revision b181f7029bd71238ac2754ce7052dffd69432085)
1e149ca29SPierre-Louis Bossart // SPDX-License-Identifier: GPL-2.0-only
2b3ea70eeSNaveen Manohar // Copyright(c) 2017-18 Intel Corporation.
3b3ea70eeSNaveen Manohar 
4b3ea70eeSNaveen Manohar /*
5b3ea70eeSNaveen Manohar  * Intel Kabylake I2S Machine Driver with MAX98357A & DA7219 Codecs
6b3ea70eeSNaveen Manohar  *
7b3ea70eeSNaveen Manohar  * Modified from:
8b3ea70eeSNaveen Manohar  *   Intel Kabylake I2S Machine driver supporting MAXIM98927 and
9b3ea70eeSNaveen Manohar  *   RT5663 codecs
10b3ea70eeSNaveen Manohar  */
11b3ea70eeSNaveen Manohar 
12b3ea70eeSNaveen Manohar #include <linux/input.h>
13b3ea70eeSNaveen Manohar #include <linux/module.h>
14b3ea70eeSNaveen Manohar #include <linux/platform_device.h>
15b3ea70eeSNaveen Manohar #include <sound/core.h>
16b3ea70eeSNaveen Manohar #include <sound/jack.h>
17b3ea70eeSNaveen Manohar #include <sound/pcm.h>
18b3ea70eeSNaveen Manohar #include <sound/pcm_params.h>
19b3ea70eeSNaveen Manohar #include <sound/soc.h>
20b3ea70eeSNaveen Manohar #include "../../codecs/da7219.h"
21b3ea70eeSNaveen Manohar #include "../../codecs/hdac_hdmi.h"
22b3ea70eeSNaveen Manohar 
23b3ea70eeSNaveen Manohar #define KBL_DIALOG_CODEC_DAI "da7219-hifi"
24b3ea70eeSNaveen Manohar #define KBL_MAXIM_CODEC_DAI "HiFi"
25b3ea70eeSNaveen Manohar #define MAXIM_DEV0_NAME "MX98357A:00"
26b3ea70eeSNaveen Manohar #define DUAL_CHANNEL 2
27b3ea70eeSNaveen Manohar #define QUAD_CHANNEL 4
28b3ea70eeSNaveen Manohar 
29b3ea70eeSNaveen Manohar static struct snd_soc_card *kabylake_audio_card;
30b3ea70eeSNaveen Manohar static struct snd_soc_jack skylake_hdmi[3];
31b3ea70eeSNaveen Manohar 
32b3ea70eeSNaveen Manohar struct kbl_hdmi_pcm {
33b3ea70eeSNaveen Manohar 	struct list_head head;
34b3ea70eeSNaveen Manohar 	struct snd_soc_dai *codec_dai;
35b3ea70eeSNaveen Manohar 	int device;
36b3ea70eeSNaveen Manohar };
37b3ea70eeSNaveen Manohar 
38b3ea70eeSNaveen Manohar struct kbl_codec_private {
39b3ea70eeSNaveen Manohar 	struct snd_soc_jack kabylake_headset;
40b3ea70eeSNaveen Manohar 	struct list_head hdmi_pcm_list;
41b3ea70eeSNaveen Manohar };
42b3ea70eeSNaveen Manohar 
43b3ea70eeSNaveen Manohar enum {
44b3ea70eeSNaveen Manohar 	KBL_DPCM_AUDIO_PB = 0,
45b3ea70eeSNaveen Manohar 	KBL_DPCM_AUDIO_CP,
4674ed9e9bSMac Chiang 	KBL_DPCM_AUDIO_REF_CP,
47b3ea70eeSNaveen Manohar 	KBL_DPCM_AUDIO_DMIC_CP,
48b3ea70eeSNaveen Manohar 	KBL_DPCM_AUDIO_HDMI1_PB,
49b3ea70eeSNaveen Manohar 	KBL_DPCM_AUDIO_HDMI2_PB,
50b3ea70eeSNaveen Manohar 	KBL_DPCM_AUDIO_HDMI3_PB,
51b3ea70eeSNaveen Manohar };
52b3ea70eeSNaveen Manohar 
platform_clock_control(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)53b3ea70eeSNaveen Manohar static int platform_clock_control(struct snd_soc_dapm_widget *w,
54b3ea70eeSNaveen Manohar 					struct snd_kcontrol *k, int  event)
55b3ea70eeSNaveen Manohar {
56b3ea70eeSNaveen Manohar 	struct snd_soc_dapm_context *dapm = w->dapm;
57b3ea70eeSNaveen Manohar 	struct snd_soc_card *card = dapm->card;
58b3ea70eeSNaveen Manohar 	struct snd_soc_dai *codec_dai;
59b3ea70eeSNaveen Manohar 	int ret = 0;
60b3ea70eeSNaveen Manohar 
61b3ea70eeSNaveen Manohar 	codec_dai = snd_soc_card_get_codec_dai(card, KBL_DIALOG_CODEC_DAI);
62b3ea70eeSNaveen Manohar 	if (!codec_dai) {
63b3ea70eeSNaveen Manohar 		dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
64b3ea70eeSNaveen Manohar 		return -EIO;
65b3ea70eeSNaveen Manohar 	}
66b3ea70eeSNaveen Manohar 
67b3ea70eeSNaveen Manohar 	if (SND_SOC_DAPM_EVENT_OFF(event)) {
68b3ea70eeSNaveen Manohar 		ret = snd_soc_dai_set_pll(codec_dai, 0,
69b3ea70eeSNaveen Manohar 				     DA7219_SYSCLK_MCLK, 0, 0);
70b3ea70eeSNaveen Manohar 		if (ret)
71b3ea70eeSNaveen Manohar 			dev_err(card->dev, "failed to stop PLL: %d\n", ret);
72b3ea70eeSNaveen Manohar 	} else if (SND_SOC_DAPM_EVENT_ON(event)) {
73b3ea70eeSNaveen Manohar 		ret = snd_soc_dai_set_pll(codec_dai, 0,	DA7219_SYSCLK_PLL_SRM,
74b3ea70eeSNaveen Manohar 				     0, DA7219_PLL_FREQ_OUT_98304);
75b3ea70eeSNaveen Manohar 		if (ret)
76b3ea70eeSNaveen Manohar 			dev_err(card->dev, "failed to start PLL: %d\n", ret);
77b3ea70eeSNaveen Manohar 	}
78b3ea70eeSNaveen Manohar 
79b3ea70eeSNaveen Manohar 	return ret;
80b3ea70eeSNaveen Manohar }
81b3ea70eeSNaveen Manohar 
82b3ea70eeSNaveen Manohar static const struct snd_kcontrol_new kabylake_controls[] = {
83b3ea70eeSNaveen Manohar 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
84b3ea70eeSNaveen Manohar 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
85b3ea70eeSNaveen Manohar 	SOC_DAPM_PIN_SWITCH("Spk"),
86da09176fSAlper Nebi Yasak 	SOC_DAPM_PIN_SWITCH("Line Out"),
87b3ea70eeSNaveen Manohar };
88b3ea70eeSNaveen Manohar 
89b3ea70eeSNaveen Manohar static const struct snd_soc_dapm_widget kabylake_widgets[] = {
90b3ea70eeSNaveen Manohar 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
91b3ea70eeSNaveen Manohar 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
92b3ea70eeSNaveen Manohar 	SND_SOC_DAPM_SPK("Spk", NULL),
93da09176fSAlper Nebi Yasak 	SND_SOC_DAPM_LINE("Line Out", NULL),
94b3ea70eeSNaveen Manohar 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
95c7c19ec0SVamshi Krishna Gopal 	SND_SOC_DAPM_SPK("HDMI1", NULL),
96c7c19ec0SVamshi Krishna Gopal 	SND_SOC_DAPM_SPK("HDMI2", NULL),
97c7c19ec0SVamshi Krishna Gopal 	SND_SOC_DAPM_SPK("HDMI3", NULL),
98b3ea70eeSNaveen Manohar 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
99b3ea70eeSNaveen Manohar 			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
100b3ea70eeSNaveen Manohar 			SND_SOC_DAPM_POST_PMD),
101b3ea70eeSNaveen Manohar };
102b3ea70eeSNaveen Manohar 
103c2065d43SPierre-Louis Bossart static struct snd_soc_jack_pin jack_pins[] = {
104c2065d43SPierre-Louis Bossart 	{
105c2065d43SPierre-Louis Bossart 		.pin    = "Headphone Jack",
106c2065d43SPierre-Louis Bossart 		.mask   = SND_JACK_HEADPHONE,
107c2065d43SPierre-Louis Bossart 	},
108c2065d43SPierre-Louis Bossart 	{
109c2065d43SPierre-Louis Bossart 		.pin    = "Headset Mic",
110c2065d43SPierre-Louis Bossart 		.mask   = SND_JACK_MICROPHONE,
111c2065d43SPierre-Louis Bossart 	},
112da09176fSAlper Nebi Yasak 	{
113da09176fSAlper Nebi Yasak 		.pin    = "Line Out",
114da09176fSAlper Nebi Yasak 		.mask   = SND_JACK_LINEOUT,
115da09176fSAlper Nebi Yasak 	},
116c2065d43SPierre-Louis Bossart };
117c2065d43SPierre-Louis Bossart 
118b3ea70eeSNaveen Manohar static const struct snd_soc_dapm_route kabylake_map[] = {
119b3ea70eeSNaveen Manohar 	{ "Headphone Jack", NULL, "HPL" },
120b3ea70eeSNaveen Manohar 	{ "Headphone Jack", NULL, "HPR" },
121b3ea70eeSNaveen Manohar 
122b3ea70eeSNaveen Manohar 	/* speaker */
123b3ea70eeSNaveen Manohar 	{ "Spk", NULL, "Speaker" },
124b3ea70eeSNaveen Manohar 
125b3ea70eeSNaveen Manohar 	/* other jacks */
126b3ea70eeSNaveen Manohar 	{ "MIC", NULL, "Headset Mic" },
127b3ea70eeSNaveen Manohar 	{ "DMic", NULL, "SoC DMIC" },
128b3ea70eeSNaveen Manohar 
129c7c19ec0SVamshi Krishna Gopal 	{"HDMI1", NULL, "hif5-0 Output"},
130c7c19ec0SVamshi Krishna Gopal 	{"HDMI2", NULL, "hif6-0 Output"},
131c7c19ec0SVamshi Krishna Gopal 	{"HDMI3", NULL, "hif7-0 Output"},
132b3ea70eeSNaveen Manohar 
133b3ea70eeSNaveen Manohar 	/* CODEC BE connections */
134b3ea70eeSNaveen Manohar 	{ "HiFi Playback", NULL, "ssp0 Tx" },
135b3ea70eeSNaveen Manohar 	{ "ssp0 Tx", NULL, "codec0_out" },
136b3ea70eeSNaveen Manohar 
137b3ea70eeSNaveen Manohar 	{ "Playback", NULL, "ssp1 Tx" },
138b3ea70eeSNaveen Manohar 	{ "ssp1 Tx", NULL, "codec1_out" },
139b3ea70eeSNaveen Manohar 
140b3ea70eeSNaveen Manohar 	{ "codec0_in", NULL, "ssp1 Rx" },
141b3ea70eeSNaveen Manohar 	{ "ssp1 Rx", NULL, "Capture" },
142b3ea70eeSNaveen Manohar 
143b3ea70eeSNaveen Manohar 	/* DMIC */
144b3ea70eeSNaveen Manohar 	{ "dmic01_hifi", NULL, "DMIC01 Rx" },
145b3ea70eeSNaveen Manohar 	{ "DMIC01 Rx", NULL, "DMIC AIF" },
146b3ea70eeSNaveen Manohar 
147b3ea70eeSNaveen Manohar 	{ "hifi1", NULL, "iDisp1 Tx" },
148b3ea70eeSNaveen Manohar 	{ "iDisp1 Tx", NULL, "iDisp1_out" },
149b3ea70eeSNaveen Manohar 	{ "hifi2", NULL, "iDisp2 Tx" },
150b3ea70eeSNaveen Manohar 	{ "iDisp2 Tx", NULL, "iDisp2_out" },
151b3ea70eeSNaveen Manohar 	{ "hifi3", NULL, "iDisp3 Tx"},
152b3ea70eeSNaveen Manohar 	{ "iDisp3 Tx", NULL, "iDisp3_out"},
153b3ea70eeSNaveen Manohar 
154b3ea70eeSNaveen Manohar 	{ "Headphone Jack", NULL, "Platform Clock" },
155b3ea70eeSNaveen Manohar 	{ "Headset Mic", NULL, "Platform Clock" },
156da09176fSAlper Nebi Yasak 	{ "Line Out", NULL, "Platform Clock" },
157b3ea70eeSNaveen Manohar };
158b3ea70eeSNaveen Manohar 
kabylake_ssp_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)159b3ea70eeSNaveen Manohar static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
160b3ea70eeSNaveen Manohar 			struct snd_pcm_hw_params *params)
161b3ea70eeSNaveen Manohar {
162b3ea70eeSNaveen Manohar 	struct snd_interval *rate = hw_param_interval(params,
163b3ea70eeSNaveen Manohar 			SNDRV_PCM_HW_PARAM_RATE);
1642e539cf7SPierre-Louis Bossart 	struct snd_interval *chan = hw_param_interval(params,
165b3ea70eeSNaveen Manohar 			SNDRV_PCM_HW_PARAM_CHANNELS);
166b3ea70eeSNaveen Manohar 	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
167b3ea70eeSNaveen Manohar 
168b3ea70eeSNaveen Manohar 	/* The ADSP will convert the FE rate to 48k, stereo */
169b3ea70eeSNaveen Manohar 	rate->min = rate->max = 48000;
1702e539cf7SPierre-Louis Bossart 	chan->min = chan->max = DUAL_CHANNEL;
171b3ea70eeSNaveen Manohar 
172b3ea70eeSNaveen Manohar 	/* set SSP to 24 bit */
173b3ea70eeSNaveen Manohar 	snd_mask_none(fmt);
174b5453e8cSTakashi Iwai 	snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
175b3ea70eeSNaveen Manohar 
176b3ea70eeSNaveen Manohar 	return 0;
177b3ea70eeSNaveen Manohar }
178b3ea70eeSNaveen Manohar 
kabylake_da7219_codec_init(struct snd_soc_pcm_runtime * rtd)179b3ea70eeSNaveen Manohar static int kabylake_da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
180b3ea70eeSNaveen Manohar {
181b3ea70eeSNaveen Manohar 	struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
1820d1571c1SKuninori Morimoto 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
1830d1571c1SKuninori Morimoto 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
184b3ea70eeSNaveen Manohar 	struct snd_soc_jack *jack;
185b3ea70eeSNaveen Manohar 	int ret;
186b3ea70eeSNaveen Manohar 
18756c3a953SMac Chiang 	/* Configure sysclk for codec */
18856c3a953SMac Chiang 	ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24576000,
18956c3a953SMac Chiang 						SND_SOC_CLOCK_IN);
19056c3a953SMac Chiang 	if (ret) {
19156c3a953SMac Chiang 		dev_err(rtd->dev, "can't set codec sysclk configuration\n");
19256c3a953SMac Chiang 		return ret;
19356c3a953SMac Chiang 	}
19456c3a953SMac Chiang 
195b3ea70eeSNaveen Manohar 	/*
196b3ea70eeSNaveen Manohar 	 * Headset buttons map to the google Reference headset.
197b3ea70eeSNaveen Manohar 	 * These can be configured by userspace.
198b3ea70eeSNaveen Manohar 	 */
199c2065d43SPierre-Louis Bossart 	ret = snd_soc_card_jack_new_pins(kabylake_audio_card, "Headset Jack",
200b3ea70eeSNaveen Manohar 					 SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
201b3ea70eeSNaveen Manohar 					 SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT,
202c2065d43SPierre-Louis Bossart 					 &ctx->kabylake_headset,
203c2065d43SPierre-Louis Bossart 					 jack_pins,
204c2065d43SPierre-Louis Bossart 					 ARRAY_SIZE(jack_pins));
205b3ea70eeSNaveen Manohar 	if (ret) {
206b3ea70eeSNaveen Manohar 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
207b3ea70eeSNaveen Manohar 		return ret;
208b3ea70eeSNaveen Manohar 	}
209b3ea70eeSNaveen Manohar 
210b3ea70eeSNaveen Manohar 	jack = &ctx->kabylake_headset;
211b3ea70eeSNaveen Manohar 
21216ec5dfeSMac Chiang 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
213b3ea70eeSNaveen Manohar 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
214b3ea70eeSNaveen Manohar 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
215b3ea70eeSNaveen Manohar 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
2169a1fe79dSCezary Rojewski 	snd_soc_component_set_jack(component, &ctx->kabylake_headset, NULL);
217b3ea70eeSNaveen Manohar 
218b3ea70eeSNaveen Manohar 	ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
219b3ea70eeSNaveen Manohar 	if (ret)
220b3ea70eeSNaveen Manohar 		dev_err(rtd->dev, "SoC DMIC - Ignore suspend failed %d\n", ret);
221b3ea70eeSNaveen Manohar 
222b3ea70eeSNaveen Manohar 	return ret;
223b3ea70eeSNaveen Manohar }
224b3ea70eeSNaveen Manohar 
kabylake_hdmi_init(struct snd_soc_pcm_runtime * rtd,int device)225b3ea70eeSNaveen Manohar static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device)
226b3ea70eeSNaveen Manohar {
227b3ea70eeSNaveen Manohar 	struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
2280d1571c1SKuninori Morimoto 	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
229b3ea70eeSNaveen Manohar 	struct kbl_hdmi_pcm *pcm;
230b3ea70eeSNaveen Manohar 
231b3ea70eeSNaveen Manohar 	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
232b3ea70eeSNaveen Manohar 	if (!pcm)
233b3ea70eeSNaveen Manohar 		return -ENOMEM;
234b3ea70eeSNaveen Manohar 
235b3ea70eeSNaveen Manohar 	pcm->device = device;
236b3ea70eeSNaveen Manohar 	pcm->codec_dai = dai;
237b3ea70eeSNaveen Manohar 
238b3ea70eeSNaveen Manohar 	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
239b3ea70eeSNaveen Manohar 
240b3ea70eeSNaveen Manohar 	return 0;
241b3ea70eeSNaveen Manohar }
242b3ea70eeSNaveen Manohar 
kabylake_hdmi1_init(struct snd_soc_pcm_runtime * rtd)243b3ea70eeSNaveen Manohar static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
244b3ea70eeSNaveen Manohar {
245b3ea70eeSNaveen Manohar 	return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB);
246b3ea70eeSNaveen Manohar }
247b3ea70eeSNaveen Manohar 
kabylake_hdmi2_init(struct snd_soc_pcm_runtime * rtd)248b3ea70eeSNaveen Manohar static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
249b3ea70eeSNaveen Manohar {
250b3ea70eeSNaveen Manohar 	return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB);
251b3ea70eeSNaveen Manohar }
252b3ea70eeSNaveen Manohar 
kabylake_hdmi3_init(struct snd_soc_pcm_runtime * rtd)253b3ea70eeSNaveen Manohar static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
254b3ea70eeSNaveen Manohar {
255b3ea70eeSNaveen Manohar 	return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB);
256b3ea70eeSNaveen Manohar }
257b3ea70eeSNaveen Manohar 
kabylake_da7219_fe_init(struct snd_soc_pcm_runtime * rtd)258b3ea70eeSNaveen Manohar static int kabylake_da7219_fe_init(struct snd_soc_pcm_runtime *rtd)
259b3ea70eeSNaveen Manohar {
260b3ea70eeSNaveen Manohar 	struct snd_soc_dapm_context *dapm;
2610d1571c1SKuninori Morimoto 	struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component;
262b3ea70eeSNaveen Manohar 
263b3ea70eeSNaveen Manohar 	dapm = snd_soc_component_get_dapm(component);
264b3ea70eeSNaveen Manohar 	snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
265b3ea70eeSNaveen Manohar 
266b3ea70eeSNaveen Manohar 	return 0;
267b3ea70eeSNaveen Manohar }
268b3ea70eeSNaveen Manohar 
269b3ea70eeSNaveen Manohar static const unsigned int rates[] = {
270b3ea70eeSNaveen Manohar 	48000,
271b3ea70eeSNaveen Manohar };
272b3ea70eeSNaveen Manohar 
273b3ea70eeSNaveen Manohar static const struct snd_pcm_hw_constraint_list constraints_rates = {
274b3ea70eeSNaveen Manohar 	.count = ARRAY_SIZE(rates),
275b3ea70eeSNaveen Manohar 	.list  = rates,
276b3ea70eeSNaveen Manohar 	.mask = 0,
277b3ea70eeSNaveen Manohar };
278b3ea70eeSNaveen Manohar 
279b3ea70eeSNaveen Manohar static const unsigned int channels[] = {
280b3ea70eeSNaveen Manohar 	DUAL_CHANNEL,
281b3ea70eeSNaveen Manohar };
282b3ea70eeSNaveen Manohar 
283b3ea70eeSNaveen Manohar static const struct snd_pcm_hw_constraint_list constraints_channels = {
284b3ea70eeSNaveen Manohar 	.count = ARRAY_SIZE(channels),
285b3ea70eeSNaveen Manohar 	.list = channels,
286b3ea70eeSNaveen Manohar 	.mask = 0,
287b3ea70eeSNaveen Manohar };
288b3ea70eeSNaveen Manohar 
289b3ea70eeSNaveen Manohar static unsigned int channels_quad[] = {
290b3ea70eeSNaveen Manohar 	QUAD_CHANNEL,
291b3ea70eeSNaveen Manohar };
292b3ea70eeSNaveen Manohar 
293b3ea70eeSNaveen Manohar static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
294b3ea70eeSNaveen Manohar 	.count = ARRAY_SIZE(channels_quad),
295b3ea70eeSNaveen Manohar 	.list = channels_quad,
296b3ea70eeSNaveen Manohar 	.mask = 0,
297b3ea70eeSNaveen Manohar };
298b3ea70eeSNaveen Manohar 
kbl_fe_startup(struct snd_pcm_substream * substream)299b3ea70eeSNaveen Manohar static int kbl_fe_startup(struct snd_pcm_substream *substream)
300b3ea70eeSNaveen Manohar {
301b3ea70eeSNaveen Manohar 	struct snd_pcm_runtime *runtime = substream->runtime;
302b3ea70eeSNaveen Manohar 
303b3ea70eeSNaveen Manohar 	/*
304b3ea70eeSNaveen Manohar 	 * On this platform for PCM device we support,
305b3ea70eeSNaveen Manohar 	 * 48Khz
306b3ea70eeSNaveen Manohar 	 * stereo
307b3ea70eeSNaveen Manohar 	 * 16 bit audio
308b3ea70eeSNaveen Manohar 	 */
309b3ea70eeSNaveen Manohar 
310b3ea70eeSNaveen Manohar 	runtime->hw.channels_max = DUAL_CHANNEL;
311b3ea70eeSNaveen Manohar 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
312b3ea70eeSNaveen Manohar 					   &constraints_channels);
313b3ea70eeSNaveen Manohar 
314b3ea70eeSNaveen Manohar 	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
315b3ea70eeSNaveen Manohar 	snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
316b3ea70eeSNaveen Manohar 
317b3ea70eeSNaveen Manohar 	snd_pcm_hw_constraint_list(runtime, 0,
318b3ea70eeSNaveen Manohar 				SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
319b3ea70eeSNaveen Manohar 
320b3ea70eeSNaveen Manohar 	return 0;
321b3ea70eeSNaveen Manohar }
322b3ea70eeSNaveen Manohar 
323b3ea70eeSNaveen Manohar static const struct snd_soc_ops kabylake_da7219_fe_ops = {
324b3ea70eeSNaveen Manohar 	.startup = kbl_fe_startup,
325b3ea70eeSNaveen Manohar };
326b3ea70eeSNaveen Manohar 
kabylake_dmic_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)327b3ea70eeSNaveen Manohar static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
328b3ea70eeSNaveen Manohar 		struct snd_pcm_hw_params *params)
329b3ea70eeSNaveen Manohar {
3302e539cf7SPierre-Louis Bossart 	struct snd_interval *chan = hw_param_interval(params,
331b3ea70eeSNaveen Manohar 				SNDRV_PCM_HW_PARAM_CHANNELS);
332b3ea70eeSNaveen Manohar 
333b3ea70eeSNaveen Manohar 	/*
334b3ea70eeSNaveen Manohar 	 * set BE channel constraint as user FE channels
335b3ea70eeSNaveen Manohar 	 */
336b3ea70eeSNaveen Manohar 
337b3ea70eeSNaveen Manohar 	if (params_channels(params) == 2)
3382e539cf7SPierre-Louis Bossart 		chan->min = chan->max = 2;
339b3ea70eeSNaveen Manohar 	else
3402e539cf7SPierre-Louis Bossart 		chan->min = chan->max = 4;
341b3ea70eeSNaveen Manohar 
342b3ea70eeSNaveen Manohar 	return 0;
343b3ea70eeSNaveen Manohar }
344b3ea70eeSNaveen Manohar 
kabylake_dmic_startup(struct snd_pcm_substream * substream)345b3ea70eeSNaveen Manohar static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
346b3ea70eeSNaveen Manohar {
347b3ea70eeSNaveen Manohar 	struct snd_pcm_runtime *runtime = substream->runtime;
348b3ea70eeSNaveen Manohar 
349b3ea70eeSNaveen Manohar 	runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
350b3ea70eeSNaveen Manohar 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
351b3ea70eeSNaveen Manohar 			&constraints_channels_quad);
352b3ea70eeSNaveen Manohar 
353b3ea70eeSNaveen Manohar 	return snd_pcm_hw_constraint_list(substream->runtime, 0,
354b3ea70eeSNaveen Manohar 			SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
355b3ea70eeSNaveen Manohar }
356b3ea70eeSNaveen Manohar 
357b3ea70eeSNaveen Manohar static struct snd_soc_ops kabylake_dmic_ops = {
358b3ea70eeSNaveen Manohar 	.startup = kabylake_dmic_startup,
359b3ea70eeSNaveen Manohar };
360b3ea70eeSNaveen Manohar 
36174ed9e9bSMac Chiang static unsigned int rates_16000[] = {
36274ed9e9bSMac Chiang         16000,
36374ed9e9bSMac Chiang };
36474ed9e9bSMac Chiang 
36574ed9e9bSMac Chiang static const struct snd_pcm_hw_constraint_list constraints_16000 = {
36674ed9e9bSMac Chiang         .count = ARRAY_SIZE(rates_16000),
36774ed9e9bSMac Chiang         .list  = rates_16000,
36874ed9e9bSMac Chiang };
36974ed9e9bSMac Chiang 
37074ed9e9bSMac Chiang static const unsigned int ch_mono[] = {
37174ed9e9bSMac Chiang 	1,
37274ed9e9bSMac Chiang };
37374ed9e9bSMac Chiang 
37474ed9e9bSMac Chiang static const struct snd_pcm_hw_constraint_list constraints_refcap = {
37574ed9e9bSMac Chiang 	.count = ARRAY_SIZE(ch_mono),
37674ed9e9bSMac Chiang 	.list  = ch_mono,
37774ed9e9bSMac Chiang };
37874ed9e9bSMac Chiang 
kabylake_refcap_startup(struct snd_pcm_substream * substream)37974ed9e9bSMac Chiang static int kabylake_refcap_startup(struct snd_pcm_substream *substream)
38074ed9e9bSMac Chiang {
38174ed9e9bSMac Chiang 	substream->runtime->hw.channels_max = 1;
38274ed9e9bSMac Chiang 	snd_pcm_hw_constraint_list(substream->runtime, 0,
38374ed9e9bSMac Chiang 					SNDRV_PCM_HW_PARAM_CHANNELS,
38474ed9e9bSMac Chiang 					&constraints_refcap);
38574ed9e9bSMac Chiang 
38674ed9e9bSMac Chiang 	return snd_pcm_hw_constraint_list(substream->runtime, 0,
38774ed9e9bSMac Chiang 					SNDRV_PCM_HW_PARAM_RATE,
38874ed9e9bSMac Chiang 					&constraints_16000);
38974ed9e9bSMac Chiang }
39074ed9e9bSMac Chiang 
39174ed9e9bSMac Chiang static struct snd_soc_ops skylake_refcap_ops = {
39274ed9e9bSMac Chiang 	.startup = kabylake_refcap_startup,
39374ed9e9bSMac Chiang };
39474ed9e9bSMac Chiang 
39527eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(dummy,
39627eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_DUMMY()));
39727eb6c7cSKuninori Morimoto 
39827eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(system,
39927eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
40027eb6c7cSKuninori Morimoto 
40174ed9e9bSMac Chiang SND_SOC_DAILINK_DEF(reference,
40274ed9e9bSMac Chiang 	DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin")));
40374ed9e9bSMac Chiang 
40427eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(dmic,
40527eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
40627eb6c7cSKuninori Morimoto 
40727eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi1,
40827eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
40927eb6c7cSKuninori Morimoto 
41027eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi2,
41127eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
41227eb6c7cSKuninori Morimoto 
41327eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi3,
41427eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin")));
41527eb6c7cSKuninori Morimoto 
41627eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp0_pin,
41727eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
41827eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp0_codec,
41927eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC(MAXIM_DEV0_NAME,
42027eb6c7cSKuninori Morimoto 				      KBL_MAXIM_CODEC_DAI)));
42127eb6c7cSKuninori Morimoto 
42227eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp1_pin,
42327eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
42427eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp1_codec,
42527eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00",
42627eb6c7cSKuninori Morimoto 				      KBL_DIALOG_CODEC_DAI)));
42727eb6c7cSKuninori Morimoto 
42827eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(dmic_pin,
42927eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
43027eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(dmic_codec,
43127eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
43227eb6c7cSKuninori Morimoto 
43327eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp1_pin,
43427eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
43527eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp1_codec,
43627eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
43727eb6c7cSKuninori Morimoto 				      "intel-hdmi-hifi1")));
43827eb6c7cSKuninori Morimoto 
43927eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp2_pin,
44027eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
44127eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp2_codec,
44227eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
44327eb6c7cSKuninori Morimoto 
44427eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp3_pin,
44527eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
44627eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp3_codec,
44727eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
44827eb6c7cSKuninori Morimoto 
44927eb6c7cSKuninori Morimoto SND_SOC_DAILINK_DEF(platform,
45027eb6c7cSKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
45127eb6c7cSKuninori Morimoto 
452b3ea70eeSNaveen Manohar /* kabylake digital audio interface glue - connects codec <--> CPU */
453b3ea70eeSNaveen Manohar static struct snd_soc_dai_link kabylake_dais[] = {
454b3ea70eeSNaveen Manohar 	/* Front End DAI links */
455b3ea70eeSNaveen Manohar 	[KBL_DPCM_AUDIO_PB] = {
456b3ea70eeSNaveen Manohar 		.name = "Kbl Audio Port",
457b3ea70eeSNaveen Manohar 		.stream_name = "Audio",
458b3ea70eeSNaveen Manohar 		.dynamic = 1,
459b3ea70eeSNaveen Manohar 		.nonatomic = 1,
460b3ea70eeSNaveen Manohar 		.init = kabylake_da7219_fe_init,
461b3ea70eeSNaveen Manohar 		.trigger = {
462b3ea70eeSNaveen Manohar 			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
463b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
464b3ea70eeSNaveen Manohar 		.ops = &kabylake_da7219_fe_ops,
46527eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(system, dummy, platform),
466b3ea70eeSNaveen Manohar 	},
467b3ea70eeSNaveen Manohar 	[KBL_DPCM_AUDIO_CP] = {
468b3ea70eeSNaveen Manohar 		.name = "Kbl Audio Capture Port",
469b3ea70eeSNaveen Manohar 		.stream_name = "Audio Record",
470b3ea70eeSNaveen Manohar 		.dynamic = 1,
471b3ea70eeSNaveen Manohar 		.nonatomic = 1,
472b3ea70eeSNaveen Manohar 		.trigger = {
473b3ea70eeSNaveen Manohar 			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
474b3ea70eeSNaveen Manohar 		.dpcm_capture = 1,
4755fd46e64SMac Chiang 		.ops = &kabylake_da7219_fe_ops,
47627eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(system, dummy, platform),
477b3ea70eeSNaveen Manohar 	},
47874ed9e9bSMac Chiang 	[KBL_DPCM_AUDIO_REF_CP] = {
47974ed9e9bSMac Chiang 		.name = "Kbl Audio Reference cap",
48074ed9e9bSMac Chiang 		.stream_name = "Wake on Voice",
48174ed9e9bSMac Chiang 		.init = NULL,
48274ed9e9bSMac Chiang 		.dpcm_capture = 1,
48374ed9e9bSMac Chiang 		.nonatomic = 1,
48474ed9e9bSMac Chiang 		.dynamic = 1,
48574ed9e9bSMac Chiang 		.ops = &skylake_refcap_ops,
48674ed9e9bSMac Chiang 		SND_SOC_DAILINK_REG(reference, dummy, platform),
48774ed9e9bSMac Chiang 	},
488b3ea70eeSNaveen Manohar 	[KBL_DPCM_AUDIO_DMIC_CP] = {
489b3ea70eeSNaveen Manohar 		.name = "Kbl Audio DMIC cap",
490b3ea70eeSNaveen Manohar 		.stream_name = "dmiccap",
491b3ea70eeSNaveen Manohar 		.init = NULL,
492b3ea70eeSNaveen Manohar 		.dpcm_capture = 1,
493b3ea70eeSNaveen Manohar 		.nonatomic = 1,
494b3ea70eeSNaveen Manohar 		.dynamic = 1,
495b3ea70eeSNaveen Manohar 		.ops = &kabylake_dmic_ops,
49627eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(dmic, dummy, platform),
497b3ea70eeSNaveen Manohar 	},
498b3ea70eeSNaveen Manohar 	[KBL_DPCM_AUDIO_HDMI1_PB] = {
499b3ea70eeSNaveen Manohar 		.name = "Kbl HDMI Port1",
500b3ea70eeSNaveen Manohar 		.stream_name = "Hdmi1",
501b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
502b3ea70eeSNaveen Manohar 		.init = NULL,
503b3ea70eeSNaveen Manohar 		.trigger = {
504b3ea70eeSNaveen Manohar 			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
505b3ea70eeSNaveen Manohar 		.nonatomic = 1,
506b3ea70eeSNaveen Manohar 		.dynamic = 1,
50727eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
508b3ea70eeSNaveen Manohar 	},
509b3ea70eeSNaveen Manohar 	[KBL_DPCM_AUDIO_HDMI2_PB] = {
510b3ea70eeSNaveen Manohar 		.name = "Kbl HDMI Port2",
511b3ea70eeSNaveen Manohar 		.stream_name = "Hdmi2",
512b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
513b3ea70eeSNaveen Manohar 		.init = NULL,
514b3ea70eeSNaveen Manohar 		.trigger = {
515b3ea70eeSNaveen Manohar 			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
516b3ea70eeSNaveen Manohar 		.nonatomic = 1,
517b3ea70eeSNaveen Manohar 		.dynamic = 1,
51827eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
519b3ea70eeSNaveen Manohar 	},
520b3ea70eeSNaveen Manohar 	[KBL_DPCM_AUDIO_HDMI3_PB] = {
521b3ea70eeSNaveen Manohar 		.name = "Kbl HDMI Port3",
522b3ea70eeSNaveen Manohar 		.stream_name = "Hdmi3",
523b3ea70eeSNaveen Manohar 		.trigger = {
524b3ea70eeSNaveen Manohar 			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
525b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
526b3ea70eeSNaveen Manohar 		.init = NULL,
527b3ea70eeSNaveen Manohar 		.nonatomic = 1,
528b3ea70eeSNaveen Manohar 		.dynamic = 1,
52927eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(hdmi3, dummy, platform),
530b3ea70eeSNaveen Manohar 	},
531b3ea70eeSNaveen Manohar 
532b3ea70eeSNaveen Manohar 	/* Back End DAI links */
533b3ea70eeSNaveen Manohar 	{
534b3ea70eeSNaveen Manohar 		/* SSP0 - Codec */
535b3ea70eeSNaveen Manohar 		.name = "SSP0-Codec",
536b3ea70eeSNaveen Manohar 		.id = 0,
537b3ea70eeSNaveen Manohar 		.no_pcm = 1,
538b3ea70eeSNaveen Manohar 		.dai_fmt = SND_SOC_DAIFMT_I2S |
539b3ea70eeSNaveen Manohar 			SND_SOC_DAIFMT_NB_NF |
5405374b921SPeter Ujfalusi 			SND_SOC_DAIFMT_CBC_CFC,
541b3ea70eeSNaveen Manohar 		.ignore_pmdown_time = 1,
542b3ea70eeSNaveen Manohar 		.be_hw_params_fixup = kabylake_ssp_fixup,
543b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
54427eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
545b3ea70eeSNaveen Manohar 	},
546b3ea70eeSNaveen Manohar 	{
547b3ea70eeSNaveen Manohar 		/* SSP1 - Codec */
548b3ea70eeSNaveen Manohar 		.name = "SSP1-Codec",
549b3ea70eeSNaveen Manohar 		.id = 1,
550b3ea70eeSNaveen Manohar 		.no_pcm = 1,
551b3ea70eeSNaveen Manohar 		.init = kabylake_da7219_codec_init,
552b3ea70eeSNaveen Manohar 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
5535374b921SPeter Ujfalusi 			SND_SOC_DAIFMT_CBC_CFC,
554b3ea70eeSNaveen Manohar 		.ignore_pmdown_time = 1,
555b3ea70eeSNaveen Manohar 		.be_hw_params_fixup = kabylake_ssp_fixup,
556b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
557b3ea70eeSNaveen Manohar 		.dpcm_capture = 1,
55827eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform),
559b3ea70eeSNaveen Manohar 	},
560b3ea70eeSNaveen Manohar 	{
561b3ea70eeSNaveen Manohar 		.name = "dmic01",
562b3ea70eeSNaveen Manohar 		.id = 2,
563b3ea70eeSNaveen Manohar 		.be_hw_params_fixup = kabylake_dmic_fixup,
564b3ea70eeSNaveen Manohar 		.ignore_suspend = 1,
565b3ea70eeSNaveen Manohar 		.dpcm_capture = 1,
566b3ea70eeSNaveen Manohar 		.no_pcm = 1,
56727eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
568b3ea70eeSNaveen Manohar 	},
569b3ea70eeSNaveen Manohar 	{
570b3ea70eeSNaveen Manohar 		.name = "iDisp1",
571b3ea70eeSNaveen Manohar 		.id = 3,
572b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
573b3ea70eeSNaveen Manohar 		.init = kabylake_hdmi1_init,
574b3ea70eeSNaveen Manohar 		.no_pcm = 1,
57527eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
576b3ea70eeSNaveen Manohar 	},
577b3ea70eeSNaveen Manohar 	{
578b3ea70eeSNaveen Manohar 		.name = "iDisp2",
579b3ea70eeSNaveen Manohar 		.id = 4,
580b3ea70eeSNaveen Manohar 		.init = kabylake_hdmi2_init,
581b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
582b3ea70eeSNaveen Manohar 		.no_pcm = 1,
58327eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
584b3ea70eeSNaveen Manohar 	},
585b3ea70eeSNaveen Manohar 	{
586b3ea70eeSNaveen Manohar 		.name = "iDisp3",
587b3ea70eeSNaveen Manohar 		.id = 5,
588b3ea70eeSNaveen Manohar 		.init = kabylake_hdmi3_init,
589b3ea70eeSNaveen Manohar 		.dpcm_playback = 1,
590b3ea70eeSNaveen Manohar 		.no_pcm = 1,
59127eb6c7cSKuninori Morimoto 		SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
592b3ea70eeSNaveen Manohar 	},
593b3ea70eeSNaveen Manohar };
594b3ea70eeSNaveen Manohar 
595b3ea70eeSNaveen Manohar #define NAME_SIZE	32
kabylake_card_late_probe(struct snd_soc_card * card)596b3ea70eeSNaveen Manohar static int kabylake_card_late_probe(struct snd_soc_card *card)
597b3ea70eeSNaveen Manohar {
598b3ea70eeSNaveen Manohar 	struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card);
599b3ea70eeSNaveen Manohar 	struct kbl_hdmi_pcm *pcm;
600257aacebSKuninori Morimoto 	struct snd_soc_component *component = NULL;
601b3ea70eeSNaveen Manohar 	int err, i = 0;
602b3ea70eeSNaveen Manohar 	char jack_name[NAME_SIZE];
603b3ea70eeSNaveen Manohar 
604b3ea70eeSNaveen Manohar 	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
605257aacebSKuninori Morimoto 		component = pcm->codec_dai->component;
606b3ea70eeSNaveen Manohar 		snprintf(jack_name, sizeof(jack_name),
607b3ea70eeSNaveen Manohar 			"HDMI/DP, pcm=%d Jack", pcm->device);
608b3ea70eeSNaveen Manohar 		err = snd_soc_card_jack_new(card, jack_name,
60919aed2d6SAkihiko Odaki 					SND_JACK_AVOUT, &skylake_hdmi[i]);
610b3ea70eeSNaveen Manohar 
611b3ea70eeSNaveen Manohar 		if (err)
612b3ea70eeSNaveen Manohar 			return err;
613b3ea70eeSNaveen Manohar 
614b3ea70eeSNaveen Manohar 		err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
615b3ea70eeSNaveen Manohar 				&skylake_hdmi[i]);
616b3ea70eeSNaveen Manohar 		if (err < 0)
617b3ea70eeSNaveen Manohar 			return err;
618b3ea70eeSNaveen Manohar 
619b3ea70eeSNaveen Manohar 		i++;
620b3ea70eeSNaveen Manohar 
621b3ea70eeSNaveen Manohar 	}
622b3ea70eeSNaveen Manohar 
623257aacebSKuninori Morimoto 	if (!component)
624b3ea70eeSNaveen Manohar 		return -EINVAL;
625b3ea70eeSNaveen Manohar 
626257aacebSKuninori Morimoto 	return hdac_hdmi_jack_port_init(component, &card->dapm);
627b3ea70eeSNaveen Manohar }
628b3ea70eeSNaveen Manohar 
629b3ea70eeSNaveen Manohar /* kabylake audio machine driver for SPT + DA7219 */
630b3ea70eeSNaveen Manohar static struct snd_soc_card kabylake_audio_card_da7219_m98357a = {
631b3ea70eeSNaveen Manohar 	.name = "kblda7219max",
632b3ea70eeSNaveen Manohar 	.owner = THIS_MODULE,
633b3ea70eeSNaveen Manohar 	.dai_link = kabylake_dais,
634b3ea70eeSNaveen Manohar 	.num_links = ARRAY_SIZE(kabylake_dais),
635b3ea70eeSNaveen Manohar 	.controls = kabylake_controls,
636b3ea70eeSNaveen Manohar 	.num_controls = ARRAY_SIZE(kabylake_controls),
637b3ea70eeSNaveen Manohar 	.dapm_widgets = kabylake_widgets,
638b3ea70eeSNaveen Manohar 	.num_dapm_widgets = ARRAY_SIZE(kabylake_widgets),
639b3ea70eeSNaveen Manohar 	.dapm_routes = kabylake_map,
640b3ea70eeSNaveen Manohar 	.num_dapm_routes = ARRAY_SIZE(kabylake_map),
641b3ea70eeSNaveen Manohar 	.fully_routed = true,
642*48f3fe13SCezary Rojewski 	.disable_route_checks = true,
643b3ea70eeSNaveen Manohar 	.late_probe = kabylake_card_late_probe,
644b3ea70eeSNaveen Manohar };
645b3ea70eeSNaveen Manohar 
kabylake_audio_probe(struct platform_device * pdev)646b3ea70eeSNaveen Manohar static int kabylake_audio_probe(struct platform_device *pdev)
647b3ea70eeSNaveen Manohar {
648b3ea70eeSNaveen Manohar 	struct kbl_codec_private *ctx;
649b3ea70eeSNaveen Manohar 
6503069db24SVinod Koul 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
651b3ea70eeSNaveen Manohar 	if (!ctx)
652b3ea70eeSNaveen Manohar 		return -ENOMEM;
653b3ea70eeSNaveen Manohar 
654b3ea70eeSNaveen Manohar 	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
655b3ea70eeSNaveen Manohar 
656b3ea70eeSNaveen Manohar 	kabylake_audio_card =
657b3ea70eeSNaveen Manohar 		(struct snd_soc_card *)pdev->id_entry->driver_data;
658b3ea70eeSNaveen Manohar 
659b3ea70eeSNaveen Manohar 	kabylake_audio_card->dev = &pdev->dev;
660b3ea70eeSNaveen Manohar 	snd_soc_card_set_drvdata(kabylake_audio_card, ctx);
661b3ea70eeSNaveen Manohar 	return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card);
662b3ea70eeSNaveen Manohar }
663b3ea70eeSNaveen Manohar 
664b3ea70eeSNaveen Manohar static const struct platform_device_id kbl_board_ids[] = {
665b3ea70eeSNaveen Manohar 	{
66694efd726SPierre-Louis Bossart 		.name = "kbl_da7219_mx98357a",
667b3ea70eeSNaveen Manohar 		.driver_data =
668b3ea70eeSNaveen Manohar 			(kernel_ulong_t)&kabylake_audio_card_da7219_m98357a,
669b3ea70eeSNaveen Manohar 	},
670b3ea70eeSNaveen Manohar 	{ }
671b3ea70eeSNaveen Manohar };
67253b98536SPierre-Louis Bossart MODULE_DEVICE_TABLE(platform, kbl_board_ids);
673b3ea70eeSNaveen Manohar 
674b3ea70eeSNaveen Manohar static struct platform_driver kabylake_audio = {
675b3ea70eeSNaveen Manohar 	.probe = kabylake_audio_probe,
676b3ea70eeSNaveen Manohar 	.driver = {
677b3ea70eeSNaveen Manohar 		.name = "kbl_da7219_max98357a",
678b3ea70eeSNaveen Manohar 		.pm = &snd_soc_pm_ops,
679b3ea70eeSNaveen Manohar 	},
680b3ea70eeSNaveen Manohar 	.id_table = kbl_board_ids,
681b3ea70eeSNaveen Manohar };
682b3ea70eeSNaveen Manohar 
683b3ea70eeSNaveen Manohar module_platform_driver(kabylake_audio)
684b3ea70eeSNaveen Manohar 
685b3ea70eeSNaveen Manohar /* Module information */
686b3ea70eeSNaveen Manohar MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode");
687b3ea70eeSNaveen Manohar MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>");
688b3ea70eeSNaveen Manohar MODULE_LICENSE("GPL v2");
689