cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

glk_rt5682_max98357a.c (18072B)


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