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_rt286.c (14114B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Intel Skylake I2S Machine Driver
      4 *
      5 * Copyright (C) 2014-2015, Intel Corporation. All rights reserved.
      6 *
      7 * Modified from:
      8 *   Intel Broadwell Wildcatpoint SST Audio
      9 *
     10 *   Copyright (C) 2013, 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/jack.h>
     19#include <sound/pcm_params.h>
     20#include "../../codecs/rt286.h"
     21#include "../../codecs/hdac_hdmi.h"
     22
     23static struct snd_soc_jack skylake_headset;
     24static struct snd_soc_jack skylake_hdmi[3];
     25
     26struct skl_hdmi_pcm {
     27	struct list_head head;
     28	struct snd_soc_dai *codec_dai;
     29	int device;
     30};
     31
     32struct skl_rt286_private {
     33	struct list_head hdmi_pcm_list;
     34};
     35
     36enum {
     37	SKL_DPCM_AUDIO_PB = 0,
     38	SKL_DPCM_AUDIO_DB_PB,
     39	SKL_DPCM_AUDIO_CP,
     40	SKL_DPCM_AUDIO_REF_CP,
     41	SKL_DPCM_AUDIO_DMIC_CP,
     42	SKL_DPCM_AUDIO_HDMI1_PB,
     43	SKL_DPCM_AUDIO_HDMI2_PB,
     44	SKL_DPCM_AUDIO_HDMI3_PB,
     45};
     46
     47/* Headset jack detection DAPM pins */
     48static struct snd_soc_jack_pin skylake_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 skylake_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 skylake_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 skylake_rt286_map[] = {
     77	/* speaker */
     78	{"Speaker", NULL, "SPOR"},
     79	{"Speaker", NULL, "SPOL"},
     80
     81	/* HP jack connectors - unknown if we have jack deteck */
     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	/* CODEC BE connections */
     92	{ "AIF1 Playback", NULL, "ssp0 Tx"},
     93	{ "ssp0 Tx", NULL, "codec0_out"},
     94	{ "ssp0 Tx", NULL, "codec1_out"},
     95
     96	{ "codec0_in", NULL, "ssp0 Rx" },
     97	{ "codec1_in", NULL, "ssp0 Rx" },
     98	{ "ssp0 Rx", NULL, "AIF1 Capture" },
     99
    100	{ "dmic01_hifi", NULL, "DMIC01 Rx" },
    101	{ "DMIC01 Rx", NULL, "DMIC AIF" },
    102
    103	{ "hifi3", NULL, "iDisp3 Tx"},
    104	{ "iDisp3 Tx", NULL, "iDisp3_out"},
    105	{ "hifi2", NULL, "iDisp2 Tx"},
    106	{ "iDisp2 Tx", NULL, "iDisp2_out"},
    107	{ "hifi1", NULL, "iDisp1 Tx"},
    108	{ "iDisp1 Tx", NULL, "iDisp1_out"},
    109
    110};
    111
    112static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd)
    113{
    114	struct snd_soc_dapm_context *dapm;
    115	struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component;
    116
    117	dapm = snd_soc_component_get_dapm(component);
    118	snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
    119
    120	return 0;
    121}
    122
    123static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
    124{
    125	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
    126	int ret;
    127
    128	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset",
    129		SND_JACK_HEADSET | SND_JACK_BTN_0,
    130		&skylake_headset,
    131		skylake_headset_pins, ARRAY_SIZE(skylake_headset_pins));
    132
    133	if (ret)
    134		return ret;
    135
    136	rt286_mic_detect(component, &skylake_headset);
    137
    138	snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
    139
    140	return 0;
    141}
    142
    143static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd)
    144{
    145	struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card);
    146	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
    147	struct skl_hdmi_pcm *pcm;
    148
    149	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
    150	if (!pcm)
    151		return -ENOMEM;
    152
    153	pcm->device = SKL_DPCM_AUDIO_HDMI1_PB + dai->id;
    154	pcm->codec_dai = dai;
    155
    156	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
    157
    158	return 0;
    159}
    160
    161static const unsigned int rates[] = {
    162	48000,
    163};
    164
    165static const struct snd_pcm_hw_constraint_list constraints_rates = {
    166	.count = ARRAY_SIZE(rates),
    167	.list  = rates,
    168	.mask = 0,
    169};
    170
    171static const unsigned int channels[] = {
    172	2,
    173};
    174
    175static const struct snd_pcm_hw_constraint_list constraints_channels = {
    176	.count = ARRAY_SIZE(channels),
    177	.list = channels,
    178	.mask = 0,
    179};
    180
    181static int skl_fe_startup(struct snd_pcm_substream *substream)
    182{
    183	struct snd_pcm_runtime *runtime = substream->runtime;
    184
    185	/*
    186	 * on this platform for PCM device we support,
    187	 *	48Khz
    188	 *	stereo
    189	 *	16 bit audio
    190	 */
    191
    192	runtime->hw.channels_max = 2;
    193	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
    194					   &constraints_channels);
    195
    196	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
    197	snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
    198
    199	snd_pcm_hw_constraint_list(runtime, 0,
    200				SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
    201
    202	return 0;
    203}
    204
    205static const struct snd_soc_ops skylake_rt286_fe_ops = {
    206	.startup = skl_fe_startup,
    207};
    208
    209static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
    210			struct snd_pcm_hw_params *params)
    211{
    212	struct snd_interval *rate = hw_param_interval(params,
    213			SNDRV_PCM_HW_PARAM_RATE);
    214	struct snd_interval *chan = hw_param_interval(params,
    215						SNDRV_PCM_HW_PARAM_CHANNELS);
    216	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
    217
    218	/* The output is 48KHz, stereo, 16bits */
    219	rate->min = rate->max = 48000;
    220	chan->min = chan->max = 2;
    221
    222	/* set SSP0 to 24 bit */
    223	snd_mask_none(fmt);
    224	snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
    225	return 0;
    226}
    227
    228static int skylake_rt286_hw_params(struct snd_pcm_substream *substream,
    229	struct snd_pcm_hw_params *params)
    230{
    231	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    232	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
    233	int ret;
    234
    235	ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000,
    236		SND_SOC_CLOCK_IN);
    237	if (ret < 0)
    238		dev_err(rtd->dev, "set codec sysclk failed: %d\n", ret);
    239
    240	return ret;
    241}
    242
    243static const struct snd_soc_ops skylake_rt286_ops = {
    244	.hw_params = skylake_rt286_hw_params,
    245};
    246
    247static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
    248				struct snd_pcm_hw_params *params)
    249{
    250	struct snd_interval *chan = hw_param_interval(params,
    251						SNDRV_PCM_HW_PARAM_CHANNELS);
    252	if (params_channels(params) == 2)
    253		chan->min = chan->max = 2;
    254	else
    255		chan->min = chan->max = 4;
    256
    257	return 0;
    258}
    259
    260static const unsigned int channels_dmic[] = {
    261	2, 4,
    262};
    263
    264static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
    265	.count = ARRAY_SIZE(channels_dmic),
    266	.list = channels_dmic,
    267	.mask = 0,
    268};
    269
    270static int skylake_dmic_startup(struct snd_pcm_substream *substream)
    271{
    272	struct snd_pcm_runtime *runtime = substream->runtime;
    273
    274	runtime->hw.channels_max = 4;
    275	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
    276					   &constraints_dmic_channels);
    277
    278	return snd_pcm_hw_constraint_list(substream->runtime, 0,
    279			SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
    280}
    281
    282static const struct snd_soc_ops skylake_dmic_ops = {
    283	.startup = skylake_dmic_startup,
    284};
    285
    286SND_SOC_DAILINK_DEF(dummy,
    287	DAILINK_COMP_ARRAY(COMP_DUMMY()));
    288
    289SND_SOC_DAILINK_DEF(system,
    290	DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
    291
    292SND_SOC_DAILINK_DEF(deepbuffer,
    293	DAILINK_COMP_ARRAY(COMP_CPU("Deepbuffer Pin")));
    294
    295SND_SOC_DAILINK_DEF(reference,
    296	DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin")));
    297
    298SND_SOC_DAILINK_DEF(dmic,
    299	DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
    300
    301SND_SOC_DAILINK_DEF(hdmi1,
    302	DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
    303
    304SND_SOC_DAILINK_DEF(hdmi2,
    305	DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
    306
    307SND_SOC_DAILINK_DEF(hdmi3,
    308	DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin")));
    309
    310SND_SOC_DAILINK_DEF(ssp0_pin,
    311	DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
    312SND_SOC_DAILINK_DEF(ssp0_codec,
    313	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00", "rt286-aif1")));
    314
    315SND_SOC_DAILINK_DEF(dmic01_pin,
    316	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
    317SND_SOC_DAILINK_DEF(dmic_codec,
    318	DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
    319
    320SND_SOC_DAILINK_DEF(idisp1_pin,
    321	DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
    322SND_SOC_DAILINK_DEF(idisp1_codec,
    323	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
    324
    325SND_SOC_DAILINK_DEF(idisp2_pin,
    326	DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
    327SND_SOC_DAILINK_DEF(idisp2_codec,
    328	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
    329
    330SND_SOC_DAILINK_DEF(idisp3_pin,
    331	DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
    332SND_SOC_DAILINK_DEF(idisp3_codec,
    333	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
    334
    335SND_SOC_DAILINK_DEF(platform,
    336	DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
    337
    338/* skylake digital audio interface glue - connects codec <--> CPU */
    339static struct snd_soc_dai_link skylake_rt286_dais[] = {
    340	/* Front End DAI links */
    341	[SKL_DPCM_AUDIO_PB] = {
    342		.name = "Skl Audio Port",
    343		.stream_name = "Audio",
    344		.nonatomic = 1,
    345		.dynamic = 1,
    346		.init = skylake_rt286_fe_init,
    347		.trigger = {
    348			SND_SOC_DPCM_TRIGGER_POST,
    349			SND_SOC_DPCM_TRIGGER_POST
    350		},
    351		.dpcm_playback = 1,
    352		.ops = &skylake_rt286_fe_ops,
    353		SND_SOC_DAILINK_REG(system, dummy, platform),
    354	},
    355	[SKL_DPCM_AUDIO_DB_PB] = {
    356		.name = "Skl Deepbuffer Port",
    357		.stream_name = "Deep Buffer Audio",
    358		.nonatomic = 1,
    359		.dynamic = 1,
    360		.trigger = {
    361			SND_SOC_DPCM_TRIGGER_POST,
    362			SND_SOC_DPCM_TRIGGER_POST
    363		},
    364		.dpcm_playback = 1,
    365		.ops = &skylake_rt286_fe_ops,
    366		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
    367	},
    368	[SKL_DPCM_AUDIO_CP] = {
    369		.name = "Skl Audio Capture Port",
    370		.stream_name = "Audio Record",
    371		.nonatomic = 1,
    372		.dynamic = 1,
    373		.trigger = {
    374			SND_SOC_DPCM_TRIGGER_POST,
    375			SND_SOC_DPCM_TRIGGER_POST
    376		},
    377		.dpcm_capture = 1,
    378		.ops = &skylake_rt286_fe_ops,
    379		SND_SOC_DAILINK_REG(system, dummy, platform),
    380	},
    381	[SKL_DPCM_AUDIO_REF_CP] = {
    382		.name = "Skl Audio Reference cap",
    383		.stream_name = "refcap",
    384		.init = NULL,
    385		.dpcm_capture = 1,
    386		.nonatomic = 1,
    387		.dynamic = 1,
    388		SND_SOC_DAILINK_REG(reference, dummy, platform),
    389	},
    390	[SKL_DPCM_AUDIO_DMIC_CP] = {
    391		.name = "Skl Audio DMIC cap",
    392		.stream_name = "dmiccap",
    393		.init = NULL,
    394		.dpcm_capture = 1,
    395		.nonatomic = 1,
    396		.dynamic = 1,
    397		.ops = &skylake_dmic_ops,
    398		SND_SOC_DAILINK_REG(dmic, dummy, platform),
    399	},
    400	[SKL_DPCM_AUDIO_HDMI1_PB] = {
    401		.name = "Skl HDMI Port1",
    402		.stream_name = "Hdmi1",
    403		.dpcm_playback = 1,
    404		.init = NULL,
    405		.nonatomic = 1,
    406		.dynamic = 1,
    407		SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
    408	},
    409	[SKL_DPCM_AUDIO_HDMI2_PB] = {
    410		.name = "Skl HDMI Port2",
    411		.stream_name = "Hdmi2",
    412		.dpcm_playback = 1,
    413		.init = NULL,
    414		.nonatomic = 1,
    415		.dynamic = 1,
    416		SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
    417	},
    418	[SKL_DPCM_AUDIO_HDMI3_PB] = {
    419		.name = "Skl HDMI Port3",
    420		.stream_name = "Hdmi3",
    421		.dpcm_playback = 1,
    422		.init = NULL,
    423		.nonatomic = 1,
    424		.dynamic = 1,
    425		SND_SOC_DAILINK_REG(hdmi3, dummy, platform),
    426	},
    427
    428	/* Back End DAI links */
    429	{
    430		/* SSP0 - Codec */
    431		.name = "SSP0-Codec",
    432		.id = 0,
    433		.no_pcm = 1,
    434		.init = skylake_rt286_codec_init,
    435		.dai_fmt = SND_SOC_DAIFMT_I2S |
    436			SND_SOC_DAIFMT_NB_NF |
    437			SND_SOC_DAIFMT_CBC_CFC,
    438		.ignore_pmdown_time = 1,
    439		.be_hw_params_fixup = skylake_ssp0_fixup,
    440		.ops = &skylake_rt286_ops,
    441		.dpcm_playback = 1,
    442		.dpcm_capture = 1,
    443		SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
    444	},
    445	{
    446		.name = "dmic01",
    447		.id = 1,
    448		.be_hw_params_fixup = skylake_dmic_fixup,
    449		.ignore_suspend = 1,
    450		.dpcm_capture = 1,
    451		.no_pcm = 1,
    452		SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform),
    453	},
    454	{
    455		.name = "iDisp1",
    456		.id = 2,
    457		.init = skylake_hdmi_init,
    458		.dpcm_playback = 1,
    459		.no_pcm = 1,
    460		SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
    461	},
    462	{
    463		.name = "iDisp2",
    464		.id = 3,
    465		.init = skylake_hdmi_init,
    466		.dpcm_playback = 1,
    467		.no_pcm = 1,
    468		SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
    469	},
    470	{
    471		.name = "iDisp3",
    472		.id = 4,
    473		.init = skylake_hdmi_init,
    474		.dpcm_playback = 1,
    475		.no_pcm = 1,
    476		SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
    477	},
    478};
    479
    480#define NAME_SIZE	32
    481static int skylake_card_late_probe(struct snd_soc_card *card)
    482{
    483	struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(card);
    484	struct skl_hdmi_pcm *pcm;
    485	struct snd_soc_component *component = NULL;
    486	int err, i = 0;
    487	char jack_name[NAME_SIZE];
    488
    489	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
    490		component = pcm->codec_dai->component;
    491		snprintf(jack_name, sizeof(jack_name),
    492			"HDMI/DP, pcm=%d Jack", pcm->device);
    493		err = snd_soc_card_jack_new(card, jack_name,
    494					SND_JACK_AVOUT, &skylake_hdmi[i]);
    495
    496		if (err)
    497			return err;
    498
    499		err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
    500						&skylake_hdmi[i]);
    501		if (err < 0)
    502			return err;
    503
    504		i++;
    505	}
    506
    507	if (!component)
    508		return -EINVAL;
    509
    510	return hdac_hdmi_jack_port_init(component, &card->dapm);
    511}
    512
    513/* skylake audio machine driver for SPT + RT286S */
    514static struct snd_soc_card skylake_rt286 = {
    515	.name = "skylake-rt286",
    516	.owner = THIS_MODULE,
    517	.dai_link = skylake_rt286_dais,
    518	.num_links = ARRAY_SIZE(skylake_rt286_dais),
    519	.controls = skylake_controls,
    520	.num_controls = ARRAY_SIZE(skylake_controls),
    521	.dapm_widgets = skylake_widgets,
    522	.num_dapm_widgets = ARRAY_SIZE(skylake_widgets),
    523	.dapm_routes = skylake_rt286_map,
    524	.num_dapm_routes = ARRAY_SIZE(skylake_rt286_map),
    525	.fully_routed = true,
    526	.late_probe = skylake_card_late_probe,
    527};
    528
    529static int skylake_audio_probe(struct platform_device *pdev)
    530{
    531	struct skl_rt286_private *ctx;
    532
    533	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
    534	if (!ctx)
    535		return -ENOMEM;
    536
    537	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
    538
    539	skylake_rt286.dev = &pdev->dev;
    540	snd_soc_card_set_drvdata(&skylake_rt286, ctx);
    541
    542	return devm_snd_soc_register_card(&pdev->dev, &skylake_rt286);
    543}
    544
    545static const struct platform_device_id skl_board_ids[] = {
    546	{ .name = "skl_alc286s_i2s" },
    547	{ .name = "kbl_alc286s_i2s" },
    548	{ }
    549};
    550MODULE_DEVICE_TABLE(platform, skl_board_ids);
    551
    552static struct platform_driver skylake_audio = {
    553	.probe = skylake_audio_probe,
    554	.driver = {
    555		.name = "skl_alc286s_i2s",
    556		.pm = &snd_soc_pm_ops,
    557	},
    558	.id_table = skl_board_ids,
    559
    560};
    561
    562module_platform_driver(skylake_audio)
    563
    564/* Module information */
    565MODULE_AUTHOR("Omair Mohammed Abdullah <omair.m.abdullah@intel.com>");
    566MODULE_DESCRIPTION("Intel SST Audio for Skylake");
    567MODULE_LICENSE("GPL v2");