1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright(c) 2018 Intel Corporation.
3
4/*
5 * Intel Geminilake I2S Machine Driver with MAX98357A & RT5682 Codecs
6 *
7 * Modified from:
8 *   Intel Apollolake I2S Machine driver
9 */
10
11#include <linux/input.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <sound/core.h>
15#include <sound/jack.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/soc-acpi.h>
20#include "../../codecs/rt5682.h"
21#include "../../codecs/rt5682s.h"
22#include "../../codecs/hdac_hdmi.h"
23#include "hda_dsp_common.h"
24
25/* The platform clock outputs 19.2Mhz clock to codec as I2S MCLK */
26#define GLK_PLAT_CLK_FREQ 19200000
27#define RT5682_PLL_FREQ (48000 * 512)
28#define RT5682_DAI_NAME "rt5682-aif1"
29#define RT5682S_DAI_NAME "rt5682s-aif1"
30#define GLK_MAXIM_CODEC_DAI "HiFi"
31#define RT5682_DEV0_NAME "i2c-10EC5682:00"
32#define RT5682S_DEV0_NAME "i2c-RTL5682:00"
33#define MAXIM_DEV0_NAME "MX98357A:00"
34#define DUAL_CHANNEL 2
35#define QUAD_CHANNEL 4
36#define NAME_SIZE 32
37
38static struct snd_soc_jack geminilake_hdmi[3];
39
40struct glk_hdmi_pcm {
41	struct list_head head;
42	struct snd_soc_dai *codec_dai;
43	int device;
44};
45
46struct glk_card_private {
47	struct snd_soc_jack geminilake_headset;
48	struct list_head hdmi_pcm_list;
49	bool common_hdmi_codec_drv;
50	int is_rt5682s;
51};
52
53enum {
54	GLK_DPCM_AUDIO_PB = 0,
55	GLK_DPCM_AUDIO_CP,
56	GLK_DPCM_AUDIO_HS_PB,
57	GLK_DPCM_AUDIO_ECHO_REF_CP,
58	GLK_DPCM_AUDIO_REF_CP,
59	GLK_DPCM_AUDIO_DMIC_CP,
60	GLK_DPCM_AUDIO_HDMI1_PB,
61	GLK_DPCM_AUDIO_HDMI2_PB,
62	GLK_DPCM_AUDIO_HDMI3_PB,
63};
64
65static const struct snd_kcontrol_new geminilake_controls[] = {
66	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
67	SOC_DAPM_PIN_SWITCH("Headset Mic"),
68	SOC_DAPM_PIN_SWITCH("Spk"),
69};
70
71static const struct snd_soc_dapm_widget geminilake_widgets[] = {
72	SND_SOC_DAPM_HP("Headphone Jack", NULL),
73	SND_SOC_DAPM_MIC("Headset Mic", NULL),
74	SND_SOC_DAPM_SPK("Spk", NULL),
75	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
76	SND_SOC_DAPM_SPK("HDMI1", NULL),
77	SND_SOC_DAPM_SPK("HDMI2", NULL),
78	SND_SOC_DAPM_SPK("HDMI3", NULL),
79};
80
81static struct snd_soc_jack_pin jack_pins[] = {
82	{
83		.pin    = "Headphone Jack",
84		.mask   = SND_JACK_HEADPHONE,
85	},
86	{
87		.pin    = "Headset Mic",
88		.mask   = SND_JACK_MICROPHONE,
89	},
90};
91
92static const struct snd_soc_dapm_route geminilake_map[] = {
93	/* HP jack connectors - unknown if we have jack detection */
94	{ "Headphone Jack", NULL, "HPOL" },
95	{ "Headphone Jack", NULL, "HPOR" },
96
97	/* speaker */
98	{ "Spk", NULL, "Speaker" },
99
100	/* other jacks */
101	{ "IN1P", NULL, "Headset Mic" },
102
103	/* digital mics */
104	{ "DMic", NULL, "SoC DMIC" },
105
106	/* CODEC BE connections */
107	{ "HiFi Playback", NULL, "ssp1 Tx" },
108	{ "ssp1 Tx", NULL, "codec0_out" },
109
110	{ "AIF1 Playback", NULL, "ssp2 Tx" },
111	{ "ssp2 Tx", NULL, "codec1_out" },
112
113	{ "codec0_in", NULL, "ssp2 Rx" },
114	{ "ssp2 Rx", NULL, "AIF1 Capture" },
115
116	{ "HDMI1", NULL, "hif5-0 Output" },
117	{ "HDMI2", NULL, "hif6-0 Output" },
118	{ "HDMI2", NULL, "hif7-0 Output" },
119
120	{ "hifi3", NULL, "iDisp3 Tx" },
121	{ "iDisp3 Tx", NULL, "iDisp3_out" },
122	{ "hifi2", NULL, "iDisp2 Tx" },
123	{ "iDisp2 Tx", NULL, "iDisp2_out" },
124	{ "hifi1", NULL, "iDisp1 Tx" },
125	{ "iDisp1 Tx", NULL, "iDisp1_out" },
126
127	/* DMIC */
128	{ "dmic01_hifi", NULL, "DMIC01 Rx" },
129	{ "DMIC01 Rx", NULL, "DMIC AIF" },
130};
131
132static int geminilake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
133			struct snd_pcm_hw_params *params)
134{
135	struct snd_interval *rate = hw_param_interval(params,
136			SNDRV_PCM_HW_PARAM_RATE);
137	struct snd_interval *chan = hw_param_interval(params,
138			SNDRV_PCM_HW_PARAM_CHANNELS);
139	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
140
141	/* The ADSP will convert the FE rate to 48k, stereo */
142	rate->min = rate->max = 48000;
143	chan->min = chan->max = DUAL_CHANNEL;
144
145	/* set SSP to 24 bit */
146	snd_mask_none(fmt);
147	snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
148
149	return 0;
150}
151
152static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
153{
154	struct glk_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
155	struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
156	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
157	struct snd_soc_jack *jack;
158	int pll_id, pll_source, clk_id, ret;
159
160	if (ctx->is_rt5682s) {
161		pll_id = RT5682S_PLL2;
162		pll_source = RT5682S_PLL_S_MCLK;
163		clk_id = RT5682S_SCLK_S_PLL2;
164	} else {
165		pll_id = RT5682_PLL1;
166		pll_source = RT5682_PLL1_S_MCLK;
167		clk_id = RT5682_SCLK_S_PLL1;
168	}
169
170	ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source,
171					GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
172	if (ret < 0) {
173		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
174		return ret;
175	}
176
177	/* Configure sysclk for codec */
178	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id,
179					RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
180	if (ret < 0)
181		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
182
183	/*
184	 * Headset buttons map to the google Reference headset.
185	 * These can be configured by userspace.
186	 */
187	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
188					 SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
189					 SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT,
190					 &ctx->geminilake_headset,
191					 jack_pins,
192					 ARRAY_SIZE(jack_pins));
193	if (ret) {
194		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
195		return ret;
196	}
197
198	jack = &ctx->geminilake_headset;
199
200	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
201	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
202	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
203	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
204
205	ret = snd_soc_component_set_jack(component, jack, NULL);
206
207	if (ret) {
208		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
209		return ret;
210	}
211
212	return ret;
213};
214
215static int geminilake_rt5682_hw_params(struct snd_pcm_substream *substream,
216	struct snd_pcm_hw_params *params)
217{
218	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
219	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
220	int ret;
221
222	/* Set valid bitmask & configuration for I2S in 24 bit */
223	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2, 24);
224	if (ret < 0) {
225		dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
226		return ret;
227	}
228
229	return ret;
230}
231
232static struct snd_soc_ops geminilake_rt5682_ops = {
233	.hw_params = geminilake_rt5682_hw_params,
234};
235
236static int geminilake_hdmi_init(struct snd_soc_pcm_runtime *rtd)
237{
238	struct glk_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
239	struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
240	struct glk_hdmi_pcm *pcm;
241
242	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
243	if (!pcm)
244		return -ENOMEM;
245
246	pcm->device = GLK_DPCM_AUDIO_HDMI1_PB + dai->id;
247	pcm->codec_dai = dai;
248
249	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
250
251	return 0;
252}
253
254static int geminilake_rt5682_fe_init(struct snd_soc_pcm_runtime *rtd)
255{
256	struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component;
257	struct snd_soc_dapm_context *dapm;
258	int ret;
259
260	dapm = snd_soc_component_get_dapm(component);
261	ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
262	if (ret) {
263		dev_err(rtd->dev, "Ref Cap ignore suspend failed %d\n", ret);
264		return ret;
265	}
266
267	return ret;
268}
269
270static const unsigned int rates[] = {
271	48000,
272};
273
274static const struct snd_pcm_hw_constraint_list constraints_rates = {
275	.count = ARRAY_SIZE(rates),
276	.list  = rates,
277	.mask = 0,
278};
279
280static unsigned int channels_quad[] = {
281	QUAD_CHANNEL,
282};
283
284static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
285	.count = ARRAY_SIZE(channels_quad),
286	.list = channels_quad,
287	.mask = 0,
288};
289
290static int geminilake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
291		struct snd_pcm_hw_params *params)
292{
293	struct snd_interval *chan = hw_param_interval(params,
294				SNDRV_PCM_HW_PARAM_CHANNELS);
295
296	/*
297	 * set BE channel constraint as user FE channels
298	 */
299	chan->min = chan->max = 4;
300
301	return 0;
302}
303
304static int geminilake_dmic_startup(struct snd_pcm_substream *substream)
305{
306	struct snd_pcm_runtime *runtime = substream->runtime;
307
308	runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
309	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
310			&constraints_channels_quad);
311
312	return snd_pcm_hw_constraint_list(substream->runtime, 0,
313			SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
314}
315
316static const struct snd_soc_ops geminilake_dmic_ops = {
317	.startup = geminilake_dmic_startup,
318};
319
320static const unsigned int rates_16000[] = {
321	16000,
322};
323
324static const struct snd_pcm_hw_constraint_list constraints_16000 = {
325	.count = ARRAY_SIZE(rates_16000),
326	.list  = rates_16000,
327};
328
329static int geminilake_refcap_startup(struct snd_pcm_substream *substream)
330{
331	return snd_pcm_hw_constraint_list(substream->runtime, 0,
332				SNDRV_PCM_HW_PARAM_RATE,
333				&constraints_16000);
334};
335
336static const struct snd_soc_ops geminilake_refcap_ops = {
337	.startup = geminilake_refcap_startup,
338};
339
340SND_SOC_DAILINK_DEF(dummy,
341	DAILINK_COMP_ARRAY(COMP_DUMMY()));
342
343SND_SOC_DAILINK_DEF(system,
344	DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
345
346SND_SOC_DAILINK_DEF(system2,
347	DAILINK_COMP_ARRAY(COMP_CPU("System Pin2")));
348
349SND_SOC_DAILINK_DEF(echoref,
350	DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin")));
351
352SND_SOC_DAILINK_DEF(reference,
353	DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin")));
354
355SND_SOC_DAILINK_DEF(dmic,
356	DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
357
358SND_SOC_DAILINK_DEF(hdmi1,
359	DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
360
361SND_SOC_DAILINK_DEF(hdmi2,
362	DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
363
364SND_SOC_DAILINK_DEF(hdmi3,
365	DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin")));
366
367SND_SOC_DAILINK_DEF(ssp1_pin,
368	DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
369SND_SOC_DAILINK_DEF(ssp1_codec,
370	DAILINK_COMP_ARRAY(COMP_CODEC(MAXIM_DEV0_NAME,
371				      GLK_MAXIM_CODEC_DAI)));
372
373SND_SOC_DAILINK_DEF(ssp2_pin,
374	DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin")));
375SND_SOC_DAILINK_DEF(ssp2_codec_5682,
376	DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
377				      RT5682_DAI_NAME)));
378SND_SOC_DAILINK_DEF(ssp2_codec_5682s,
379	DAILINK_COMP_ARRAY(COMP_CODEC(RT5682S_DEV0_NAME,
380				      RT5682S_DAI_NAME)));
381
382SND_SOC_DAILINK_DEF(dmic_pin,
383	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
384SND_SOC_DAILINK_DEF(dmic_codec,
385	DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
386
387SND_SOC_DAILINK_DEF(idisp1_pin,
388	DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
389SND_SOC_DAILINK_DEF(idisp1_codec,
390	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
391
392SND_SOC_DAILINK_DEF(idisp2_pin,
393	DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
394SND_SOC_DAILINK_DEF(idisp2_codec,
395	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
396
397SND_SOC_DAILINK_DEF(idisp3_pin,
398	DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
399SND_SOC_DAILINK_DEF(idisp3_codec,
400	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
401
402SND_SOC_DAILINK_DEF(platform,
403	DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0")));
404
405/* geminilake digital audio interface glue - connects codec <--> CPU */
406static struct snd_soc_dai_link geminilake_dais[] = {
407	/* Front End DAI links */
408	[GLK_DPCM_AUDIO_PB] = {
409		.name = "Glk Audio Port",
410		.stream_name = "Audio",
411		.dynamic = 1,
412		.nonatomic = 1,
413		.init = geminilake_rt5682_fe_init,
414		.trigger = {
415			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
416		.dpcm_playback = 1,
417		SND_SOC_DAILINK_REG(system, dummy, platform),
418	},
419	[GLK_DPCM_AUDIO_CP] = {
420		.name = "Glk Audio Capture Port",
421		.stream_name = "Audio Record",
422		.dynamic = 1,
423		.nonatomic = 1,
424		.trigger = {
425			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
426		.dpcm_capture = 1,
427		SND_SOC_DAILINK_REG(system, dummy, platform),
428	},
429	[GLK_DPCM_AUDIO_HS_PB] = {
430		.name = "Glk Audio Headset Playback",
431		.stream_name = "Headset Audio",
432		.dpcm_playback = 1,
433		.nonatomic = 1,
434		.dynamic = 1,
435		SND_SOC_DAILINK_REG(system2, dummy, platform),
436	},
437	[GLK_DPCM_AUDIO_ECHO_REF_CP] = {
438		.name = "Glk Audio Echo Reference cap",
439		.stream_name = "Echoreference Capture",
440		.init = NULL,
441		.dpcm_capture = 1,
442		.nonatomic = 1,
443		.dynamic = 1,
444		SND_SOC_DAILINK_REG(echoref, dummy, platform),
445	},
446	[GLK_DPCM_AUDIO_REF_CP] = {
447		.name = "Glk Audio Reference cap",
448		.stream_name = "Refcap",
449		.init = NULL,
450		.dpcm_capture = 1,
451		.nonatomic = 1,
452		.dynamic = 1,
453		.ops = &geminilake_refcap_ops,
454		SND_SOC_DAILINK_REG(reference, dummy, platform),
455	},
456	[GLK_DPCM_AUDIO_DMIC_CP] = {
457		.name = "Glk Audio DMIC cap",
458		.stream_name = "dmiccap",
459		.init = NULL,
460		.dpcm_capture = 1,
461		.nonatomic = 1,
462		.dynamic = 1,
463		.ops = &geminilake_dmic_ops,
464		SND_SOC_DAILINK_REG(dmic, dummy, platform),
465	},
466	[GLK_DPCM_AUDIO_HDMI1_PB] = {
467		.name = "Glk HDMI Port1",
468		.stream_name = "Hdmi1",
469		.dpcm_playback = 1,
470		.init = NULL,
471		.trigger = {
472			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
473		.nonatomic = 1,
474		.dynamic = 1,
475		SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
476	},
477	[GLK_DPCM_AUDIO_HDMI2_PB] =	{
478		.name = "Glk HDMI Port2",
479		.stream_name = "Hdmi2",
480		.dpcm_playback = 1,
481		.init = NULL,
482		.trigger = {
483			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
484		.nonatomic = 1,
485		.dynamic = 1,
486		SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
487	},
488	[GLK_DPCM_AUDIO_HDMI3_PB] =	{
489		.name = "Glk HDMI Port3",
490		.stream_name = "Hdmi3",
491		.trigger = {
492			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
493		.dpcm_playback = 1,
494		.init = NULL,
495		.nonatomic = 1,
496		.dynamic = 1,
497		SND_SOC_DAILINK_REG(hdmi3, dummy, platform),
498	},
499	/* Back End DAI links */
500	{
501		/* SSP1 - Codec */
502		.name = "SSP1-Codec",
503		.id = 0,
504		.no_pcm = 1,
505		.dai_fmt = SND_SOC_DAIFMT_I2S |
506			SND_SOC_DAIFMT_NB_NF |
507			SND_SOC_DAIFMT_CBC_CFC,
508		.ignore_pmdown_time = 1,
509		.be_hw_params_fixup = geminilake_ssp_fixup,
510		.dpcm_playback = 1,
511		SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform),
512	},
513	{
514		/* SSP2 - Codec */
515		.name = "SSP2-Codec",
516		.id = 1,
517		.no_pcm = 1,
518		.init = geminilake_rt5682_codec_init,
519		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
520			SND_SOC_DAIFMT_CBC_CFC,
521		.ignore_pmdown_time = 1,
522		.be_hw_params_fixup = geminilake_ssp_fixup,
523		.ops = &geminilake_rt5682_ops,
524		.dpcm_playback = 1,
525		.dpcm_capture = 1,
526		SND_SOC_DAILINK_REG(ssp2_pin, ssp2_codec_5682, platform),
527	},
528	{
529		.name = "dmic01",
530		.id = 2,
531		.ignore_suspend = 1,
532		.be_hw_params_fixup = geminilake_dmic_fixup,
533		.dpcm_capture = 1,
534		.no_pcm = 1,
535		SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
536	},
537	{
538		.name = "iDisp1",
539		.id = 3,
540		.init = geminilake_hdmi_init,
541		.dpcm_playback = 1,
542		.no_pcm = 1,
543		SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
544	},
545	{
546		.name = "iDisp2",
547		.id = 4,
548		.init = geminilake_hdmi_init,
549		.dpcm_playback = 1,
550		.no_pcm = 1,
551		SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
552	},
553	{
554		.name = "iDisp3",
555		.id = 5,
556		.init = geminilake_hdmi_init,
557		.dpcm_playback = 1,
558		.no_pcm = 1,
559		SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
560	},
561};
562
563static int glk_card_late_probe(struct snd_soc_card *card)
564{
565	struct glk_card_private *ctx = snd_soc_card_get_drvdata(card);
566	struct snd_soc_component *component = NULL;
567	char jack_name[NAME_SIZE];
568	struct glk_hdmi_pcm *pcm;
569	int err;
570	int i = 0;
571
572	if (list_empty(&ctx->hdmi_pcm_list))
573		return -EINVAL;
574
575	if (ctx->common_hdmi_codec_drv) {
576		pcm = list_first_entry(&ctx->hdmi_pcm_list, struct glk_hdmi_pcm,
577				       head);
578		component = pcm->codec_dai->component;
579		return hda_dsp_hdmi_build_controls(card, component);
580	}
581
582	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
583		component = pcm->codec_dai->component;
584		snprintf(jack_name, sizeof(jack_name),
585			"HDMI/DP, pcm=%d Jack", pcm->device);
586		err = snd_soc_card_jack_new(card, jack_name,
587					SND_JACK_AVOUT, &geminilake_hdmi[i]);
588
589		if (err)
590			return err;
591
592		err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
593						&geminilake_hdmi[i]);
594		if (err < 0)
595			return err;
596
597		i++;
598	}
599
600	return hdac_hdmi_jack_port_init(component, &card->dapm);
601}
602
603/* geminilake audio machine driver for SPT + RT5682 */
604static struct snd_soc_card glk_audio_card_rt5682_m98357a = {
605	.name = "glkrt5682max",
606	.owner = THIS_MODULE,
607	.dai_link = geminilake_dais,
608	.num_links = ARRAY_SIZE(geminilake_dais),
609	.controls = geminilake_controls,
610	.num_controls = ARRAY_SIZE(geminilake_controls),
611	.dapm_widgets = geminilake_widgets,
612	.num_dapm_widgets = ARRAY_SIZE(geminilake_widgets),
613	.dapm_routes = geminilake_map,
614	.num_dapm_routes = ARRAY_SIZE(geminilake_map),
615	.fully_routed = true,
616	.late_probe = glk_card_late_probe,
617};
618
619static int geminilake_audio_probe(struct platform_device *pdev)
620{
621	struct glk_card_private *ctx;
622	struct snd_soc_acpi_mach *mach;
623	const char *platform_name;
624	struct snd_soc_card *card;
625	int ret, i;
626
627	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
628	if (!ctx)
629		return -ENOMEM;
630
631	/* Detect the headset codec variant */
632	if (acpi_dev_present("RTL5682", NULL, -1)) {
633		/* ALC5682I-VS is detected */
634		ctx->is_rt5682s = 1;
635
636		for (i = 0; i < glk_audio_card_rt5682_m98357a.num_links; i++) {
637			if (strcmp(geminilake_dais[i].name, "SSP2-Codec"))
638				continue;
639
640			/* update the dai link to use rt5682s codec */
641			geminilake_dais[i].codecs = ssp2_codec_5682s;
642			geminilake_dais[i].num_codecs = ARRAY_SIZE(ssp2_codec_5682s);
643			break;
644		}
645	}
646
647	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
648
649	card = &glk_audio_card_rt5682_m98357a;
650	card->dev = &pdev->dev;
651	snd_soc_card_set_drvdata(card, ctx);
652
653	/* override platform name, if required */
654	mach = pdev->dev.platform_data;
655	platform_name = mach->mach_params.platform;
656
657	ret = snd_soc_fixup_dai_links_platform_name(card, platform_name);
658	if (ret)
659		return ret;
660
661	ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
662
663	return devm_snd_soc_register_card(&pdev->dev, card);
664}
665
666static const struct platform_device_id glk_board_ids[] = {
667	{
668		.name = "glk_rt5682_mx98357a",
669		.driver_data =
670			(kernel_ulong_t)&glk_audio_card_rt5682_m98357a,
671	},
672	{ }
673};
674MODULE_DEVICE_TABLE(platform, glk_board_ids);
675
676static struct platform_driver geminilake_audio = {
677	.probe = geminilake_audio_probe,
678	.driver = {
679		.name = "glk_rt5682_max98357a",
680		.pm = &snd_soc_pm_ops,
681	},
682	.id_table = glk_board_ids,
683};
684module_platform_driver(geminilake_audio)
685
686/* Module information */
687MODULE_DESCRIPTION("Geminilake Audio Machine driver-RT5682 & MAX98357A in I2S mode");
688MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>");
689MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
690MODULE_LICENSE("GPL v2");
691MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
692