Linux Audio

Check our new training course

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