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

bxt_rt298.c (16981B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Intel Broxton-P I2S Machine Driver
      4 *
      5 * Copyright (C) 2014-2016, Intel Corporation. All rights reserved.
      6 *
      7 * Modified from:
      8 *   Intel Skylake I2S Machine driver
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/platform_device.h>
     13#include <sound/core.h>
     14#include <sound/pcm.h>
     15#include <sound/soc.h>
     16#include <sound/soc-acpi.h>
     17#include <sound/jack.h>
     18#include <sound/pcm_params.h>
     19#include "../../codecs/hdac_hdmi.h"
     20#include "../../codecs/rt298.h"
     21#include "hda_dsp_common.h"
     22
     23/* Headset jack detection DAPM pins */
     24static struct snd_soc_jack broxton_headset;
     25static struct snd_soc_jack broxton_hdmi[3];
     26
     27struct bxt_hdmi_pcm {
     28	struct list_head head;
     29	struct snd_soc_dai *codec_dai;
     30	int device;
     31};
     32
     33struct bxt_rt286_private {
     34	struct list_head hdmi_pcm_list;
     35	bool common_hdmi_codec_drv;
     36};
     37
     38enum {
     39	BXT_DPCM_AUDIO_PB = 0,
     40	BXT_DPCM_AUDIO_CP,
     41	BXT_DPCM_AUDIO_REF_CP,
     42	BXT_DPCM_AUDIO_DMIC_CP,
     43	BXT_DPCM_AUDIO_HDMI1_PB,
     44	BXT_DPCM_AUDIO_HDMI2_PB,
     45	BXT_DPCM_AUDIO_HDMI3_PB,
     46};
     47
     48static struct snd_soc_jack_pin broxton_headset_pins[] = {
     49	{
     50		.pin = "Mic Jack",
     51		.mask = SND_JACK_MICROPHONE,
     52	},
     53	{
     54		.pin = "Headphone Jack",
     55		.mask = SND_JACK_HEADPHONE,
     56	},
     57};
     58
     59static const struct snd_kcontrol_new broxton_controls[] = {
     60	SOC_DAPM_PIN_SWITCH("Speaker"),
     61	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
     62	SOC_DAPM_PIN_SWITCH("Mic Jack"),
     63};
     64
     65static const struct snd_soc_dapm_widget broxton_widgets[] = {
     66	SND_SOC_DAPM_HP("Headphone Jack", NULL),
     67	SND_SOC_DAPM_SPK("Speaker", NULL),
     68	SND_SOC_DAPM_MIC("Mic Jack", NULL),
     69	SND_SOC_DAPM_MIC("DMIC2", 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 broxton_rt298_map[] = {
     77	/* speaker */
     78	{"Speaker", NULL, "SPOR"},
     79	{"Speaker", NULL, "SPOL"},
     80
     81	/* HP jack connectors - unknown if we have jack detect */
     82	{"Headphone Jack", NULL, "HPO Pin"},
     83
     84	/* other jacks */
     85	{"MIC1", NULL, "Mic Jack"},
     86
     87	/* digital mics */
     88	{"DMIC1 Pin", NULL, "DMIC2"},
     89	{"DMic", NULL, "SoC DMIC"},
     90
     91	{"HDMI1", NULL, "hif5-0 Output"},
     92	{"HDMI2", NULL, "hif6-0 Output"},
     93	{"HDMI2", NULL, "hif7-0 Output"},
     94
     95	/* CODEC BE connections */
     96	{ "AIF1 Playback", NULL, "ssp5 Tx"},
     97	{ "ssp5 Tx", NULL, "codec0_out"},
     98	{ "ssp5 Tx", NULL, "codec1_out"},
     99
    100	{ "codec0_in", NULL, "ssp5 Rx" },
    101	{ "ssp5 Rx", NULL, "AIF1 Capture" },
    102
    103	{ "dmic01_hifi", NULL, "DMIC01 Rx" },
    104	{ "DMIC01 Rx", NULL, "Capture" },
    105
    106	{ "hifi3", NULL, "iDisp3 Tx"},
    107	{ "iDisp3 Tx", NULL, "iDisp3_out"},
    108	{ "hifi2", NULL, "iDisp2 Tx"},
    109	{ "iDisp2 Tx", NULL, "iDisp2_out"},
    110	{ "hifi1", NULL, "iDisp1 Tx"},
    111	{ "iDisp1 Tx", NULL, "iDisp1_out"},
    112};
    113
    114static const struct snd_soc_dapm_route geminilake_rt298_map[] = {
    115	/* speaker */
    116	{"Speaker", NULL, "SPOR"},
    117	{"Speaker", NULL, "SPOL"},
    118
    119	/* HP jack connectors - unknown if we have jack detect */
    120	{"Headphone Jack", NULL, "HPO Pin"},
    121
    122	/* other jacks */
    123	{"MIC1", NULL, "Mic Jack"},
    124
    125	/* digital mics */
    126	{"DMIC1 Pin", NULL, "DMIC2"},
    127	{"DMic", NULL, "SoC DMIC"},
    128
    129	{"HDMI1", NULL, "hif5-0 Output"},
    130	{"HDMI2", NULL, "hif6-0 Output"},
    131	{"HDMI2", NULL, "hif7-0 Output"},
    132
    133	/* CODEC BE connections */
    134	{ "AIF1 Playback", NULL, "ssp2 Tx"},
    135	{ "ssp2 Tx", NULL, "codec0_out"},
    136	{ "ssp2 Tx", NULL, "codec1_out"},
    137
    138	{ "codec0_in", NULL, "ssp2 Rx" },
    139	{ "ssp2 Rx", NULL, "AIF1 Capture" },
    140
    141	{ "dmic01_hifi", NULL, "DMIC01 Rx" },
    142	{ "DMIC01 Rx", NULL, "Capture" },
    143
    144	{ "dmic_voice", NULL, "DMIC16k Rx" },
    145	{ "DMIC16k Rx", NULL, "Capture" },
    146
    147	{ "hifi3", NULL, "iDisp3 Tx"},
    148	{ "iDisp3 Tx", NULL, "iDisp3_out"},
    149	{ "hifi2", NULL, "iDisp2 Tx"},
    150	{ "iDisp2 Tx", NULL, "iDisp2_out"},
    151	{ "hifi1", NULL, "iDisp1 Tx"},
    152	{ "iDisp1 Tx", NULL, "iDisp1_out"},
    153};
    154
    155static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd)
    156{
    157	struct snd_soc_dapm_context *dapm;
    158	struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component;
    159
    160	dapm = snd_soc_component_get_dapm(component);
    161	snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
    162
    163	return 0;
    164}
    165
    166static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd)
    167{
    168	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
    169	int ret = 0;
    170
    171	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset",
    172		SND_JACK_HEADSET | SND_JACK_BTN_0,
    173		&broxton_headset,
    174		broxton_headset_pins, ARRAY_SIZE(broxton_headset_pins));
    175
    176	if (ret)
    177		return ret;
    178
    179	rt298_mic_detect(component, &broxton_headset);
    180
    181	snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
    182
    183	return 0;
    184}
    185
    186static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd)
    187{
    188	struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card);
    189	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
    190	struct bxt_hdmi_pcm *pcm;
    191
    192	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
    193	if (!pcm)
    194		return -ENOMEM;
    195
    196	pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id;
    197	pcm->codec_dai = dai;
    198
    199	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
    200
    201	return 0;
    202}
    203
    204static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd,
    205			struct snd_pcm_hw_params *params)
    206{
    207	struct snd_interval *rate = hw_param_interval(params,
    208					SNDRV_PCM_HW_PARAM_RATE);
    209	struct snd_interval *chan = hw_param_interval(params,
    210					SNDRV_PCM_HW_PARAM_CHANNELS);
    211	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
    212
    213	/* The ADSP will covert the FE rate to 48k, stereo */
    214	rate->min = rate->max = 48000;
    215	chan->min = chan->max = 2;
    216
    217	/* set SSP5 to 24 bit */
    218	snd_mask_none(fmt);
    219	snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
    220
    221	return 0;
    222}
    223
    224static int broxton_rt298_hw_params(struct snd_pcm_substream *substream,
    225	struct snd_pcm_hw_params *params)
    226{
    227	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    228	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
    229	int ret;
    230
    231	ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL,
    232					19200000, SND_SOC_CLOCK_IN);
    233	if (ret < 0) {
    234		dev_err(rtd->dev, "can't set codec sysclk configuration\n");
    235		return ret;
    236	}
    237
    238	return ret;
    239}
    240
    241static const struct snd_soc_ops broxton_rt298_ops = {
    242	.hw_params = broxton_rt298_hw_params,
    243};
    244
    245static const unsigned int rates[] = {
    246	48000,
    247};
    248
    249static const struct snd_pcm_hw_constraint_list constraints_rates = {
    250	.count = ARRAY_SIZE(rates),
    251	.list  = rates,
    252	.mask = 0,
    253};
    254
    255static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
    256				struct snd_pcm_hw_params *params)
    257{
    258	struct snd_interval *chan = hw_param_interval(params,
    259						SNDRV_PCM_HW_PARAM_CHANNELS);
    260	chan->min = chan->max = 4;
    261
    262	return 0;
    263}
    264
    265static const unsigned int channels_dmic[] = {
    266	1, 2, 3, 4,
    267};
    268
    269static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
    270	.count = ARRAY_SIZE(channels_dmic),
    271	.list = channels_dmic,
    272	.mask = 0,
    273};
    274
    275static int broxton_dmic_startup(struct snd_pcm_substream *substream)
    276{
    277	struct snd_pcm_runtime *runtime = substream->runtime;
    278
    279	runtime->hw.channels_max = 4;
    280	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
    281					&constraints_dmic_channels);
    282
    283	return snd_pcm_hw_constraint_list(substream->runtime, 0,
    284				SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
    285}
    286
    287static const struct snd_soc_ops broxton_dmic_ops = {
    288	.startup = broxton_dmic_startup,
    289};
    290
    291static const unsigned int channels[] = {
    292	2,
    293};
    294
    295static const struct snd_pcm_hw_constraint_list constraints_channels = {
    296	.count = ARRAY_SIZE(channels),
    297	.list = channels,
    298	.mask = 0,
    299};
    300
    301static int bxt_fe_startup(struct snd_pcm_substream *substream)
    302{
    303	struct snd_pcm_runtime *runtime = substream->runtime;
    304
    305	/*
    306	 * on this platform for PCM device we support:
    307	 *      48Khz
    308	 *      stereo
    309	 *	16-bit audio
    310	 */
    311
    312	runtime->hw.channels_max = 2;
    313	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
    314				&constraints_channels);
    315
    316	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
    317	snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
    318	snd_pcm_hw_constraint_list(runtime, 0,
    319				SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
    320
    321	return 0;
    322}
    323
    324static const struct snd_soc_ops broxton_rt286_fe_ops = {
    325	.startup = bxt_fe_startup,
    326};
    327
    328SND_SOC_DAILINK_DEF(dummy,
    329	DAILINK_COMP_ARRAY(COMP_DUMMY()));
    330
    331SND_SOC_DAILINK_DEF(system,
    332	DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
    333
    334SND_SOC_DAILINK_DEF(reference,
    335	DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin")));
    336
    337SND_SOC_DAILINK_DEF(dmic,
    338	DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
    339
    340SND_SOC_DAILINK_DEF(hdmi1,
    341	DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
    342
    343SND_SOC_DAILINK_DEF(hdmi2,
    344	DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
    345
    346SND_SOC_DAILINK_DEF(hdmi3,
    347	DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin")));
    348
    349SND_SOC_DAILINK_DEF(ssp5_pin,
    350	DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin")));
    351SND_SOC_DAILINK_DEF(ssp5_codec,
    352	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00",
    353				      "rt298-aif1")));
    354
    355SND_SOC_DAILINK_DEF(dmic_pin,
    356	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
    357
    358SND_SOC_DAILINK_DEF(dmic_codec,
    359	DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec",
    360				      "dmic-hifi")));
    361
    362SND_SOC_DAILINK_DEF(dmic16k,
    363	DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
    364
    365SND_SOC_DAILINK_DEF(idisp1_pin,
    366	DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
    367SND_SOC_DAILINK_DEF(idisp1_codec,
    368	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
    369				      "intel-hdmi-hifi1")));
    370
    371SND_SOC_DAILINK_DEF(idisp2_pin,
    372	DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
    373SND_SOC_DAILINK_DEF(idisp2_codec,
    374	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
    375				      "intel-hdmi-hifi2")));
    376
    377SND_SOC_DAILINK_DEF(idisp3_pin,
    378	DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
    379SND_SOC_DAILINK_DEF(idisp3_codec,
    380	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2",
    381				      "intel-hdmi-hifi3")));
    382
    383SND_SOC_DAILINK_DEF(platform,
    384	DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0")));
    385
    386/* broxton digital audio interface glue - connects codec <--> CPU */
    387static struct snd_soc_dai_link broxton_rt298_dais[] = {
    388	/* Front End DAI links */
    389	[BXT_DPCM_AUDIO_PB] =
    390	{
    391		.name = "Bxt Audio Port",
    392		.stream_name = "Audio",
    393		.nonatomic = 1,
    394		.dynamic = 1,
    395		.init = broxton_rt298_fe_init,
    396		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
    397		.dpcm_playback = 1,
    398		.ops = &broxton_rt286_fe_ops,
    399		SND_SOC_DAILINK_REG(system, dummy, platform),
    400	},
    401	[BXT_DPCM_AUDIO_CP] =
    402	{
    403		.name = "Bxt Audio Capture Port",
    404		.stream_name = "Audio Record",
    405		.nonatomic = 1,
    406		.dynamic = 1,
    407		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
    408		.dpcm_capture = 1,
    409		.ops = &broxton_rt286_fe_ops,
    410		SND_SOC_DAILINK_REG(system, dummy, platform),
    411	},
    412	[BXT_DPCM_AUDIO_REF_CP] =
    413	{
    414		.name = "Bxt Audio Reference cap",
    415		.stream_name = "refcap",
    416		.init = NULL,
    417		.dpcm_capture = 1,
    418		.nonatomic = 1,
    419		.dynamic = 1,
    420		SND_SOC_DAILINK_REG(reference, dummy, platform),
    421	},
    422	[BXT_DPCM_AUDIO_DMIC_CP] =
    423	{
    424		.name = "Bxt Audio DMIC cap",
    425		.stream_name = "dmiccap",
    426		.init = NULL,
    427		.dpcm_capture = 1,
    428		.nonatomic = 1,
    429		.dynamic = 1,
    430		.ops = &broxton_dmic_ops,
    431		SND_SOC_DAILINK_REG(dmic, dummy, platform),
    432	},
    433	[BXT_DPCM_AUDIO_HDMI1_PB] =
    434	{
    435		.name = "Bxt HDMI Port1",
    436		.stream_name = "Hdmi1",
    437		.dpcm_playback = 1,
    438		.init = NULL,
    439		.nonatomic = 1,
    440		.dynamic = 1,
    441		SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
    442	},
    443	[BXT_DPCM_AUDIO_HDMI2_PB] =
    444	{
    445		.name = "Bxt HDMI Port2",
    446		.stream_name = "Hdmi2",
    447		.dpcm_playback = 1,
    448		.init = NULL,
    449		.nonatomic = 1,
    450		.dynamic = 1,
    451		SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
    452	},
    453	[BXT_DPCM_AUDIO_HDMI3_PB] =
    454	{
    455		.name = "Bxt HDMI Port3",
    456		.stream_name = "Hdmi3",
    457		.dpcm_playback = 1,
    458		.init = NULL,
    459		.nonatomic = 1,
    460		.dynamic = 1,
    461		SND_SOC_DAILINK_REG(hdmi3, dummy, platform),
    462	},
    463	/* Back End DAI links */
    464	{
    465		/* SSP5 - Codec */
    466		.name = "SSP5-Codec",
    467		.id = 0,
    468		.no_pcm = 1,
    469		.init = broxton_rt298_codec_init,
    470		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF |
    471						SND_SOC_DAIFMT_CBC_CFC,
    472		.ignore_pmdown_time = 1,
    473		.be_hw_params_fixup = broxton_ssp5_fixup,
    474		.ops = &broxton_rt298_ops,
    475		.dpcm_playback = 1,
    476		.dpcm_capture = 1,
    477		SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform),
    478	},
    479	{
    480		.name = "dmic01",
    481		.id = 1,
    482		.be_hw_params_fixup = broxton_dmic_fixup,
    483		.ignore_suspend = 1,
    484		.dpcm_capture = 1,
    485		.no_pcm = 1,
    486		SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
    487	},
    488	{
    489		.name = "dmic16k",
    490		.id = 2,
    491		.be_hw_params_fixup = broxton_dmic_fixup,
    492		.ignore_suspend = 1,
    493		.dpcm_capture = 1,
    494		.no_pcm = 1,
    495		SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
    496	},
    497	{
    498		.name = "iDisp1",
    499		.id = 3,
    500		.init = broxton_hdmi_init,
    501		.dpcm_playback = 1,
    502		.no_pcm = 1,
    503		SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
    504	},
    505	{
    506		.name = "iDisp2",
    507		.id = 4,
    508		.init = broxton_hdmi_init,
    509		.dpcm_playback = 1,
    510		.no_pcm = 1,
    511		SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
    512	},
    513	{
    514		.name = "iDisp3",
    515		.id = 5,
    516		.init = broxton_hdmi_init,
    517		.dpcm_playback = 1,
    518		.no_pcm = 1,
    519		SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
    520	},
    521};
    522
    523#define NAME_SIZE	32
    524static int bxt_card_late_probe(struct snd_soc_card *card)
    525{
    526	struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card);
    527	struct bxt_hdmi_pcm *pcm;
    528	struct snd_soc_component *component = NULL;
    529	int err, i = 0;
    530	char jack_name[NAME_SIZE];
    531
    532	if (list_empty(&ctx->hdmi_pcm_list))
    533		return -EINVAL;
    534
    535	if (ctx->common_hdmi_codec_drv) {
    536		pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
    537				       head);
    538		component = pcm->codec_dai->component;
    539		return hda_dsp_hdmi_build_controls(card, component);
    540	}
    541
    542	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
    543		component = pcm->codec_dai->component;
    544		snprintf(jack_name, sizeof(jack_name),
    545			"HDMI/DP, pcm=%d Jack", pcm->device);
    546		err = snd_soc_card_jack_new(card, jack_name,
    547					SND_JACK_AVOUT, &broxton_hdmi[i]);
    548
    549		if (err)
    550			return err;
    551
    552		err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
    553						&broxton_hdmi[i]);
    554		if (err < 0)
    555			return err;
    556
    557		i++;
    558	}
    559
    560	return hdac_hdmi_jack_port_init(component, &card->dapm);
    561}
    562
    563
    564/* broxton audio machine driver for SPT + RT298S */
    565static struct snd_soc_card broxton_rt298 = {
    566	.name = "broxton-rt298",
    567	.owner = THIS_MODULE,
    568	.dai_link = broxton_rt298_dais,
    569	.num_links = ARRAY_SIZE(broxton_rt298_dais),
    570	.controls = broxton_controls,
    571	.num_controls = ARRAY_SIZE(broxton_controls),
    572	.dapm_widgets = broxton_widgets,
    573	.num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
    574	.dapm_routes = broxton_rt298_map,
    575	.num_dapm_routes = ARRAY_SIZE(broxton_rt298_map),
    576	.fully_routed = true,
    577	.late_probe = bxt_card_late_probe,
    578
    579};
    580
    581static struct snd_soc_card geminilake_rt298 = {
    582	.name = "geminilake-rt298",
    583	.owner = THIS_MODULE,
    584	.dai_link = broxton_rt298_dais,
    585	.num_links = ARRAY_SIZE(broxton_rt298_dais),
    586	.controls = broxton_controls,
    587	.num_controls = ARRAY_SIZE(broxton_controls),
    588	.dapm_widgets = broxton_widgets,
    589	.num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
    590	.dapm_routes = geminilake_rt298_map,
    591	.num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map),
    592	.fully_routed = true,
    593	.late_probe = bxt_card_late_probe,
    594};
    595
    596static int broxton_audio_probe(struct platform_device *pdev)
    597{
    598	struct bxt_rt286_private *ctx;
    599	struct snd_soc_card *card =
    600			(struct snd_soc_card *)pdev->id_entry->driver_data;
    601	struct snd_soc_acpi_mach *mach;
    602	const char *platform_name;
    603	int ret;
    604	int i;
    605
    606	for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) {
    607		if (!strncmp(card->dai_link[i].codecs->name, "i2c-INT343A:00",
    608			     I2C_NAME_SIZE)) {
    609			if (!strncmp(card->name, "broxton-rt298",
    610				     PLATFORM_NAME_SIZE)) {
    611				card->dai_link[i].name = "SSP5-Codec";
    612				card->dai_link[i].cpus->dai_name = "SSP5 Pin";
    613			} else if (!strncmp(card->name, "geminilake-rt298",
    614					    PLATFORM_NAME_SIZE)) {
    615				card->dai_link[i].name = "SSP2-Codec";
    616				card->dai_link[i].cpus->dai_name = "SSP2 Pin";
    617			}
    618		}
    619	}
    620
    621	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
    622	if (!ctx)
    623		return -ENOMEM;
    624
    625	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
    626
    627	card->dev = &pdev->dev;
    628	snd_soc_card_set_drvdata(card, ctx);
    629
    630	/* override platform name, if required */
    631	mach = pdev->dev.platform_data;
    632	platform_name = mach->mach_params.platform;
    633
    634	ret = snd_soc_fixup_dai_links_platform_name(card,
    635						    platform_name);
    636	if (ret)
    637		return ret;
    638
    639	ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
    640
    641	return devm_snd_soc_register_card(&pdev->dev, card);
    642}
    643
    644static const struct platform_device_id bxt_board_ids[] = {
    645	{ .name = "bxt_alc298s_i2s", .driver_data =
    646				(unsigned long)&broxton_rt298 },
    647	{ .name = "glk_alc298s_i2s", .driver_data =
    648				(unsigned long)&geminilake_rt298 },
    649	{}
    650};
    651MODULE_DEVICE_TABLE(platform, bxt_board_ids);
    652
    653static struct platform_driver broxton_audio = {
    654	.probe = broxton_audio_probe,
    655	.driver = {
    656		.name = "bxt_alc298s_i2s",
    657		.pm = &snd_soc_pm_ops,
    658	},
    659	.id_table = bxt_board_ids,
    660};
    661module_platform_driver(broxton_audio)
    662
    663/* Module information */
    664MODULE_AUTHOR("Ramesh Babu <Ramesh.Babu@intel.com>");
    665MODULE_AUTHOR("Senthilnathan Veppur <senthilnathanx.veppur@intel.com>");
    666MODULE_DESCRIPTION("Intel SST Audio for Broxton");
    667MODULE_LICENSE("GPL v2");
    668MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);