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

skl_nau88l25_ssm4567.c (19204B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Intel Skylake I2S Machine Driver for NAU88L25+SSM4567
      4 *
      5 * Copyright (C) 2015, Intel Corporation. All rights reserved.
      6 *
      7 * Modified from:
      8 *   Intel Skylake I2S Machine Driver for NAU88L25 and SSM4567
      9 *
     10 *   Copyright (C) 2015, Intel Corporation. All rights reserved.
     11 */
     12
     13#include <linux/module.h>
     14#include <linux/platform_device.h>
     15#include <sound/core.h>
     16#include <sound/pcm.h>
     17#include <sound/soc.h>
     18#include <sound/soc-acpi.h>
     19#include <sound/jack.h>
     20#include <sound/pcm_params.h>
     21#include "../../codecs/nau8825.h"
     22#include "../../codecs/hdac_hdmi.h"
     23
     24#define SKL_NUVOTON_CODEC_DAI	"nau8825-hifi"
     25#define SKL_SSM_CODEC_DAI	"ssm4567-hifi"
     26#define DMIC_CH(p)     p->list[p->count-1]
     27
     28static struct snd_soc_jack skylake_headset;
     29static struct snd_soc_card skylake_audio_card;
     30static const struct snd_pcm_hw_constraint_list *dmic_constraints;
     31static struct snd_soc_jack skylake_hdmi[3];
     32
     33struct skl_hdmi_pcm {
     34	struct list_head head;
     35	struct snd_soc_dai *codec_dai;
     36	int device;
     37};
     38
     39struct skl_nau88125_private {
     40	struct list_head hdmi_pcm_list;
     41};
     42enum {
     43	SKL_DPCM_AUDIO_PB = 0,
     44	SKL_DPCM_AUDIO_CP,
     45	SKL_DPCM_AUDIO_REF_CP,
     46	SKL_DPCM_AUDIO_DMIC_CP,
     47	SKL_DPCM_AUDIO_HDMI1_PB,
     48	SKL_DPCM_AUDIO_HDMI2_PB,
     49	SKL_DPCM_AUDIO_HDMI3_PB,
     50};
     51
     52static const struct snd_kcontrol_new skylake_controls[] = {
     53	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
     54	SOC_DAPM_PIN_SWITCH("Headset Mic"),
     55	SOC_DAPM_PIN_SWITCH("Left Speaker"),
     56	SOC_DAPM_PIN_SWITCH("Right Speaker"),
     57};
     58
     59static int platform_clock_control(struct snd_soc_dapm_widget *w,
     60		struct snd_kcontrol *k, int  event)
     61{
     62	struct snd_soc_dapm_context *dapm = w->dapm;
     63	struct snd_soc_card *card = dapm->card;
     64	struct snd_soc_dai *codec_dai;
     65	int ret;
     66
     67	codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI);
     68	if (!codec_dai) {
     69		dev_err(card->dev, "Codec dai not found\n");
     70		return -EIO;
     71	}
     72
     73	if (SND_SOC_DAPM_EVENT_ON(event)) {
     74		ret = snd_soc_dai_set_sysclk(codec_dai,
     75				NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN);
     76		if (ret < 0) {
     77			dev_err(card->dev, "set sysclk err = %d\n", ret);
     78			return -EIO;
     79		}
     80	} else {
     81		ret = snd_soc_dai_set_sysclk(codec_dai,
     82				NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN);
     83		if (ret < 0) {
     84			dev_err(card->dev, "set sysclk err = %d\n", ret);
     85			return -EIO;
     86		}
     87	}
     88	return ret;
     89}
     90
     91static const struct snd_soc_dapm_widget skylake_widgets[] = {
     92	SND_SOC_DAPM_HP("Headphone Jack", NULL),
     93	SND_SOC_DAPM_MIC("Headset Mic", NULL),
     94	SND_SOC_DAPM_SPK("Left Speaker", NULL),
     95	SND_SOC_DAPM_SPK("Right Speaker", NULL),
     96	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
     97	SND_SOC_DAPM_SPK("DP1", NULL),
     98	SND_SOC_DAPM_SPK("DP2", NULL),
     99	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
    100			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
    101			SND_SOC_DAPM_POST_PMD),
    102};
    103
    104static const struct snd_soc_dapm_route skylake_map[] = {
    105	/* HP jack connectors - unknown if we have jack detection */
    106	{"Headphone Jack", NULL, "HPOL"},
    107	{"Headphone Jack", NULL, "HPOR"},
    108
    109	/* speaker */
    110	{"Left Speaker", NULL, "Left OUT"},
    111	{"Right Speaker", NULL, "Right OUT"},
    112
    113	/* other jacks */
    114	{"MIC", NULL, "Headset Mic"},
    115	{"DMic", NULL, "SoC DMIC"},
    116
    117	/* CODEC BE connections */
    118	{ "Left Playback", NULL, "ssp0 Tx"},
    119	{ "Right Playback", NULL, "ssp0 Tx"},
    120	{ "ssp0 Tx", NULL, "codec0_out"},
    121
    122	/* IV feedback path */
    123	{ "codec0_lp_in", NULL, "ssp0 Rx"},
    124	{ "ssp0 Rx", NULL, "Left Capture Sense" },
    125	{ "ssp0 Rx", NULL, "Right Capture Sense" },
    126
    127	{ "Playback", NULL, "ssp1 Tx"},
    128	{ "ssp1 Tx", NULL, "codec1_out"},
    129
    130	{ "codec0_in", NULL, "ssp1 Rx" },
    131	{ "ssp1 Rx", NULL, "Capture" },
    132
    133	/* DMIC */
    134	{ "dmic01_hifi", NULL, "DMIC01 Rx" },
    135	{ "DMIC01 Rx", NULL, "DMIC AIF" },
    136
    137	{ "hifi3", NULL, "iDisp3 Tx"},
    138	{ "iDisp3 Tx", NULL, "iDisp3_out"},
    139	{ "hifi2", NULL, "iDisp2 Tx"},
    140	{ "iDisp2 Tx", NULL, "iDisp2_out"},
    141	{ "hifi1", NULL, "iDisp1 Tx"},
    142	{ "iDisp1 Tx", NULL, "iDisp1_out"},
    143
    144	{ "Headphone Jack", NULL, "Platform Clock" },
    145	{ "Headset Mic", NULL, "Platform Clock" },
    146};
    147
    148static struct snd_soc_codec_conf ssm4567_codec_conf[] = {
    149	{
    150		.dlc = COMP_CODEC_CONF("i2c-INT343B:00"),
    151		.name_prefix = "Left",
    152	},
    153	{
    154		.dlc = COMP_CODEC_CONF("i2c-INT343B:01"),
    155		.name_prefix = "Right",
    156	},
    157};
    158
    159static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd)
    160{
    161	int ret;
    162
    163	/* Slot 1 for left */
    164	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0x01, 0x01, 2, 48);
    165	if (ret < 0)
    166		return ret;
    167
    168	/* Slot 2 for right */
    169	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 1), 0x02, 0x02, 2, 48);
    170	if (ret < 0)
    171		return ret;
    172
    173	return ret;
    174}
    175
    176static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
    177{
    178	int ret;
    179	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
    180
    181	/*
    182	 * 4 buttons here map to the google Reference headset
    183	 * The use of these buttons can be decided by the user space.
    184	 */
    185	ret = snd_soc_card_jack_new(&skylake_audio_card, "Headset Jack",
    186		SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
    187		SND_JACK_BTN_2 | SND_JACK_BTN_3, &skylake_headset);
    188	if (ret) {
    189		dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
    190		return ret;
    191	}
    192
    193	nau8825_enable_jack_detect(component, &skylake_headset);
    194
    195	snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
    196
    197	return ret;
    198}
    199
    200static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
    201{
    202	struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card);
    203	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
    204	struct skl_hdmi_pcm *pcm;
    205
    206	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
    207	if (!pcm)
    208		return -ENOMEM;
    209
    210	pcm->device = SKL_DPCM_AUDIO_HDMI1_PB;
    211	pcm->codec_dai = dai;
    212
    213	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
    214
    215	return 0;
    216}
    217
    218static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
    219{
    220	struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card);
    221	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
    222	struct skl_hdmi_pcm *pcm;
    223
    224	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
    225	if (!pcm)
    226		return -ENOMEM;
    227
    228	pcm->device = SKL_DPCM_AUDIO_HDMI2_PB;
    229	pcm->codec_dai = dai;
    230
    231	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
    232
    233	return 0;
    234}
    235
    236
    237static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
    238{
    239	struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card);
    240	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
    241	struct skl_hdmi_pcm *pcm;
    242
    243	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
    244	if (!pcm)
    245		return -ENOMEM;
    246
    247	pcm->device = SKL_DPCM_AUDIO_HDMI3_PB;
    248	pcm->codec_dai = dai;
    249
    250	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
    251
    252	return 0;
    253}
    254
    255static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
    256{
    257	struct snd_soc_dapm_context *dapm;
    258	struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component;
    259
    260	dapm = snd_soc_component_get_dapm(component);
    261	snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
    262
    263	return 0;
    264}
    265
    266static const unsigned int rates[] = {
    267	48000,
    268};
    269
    270static const struct snd_pcm_hw_constraint_list constraints_rates = {
    271	.count = ARRAY_SIZE(rates),
    272	.list  = rates,
    273	.mask = 0,
    274};
    275
    276static const unsigned int channels[] = {
    277	2,
    278};
    279
    280static const struct snd_pcm_hw_constraint_list constraints_channels = {
    281	.count = ARRAY_SIZE(channels),
    282	.list = channels,
    283	.mask = 0,
    284};
    285
    286static int skl_fe_startup(struct snd_pcm_substream *substream)
    287{
    288	struct snd_pcm_runtime *runtime = substream->runtime;
    289
    290	/*
    291	 * on this platform for PCM device we support,
    292	 *	48Khz
    293	 *	stereo
    294	 *	16 bit audio
    295	 */
    296
    297	runtime->hw.channels_max = 2;
    298	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
    299					   &constraints_channels);
    300
    301	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
    302	snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
    303
    304	snd_pcm_hw_constraint_list(runtime, 0,
    305				SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
    306
    307	return 0;
    308}
    309
    310static const struct snd_soc_ops skylake_nau8825_fe_ops = {
    311	.startup = skl_fe_startup,
    312};
    313
    314static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
    315			struct snd_pcm_hw_params *params)
    316{
    317	struct snd_interval *rate = hw_param_interval(params,
    318			SNDRV_PCM_HW_PARAM_RATE);
    319	struct snd_interval *chan = hw_param_interval(params,
    320						SNDRV_PCM_HW_PARAM_CHANNELS);
    321	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
    322
    323	/* The ADSP will covert the FE rate to 48k, stereo */
    324	rate->min = rate->max = 48000;
    325	chan->min = chan->max = 2;
    326
    327	/* set SSP0 to 24 bit */
    328	snd_mask_none(fmt);
    329	snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
    330	return 0;
    331}
    332
    333static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
    334			struct snd_pcm_hw_params *params)
    335{
    336	struct snd_interval *chan = hw_param_interval(params,
    337						SNDRV_PCM_HW_PARAM_CHANNELS);
    338	if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2)
    339		chan->min = chan->max = 2;
    340	else
    341		chan->min = chan->max = 4;
    342
    343	return 0;
    344}
    345
    346static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream,
    347	struct snd_pcm_hw_params *params)
    348{
    349	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    350	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
    351	int ret;
    352
    353	ret = snd_soc_dai_set_sysclk(codec_dai,
    354			NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN);
    355
    356	if (ret < 0)
    357		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
    358
    359	return ret;
    360}
    361
    362static const struct snd_soc_ops skylake_nau8825_ops = {
    363	.hw_params = skylake_nau8825_hw_params,
    364};
    365
    366static const unsigned int channels_dmic[] = {
    367	2, 4,
    368};
    369
    370static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
    371	.count = ARRAY_SIZE(channels_dmic),
    372	.list = channels_dmic,
    373	.mask = 0,
    374};
    375
    376static const unsigned int dmic_2ch[] = {
    377	2,
    378};
    379
    380static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = {
    381	.count = ARRAY_SIZE(dmic_2ch),
    382	.list = dmic_2ch,
    383	.mask = 0,
    384};
    385
    386static int skylake_dmic_startup(struct snd_pcm_substream *substream)
    387{
    388	struct snd_pcm_runtime *runtime = substream->runtime;
    389
    390	runtime->hw.channels_max = DMIC_CH(dmic_constraints);
    391	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
    392			dmic_constraints);
    393
    394	return snd_pcm_hw_constraint_list(substream->runtime, 0,
    395			SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
    396}
    397
    398static const struct snd_soc_ops skylake_dmic_ops = {
    399	.startup = skylake_dmic_startup,
    400};
    401
    402static const unsigned int rates_16000[] = {
    403	16000,
    404};
    405
    406static const struct snd_pcm_hw_constraint_list constraints_16000 = {
    407	.count = ARRAY_SIZE(rates_16000),
    408	.list  = rates_16000,
    409};
    410
    411static const unsigned int ch_mono[] = {
    412	1,
    413};
    414
    415static const struct snd_pcm_hw_constraint_list constraints_refcap = {
    416	.count = ARRAY_SIZE(ch_mono),
    417	.list  = ch_mono,
    418};
    419
    420static int skylake_refcap_startup(struct snd_pcm_substream *substream)
    421{
    422	substream->runtime->hw.channels_max = 1;
    423	snd_pcm_hw_constraint_list(substream->runtime, 0,
    424					SNDRV_PCM_HW_PARAM_CHANNELS,
    425					&constraints_refcap);
    426
    427	return snd_pcm_hw_constraint_list(substream->runtime, 0,
    428			SNDRV_PCM_HW_PARAM_RATE,
    429			&constraints_16000);
    430}
    431
    432static const struct snd_soc_ops skylake_refcap_ops = {
    433	.startup = skylake_refcap_startup,
    434};
    435
    436SND_SOC_DAILINK_DEF(dummy,
    437	DAILINK_COMP_ARRAY(COMP_DUMMY()));
    438
    439SND_SOC_DAILINK_DEF(system,
    440	DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
    441
    442SND_SOC_DAILINK_DEF(reference,
    443	DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin")));
    444
    445SND_SOC_DAILINK_DEF(dmic,
    446	DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
    447
    448SND_SOC_DAILINK_DEF(hdmi1,
    449	DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
    450
    451SND_SOC_DAILINK_DEF(hdmi2,
    452	DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
    453
    454SND_SOC_DAILINK_DEF(hdmi3,
    455	DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin")));
    456
    457SND_SOC_DAILINK_DEF(ssp0_pin,
    458	DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
    459SND_SOC_DAILINK_DEF(ssp0_codec,
    460	DAILINK_COMP_ARRAY(
    461	/* Left */	COMP_CODEC("i2c-INT343B:00", SKL_SSM_CODEC_DAI),
    462	/* Right */	COMP_CODEC("i2c-INT343B:01", SKL_SSM_CODEC_DAI)));
    463
    464SND_SOC_DAILINK_DEF(ssp1_pin,
    465	DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
    466SND_SOC_DAILINK_DEF(ssp1_codec,
    467	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", SKL_NUVOTON_CODEC_DAI)));
    468
    469SND_SOC_DAILINK_DEF(dmic01_pin,
    470	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
    471SND_SOC_DAILINK_DEF(dmic_codec,
    472	DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
    473
    474SND_SOC_DAILINK_DEF(idisp1_pin,
    475	DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
    476SND_SOC_DAILINK_DEF(idisp1_codec,
    477	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
    478
    479SND_SOC_DAILINK_DEF(idisp2_pin,
    480	DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
    481SND_SOC_DAILINK_DEF(idisp2_codec,
    482	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
    483
    484SND_SOC_DAILINK_DEF(idisp3_pin,
    485	DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
    486SND_SOC_DAILINK_DEF(idisp3_codec,
    487	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
    488
    489SND_SOC_DAILINK_DEF(platform,
    490	DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
    491
    492/* skylake digital audio interface glue - connects codec <--> CPU */
    493static struct snd_soc_dai_link skylake_dais[] = {
    494	/* Front End DAI links */
    495	[SKL_DPCM_AUDIO_PB] = {
    496		.name = "Skl Audio Port",
    497		.stream_name = "Audio",
    498		.dynamic = 1,
    499		.nonatomic = 1,
    500		.init = skylake_nau8825_fe_init,
    501		.trigger = {
    502			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
    503		.dpcm_playback = 1,
    504		.ops = &skylake_nau8825_fe_ops,
    505		SND_SOC_DAILINK_REG(system, dummy, platform),
    506	},
    507	[SKL_DPCM_AUDIO_CP] = {
    508		.name = "Skl Audio Capture Port",
    509		.stream_name = "Audio Record",
    510		.dynamic = 1,
    511		.nonatomic = 1,
    512		.trigger = {
    513			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
    514		.dpcm_capture = 1,
    515		.ops = &skylake_nau8825_fe_ops,
    516		SND_SOC_DAILINK_REG(system, dummy, platform),
    517	},
    518	[SKL_DPCM_AUDIO_REF_CP] = {
    519		.name = "Skl Audio Reference cap",
    520		.stream_name = "Wake on Voice",
    521		.init = NULL,
    522		.dpcm_capture = 1,
    523		.nonatomic = 1,
    524		.dynamic = 1,
    525		.ops = &skylake_refcap_ops,
    526		SND_SOC_DAILINK_REG(reference, dummy, platform),
    527	},
    528	[SKL_DPCM_AUDIO_DMIC_CP] = {
    529		.name = "Skl Audio DMIC cap",
    530		.stream_name = "dmiccap",
    531		.init = NULL,
    532		.dpcm_capture = 1,
    533		.nonatomic = 1,
    534		.dynamic = 1,
    535		.ops = &skylake_dmic_ops,
    536		SND_SOC_DAILINK_REG(dmic, dummy, platform),
    537	},
    538	[SKL_DPCM_AUDIO_HDMI1_PB] = {
    539		.name = "Skl HDMI Port1",
    540		.stream_name = "Hdmi1",
    541		.dpcm_playback = 1,
    542		.init = NULL,
    543		.trigger = {
    544			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
    545		.nonatomic = 1,
    546		.dynamic = 1,
    547		SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
    548	},
    549	[SKL_DPCM_AUDIO_HDMI2_PB] = {
    550		.name = "Skl HDMI Port2",
    551		.stream_name = "Hdmi2",
    552		.dpcm_playback = 1,
    553		.init = NULL,
    554		.trigger = {
    555			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
    556		.nonatomic = 1,
    557		.dynamic = 1,
    558		SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
    559	},
    560	[SKL_DPCM_AUDIO_HDMI3_PB] = {
    561		.name = "Skl HDMI Port3",
    562		.stream_name = "Hdmi3",
    563		.trigger = {
    564			SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
    565		.dpcm_playback = 1,
    566		.init = NULL,
    567		.nonatomic = 1,
    568		.dynamic = 1,
    569		SND_SOC_DAILINK_REG(hdmi3, dummy, platform),
    570	},
    571
    572	/* Back End DAI links */
    573	{
    574		/* SSP0 - Codec */
    575		.name = "SSP0-Codec",
    576		.id = 0,
    577		.no_pcm = 1,
    578		.dai_fmt = SND_SOC_DAIFMT_DSP_A |
    579			SND_SOC_DAIFMT_IB_NF |
    580			SND_SOC_DAIFMT_CBC_CFC,
    581		.init = skylake_ssm4567_codec_init,
    582		.ignore_pmdown_time = 1,
    583		.be_hw_params_fixup = skylake_ssp_fixup,
    584		.dpcm_playback = 1,
    585		.dpcm_capture = 1,
    586		SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
    587	},
    588	{
    589		/* SSP1 - Codec */
    590		.name = "SSP1-Codec",
    591		.id = 1,
    592		.no_pcm = 1,
    593		.init = skylake_nau8825_codec_init,
    594		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
    595			SND_SOC_DAIFMT_CBC_CFC,
    596		.ignore_pmdown_time = 1,
    597		.be_hw_params_fixup = skylake_ssp_fixup,
    598		.ops = &skylake_nau8825_ops,
    599		.dpcm_playback = 1,
    600		.dpcm_capture = 1,
    601		SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform),
    602	},
    603	{
    604		.name = "dmic01",
    605		.id = 2,
    606		.ignore_suspend = 1,
    607		.be_hw_params_fixup = skylake_dmic_fixup,
    608		.dpcm_capture = 1,
    609		.no_pcm = 1,
    610		SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform),
    611	},
    612	{
    613		.name = "iDisp1",
    614		.id = 3,
    615		.dpcm_playback = 1,
    616		.init = skylake_hdmi1_init,
    617		.no_pcm = 1,
    618		SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
    619	},
    620	{
    621		.name = "iDisp2",
    622		.id = 4,
    623		.init = skylake_hdmi2_init,
    624		.dpcm_playback = 1,
    625		.no_pcm = 1,
    626		SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
    627	},
    628	{
    629		.name = "iDisp3",
    630		.id = 5,
    631		.init = skylake_hdmi3_init,
    632		.dpcm_playback = 1,
    633		.no_pcm = 1,
    634		SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
    635	},
    636};
    637
    638#define NAME_SIZE	32
    639static int skylake_card_late_probe(struct snd_soc_card *card)
    640{
    641	struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card);
    642	struct skl_hdmi_pcm *pcm;
    643	struct snd_soc_component *component = NULL;
    644	int err, i = 0;
    645	char jack_name[NAME_SIZE];
    646
    647	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
    648		component = pcm->codec_dai->component;
    649		snprintf(jack_name, sizeof(jack_name),
    650			"HDMI/DP, pcm=%d Jack", pcm->device);
    651		err = snd_soc_card_jack_new(card, jack_name,
    652					SND_JACK_AVOUT,
    653					&skylake_hdmi[i]);
    654
    655		if (err)
    656			return err;
    657
    658		err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
    659						&skylake_hdmi[i]);
    660		if (err < 0)
    661			return err;
    662
    663		i++;
    664	}
    665
    666	if (!component)
    667		return -EINVAL;
    668
    669	return hdac_hdmi_jack_port_init(component, &card->dapm);
    670}
    671
    672/* skylake audio machine driver for SPT + NAU88L25 */
    673static struct snd_soc_card skylake_audio_card = {
    674	.name = "sklnau8825adi",
    675	.owner = THIS_MODULE,
    676	.dai_link = skylake_dais,
    677	.num_links = ARRAY_SIZE(skylake_dais),
    678	.controls = skylake_controls,
    679	.num_controls = ARRAY_SIZE(skylake_controls),
    680	.dapm_widgets = skylake_widgets,
    681	.num_dapm_widgets = ARRAY_SIZE(skylake_widgets),
    682	.dapm_routes = skylake_map,
    683	.num_dapm_routes = ARRAY_SIZE(skylake_map),
    684	.codec_conf = ssm4567_codec_conf,
    685	.num_configs = ARRAY_SIZE(ssm4567_codec_conf),
    686	.fully_routed = true,
    687	.disable_route_checks = true,
    688	.late_probe = skylake_card_late_probe,
    689};
    690
    691static int skylake_audio_probe(struct platform_device *pdev)
    692{
    693	struct skl_nau88125_private *ctx;
    694	struct snd_soc_acpi_mach *mach;
    695
    696	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
    697	if (!ctx)
    698		return -ENOMEM;
    699
    700	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
    701
    702	skylake_audio_card.dev = &pdev->dev;
    703	snd_soc_card_set_drvdata(&skylake_audio_card, ctx);
    704
    705	mach = pdev->dev.platform_data;
    706	if (mach)
    707		dmic_constraints = mach->mach_params.dmic_num == 2 ?
    708			&constraints_dmic_2ch : &constraints_dmic_channels;
    709
    710	return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card);
    711}
    712
    713static const struct platform_device_id skl_board_ids[] = {
    714	{ .name = "skl_n88l25_s4567" },
    715	{ .name = "kbl_n88l25_s4567" },
    716	{ }
    717};
    718MODULE_DEVICE_TABLE(platform, skl_board_ids);
    719
    720static struct platform_driver skylake_audio = {
    721	.probe = skylake_audio_probe,
    722	.driver = {
    723		.name = "skl_n88l25_s4567",
    724		.pm = &snd_soc_pm_ops,
    725	},
    726	.id_table = skl_board_ids,
    727};
    728
    729module_platform_driver(skylake_audio)
    730
    731/* Module information */
    732MODULE_AUTHOR("Conrad Cooke  <conrad.cooke@intel.com>");
    733MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
    734MODULE_AUTHOR("Naveen M <naveen.m@intel.com>");
    735MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
    736MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
    737MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode");
    738MODULE_LICENSE("GPL v2");