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

mt2701-cs42448.c (12449B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * mt2701-cs42448.c  --  MT2701 CS42448 ALSA SoC machine driver
      4 *
      5 * Copyright (c) 2016 MediaTek Inc.
      6 * Author: Ir Lian <ir.lian@mediatek.com>
      7 *	   Garlic Tseng <garlic.tseng@mediatek.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <sound/soc.h>
     12#include <linux/delay.h>
     13#include <linux/gpio.h>
     14#include <linux/pinctrl/consumer.h>
     15#include <linux/of_gpio.h>
     16
     17#include "mt2701-afe-common.h"
     18
     19struct mt2701_cs42448_private {
     20	int i2s1_in_mux;
     21	int i2s1_in_mux_gpio_sel_1;
     22	int i2s1_in_mux_gpio_sel_2;
     23};
     24
     25static const char * const i2sin_mux_switch_text[] = {
     26	"ADC_SDOUT2",
     27	"ADC_SDOUT3",
     28	"I2S_IN_1",
     29	"I2S_IN_2",
     30};
     31
     32static const struct soc_enum i2sin_mux_enum =
     33	SOC_ENUM_SINGLE_EXT(4, i2sin_mux_switch_text);
     34
     35static int mt2701_cs42448_i2sin1_mux_get(struct snd_kcontrol *kcontrol,
     36					 struct snd_ctl_elem_value *ucontrol)
     37{
     38	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
     39	struct mt2701_cs42448_private *priv = snd_soc_card_get_drvdata(card);
     40
     41	ucontrol->value.integer.value[0] = priv->i2s1_in_mux;
     42	return 0;
     43}
     44
     45static int mt2701_cs42448_i2sin1_mux_set(struct snd_kcontrol *kcontrol,
     46					 struct snd_ctl_elem_value *ucontrol)
     47{
     48	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
     49	struct mt2701_cs42448_private *priv = snd_soc_card_get_drvdata(card);
     50
     51	if (ucontrol->value.integer.value[0] == priv->i2s1_in_mux)
     52		return 0;
     53
     54	switch (ucontrol->value.integer.value[0]) {
     55	case 0:
     56		gpio_set_value(priv->i2s1_in_mux_gpio_sel_1, 0);
     57		gpio_set_value(priv->i2s1_in_mux_gpio_sel_2, 0);
     58		break;
     59	case 1:
     60		gpio_set_value(priv->i2s1_in_mux_gpio_sel_1, 1);
     61		gpio_set_value(priv->i2s1_in_mux_gpio_sel_2, 0);
     62		break;
     63	case 2:
     64		gpio_set_value(priv->i2s1_in_mux_gpio_sel_1, 0);
     65		gpio_set_value(priv->i2s1_in_mux_gpio_sel_2, 1);
     66		break;
     67	case 3:
     68		gpio_set_value(priv->i2s1_in_mux_gpio_sel_1, 1);
     69		gpio_set_value(priv->i2s1_in_mux_gpio_sel_2, 1);
     70		break;
     71	default:
     72		dev_warn(card->dev, "%s invalid setting\n", __func__);
     73	}
     74
     75	priv->i2s1_in_mux = ucontrol->value.integer.value[0];
     76	return 0;
     77}
     78
     79static const struct snd_soc_dapm_widget
     80			mt2701_cs42448_asoc_card_dapm_widgets[] = {
     81	SND_SOC_DAPM_LINE("Line Out Jack", NULL),
     82	SND_SOC_DAPM_MIC("AMIC", NULL),
     83	SND_SOC_DAPM_LINE("Tuner In", NULL),
     84	SND_SOC_DAPM_LINE("Satellite Tuner In", NULL),
     85	SND_SOC_DAPM_LINE("AUX In", NULL),
     86};
     87
     88static const struct snd_kcontrol_new mt2701_cs42448_controls[] = {
     89	SOC_DAPM_PIN_SWITCH("Line Out Jack"),
     90	SOC_DAPM_PIN_SWITCH("AMIC"),
     91	SOC_DAPM_PIN_SWITCH("Tuner In"),
     92	SOC_DAPM_PIN_SWITCH("Satellite Tuner In"),
     93	SOC_DAPM_PIN_SWITCH("AUX In"),
     94	SOC_ENUM_EXT("I2SIN1_MUX_Switch", i2sin_mux_enum,
     95		     mt2701_cs42448_i2sin1_mux_get,
     96		     mt2701_cs42448_i2sin1_mux_set),
     97};
     98
     99static const unsigned int mt2701_cs42448_sampling_rates[] = {48000};
    100
    101static const struct snd_pcm_hw_constraint_list mt2701_cs42448_constraints_rates = {
    102		.count = ARRAY_SIZE(mt2701_cs42448_sampling_rates),
    103		.list = mt2701_cs42448_sampling_rates,
    104		.mask = 0,
    105};
    106
    107static int mt2701_cs42448_fe_ops_startup(struct snd_pcm_substream *substream)
    108{
    109	int err;
    110
    111	err = snd_pcm_hw_constraint_list(substream->runtime, 0,
    112					 SNDRV_PCM_HW_PARAM_RATE,
    113					 &mt2701_cs42448_constraints_rates);
    114	if (err < 0) {
    115		dev_err(substream->pcm->card->dev,
    116			"%s snd_pcm_hw_constraint_list failed: 0x%x\n",
    117			__func__, err);
    118		return err;
    119	}
    120	return 0;
    121}
    122
    123static const struct snd_soc_ops mt2701_cs42448_48k_fe_ops = {
    124	.startup = mt2701_cs42448_fe_ops_startup,
    125};
    126
    127static int mt2701_cs42448_be_ops_hw_params(struct snd_pcm_substream *substream,
    128					   struct snd_pcm_hw_params *params)
    129{
    130	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    131	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
    132	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
    133	unsigned int mclk_rate;
    134	unsigned int rate = params_rate(params);
    135	unsigned int div_mclk_over_bck = rate > 192000 ? 2 : 4;
    136	unsigned int div_bck_over_lrck = 64;
    137
    138	mclk_rate = rate * div_bck_over_lrck * div_mclk_over_bck;
    139
    140	/* mt2701 mclk */
    141	snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, SND_SOC_CLOCK_OUT);
    142
    143	/* codec mclk */
    144	snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, SND_SOC_CLOCK_IN);
    145
    146	return 0;
    147}
    148
    149static const struct snd_soc_ops mt2701_cs42448_be_ops = {
    150	.hw_params = mt2701_cs42448_be_ops_hw_params
    151};
    152
    153enum {
    154	DAI_LINK_FE_MULTI_CH_OUT,
    155	DAI_LINK_FE_PCM0_IN,
    156	DAI_LINK_FE_PCM1_IN,
    157	DAI_LINK_FE_BT_OUT,
    158	DAI_LINK_FE_BT_IN,
    159	DAI_LINK_BE_I2S0,
    160	DAI_LINK_BE_I2S1,
    161	DAI_LINK_BE_I2S2,
    162	DAI_LINK_BE_I2S3,
    163	DAI_LINK_BE_MRG_BT,
    164};
    165
    166SND_SOC_DAILINK_DEFS(fe_multi_ch_out,
    167	DAILINK_COMP_ARRAY(COMP_CPU("PCM_multi")),
    168	DAILINK_COMP_ARRAY(COMP_DUMMY()),
    169	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    170
    171SND_SOC_DAILINK_DEFS(fe_pcm0_in,
    172	DAILINK_COMP_ARRAY(COMP_CPU("PCM0")),
    173	DAILINK_COMP_ARRAY(COMP_DUMMY()),
    174	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    175
    176SND_SOC_DAILINK_DEFS(fe_pcm1_in,
    177	DAILINK_COMP_ARRAY(COMP_CPU("PCM1")),
    178	DAILINK_COMP_ARRAY(COMP_DUMMY()),
    179	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    180
    181SND_SOC_DAILINK_DEFS(fe_bt_out,
    182	DAILINK_COMP_ARRAY(COMP_CPU("PCM_BT_DL")),
    183	DAILINK_COMP_ARRAY(COMP_DUMMY()),
    184	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    185
    186SND_SOC_DAILINK_DEFS(fe_bt_in,
    187	DAILINK_COMP_ARRAY(COMP_CPU("PCM_BT_UL")),
    188	DAILINK_COMP_ARRAY(COMP_DUMMY()),
    189	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    190
    191SND_SOC_DAILINK_DEFS(be_i2s0,
    192	DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
    193	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")),
    194	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    195
    196SND_SOC_DAILINK_DEFS(be_i2s1,
    197	DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
    198	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")),
    199	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    200
    201SND_SOC_DAILINK_DEFS(be_i2s2,
    202	DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
    203	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")),
    204	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    205
    206SND_SOC_DAILINK_DEFS(be_i2s3,
    207	DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
    208	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")),
    209	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    210
    211SND_SOC_DAILINK_DEFS(be_mrg_bt,
    212	DAILINK_COMP_ARRAY(COMP_CPU("MRG BT")),
    213	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "bt-sco-pcm-wb")),
    214	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    215
    216static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
    217	/* FE */
    218	[DAI_LINK_FE_MULTI_CH_OUT] = {
    219		.name = "mt2701-cs42448-multi-ch-out",
    220		.stream_name = "mt2701-cs42448-multi-ch-out",
    221		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
    222			    SND_SOC_DPCM_TRIGGER_POST},
    223		.ops = &mt2701_cs42448_48k_fe_ops,
    224		.dynamic = 1,
    225		.dpcm_playback = 1,
    226		SND_SOC_DAILINK_REG(fe_multi_ch_out),
    227	},
    228	[DAI_LINK_FE_PCM0_IN] = {
    229		.name = "mt2701-cs42448-pcm0",
    230		.stream_name = "mt2701-cs42448-pcm0-data-UL",
    231		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
    232			    SND_SOC_DPCM_TRIGGER_POST},
    233		.ops = &mt2701_cs42448_48k_fe_ops,
    234		.dynamic = 1,
    235		.dpcm_capture = 1,
    236		SND_SOC_DAILINK_REG(fe_pcm0_in),
    237	},
    238	[DAI_LINK_FE_PCM1_IN] = {
    239		.name = "mt2701-cs42448-pcm1-data-UL",
    240		.stream_name = "mt2701-cs42448-pcm1-data-UL",
    241		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
    242			    SND_SOC_DPCM_TRIGGER_POST},
    243		.ops = &mt2701_cs42448_48k_fe_ops,
    244		.dynamic = 1,
    245		.dpcm_capture = 1,
    246		SND_SOC_DAILINK_REG(fe_pcm1_in),
    247	},
    248	[DAI_LINK_FE_BT_OUT] = {
    249		.name = "mt2701-cs42448-pcm-BT-out",
    250		.stream_name = "mt2701-cs42448-pcm-BT",
    251		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
    252			    SND_SOC_DPCM_TRIGGER_POST},
    253		.dynamic = 1,
    254		.dpcm_playback = 1,
    255		SND_SOC_DAILINK_REG(fe_bt_out),
    256	},
    257	[DAI_LINK_FE_BT_IN] = {
    258		.name = "mt2701-cs42448-pcm-BT-in",
    259		.stream_name = "mt2701-cs42448-pcm-BT",
    260		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
    261			    SND_SOC_DPCM_TRIGGER_POST},
    262		.dynamic = 1,
    263		.dpcm_capture = 1,
    264		SND_SOC_DAILINK_REG(fe_bt_in),
    265	},
    266	/* BE */
    267	[DAI_LINK_BE_I2S0] = {
    268		.name = "mt2701-cs42448-I2S0",
    269		.no_pcm = 1,
    270		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
    271			 | SND_SOC_DAIFMT_GATED,
    272		.ops = &mt2701_cs42448_be_ops,
    273		.dpcm_playback = 1,
    274		.dpcm_capture = 1,
    275		SND_SOC_DAILINK_REG(be_i2s0),
    276	},
    277	[DAI_LINK_BE_I2S1] = {
    278		.name = "mt2701-cs42448-I2S1",
    279		.no_pcm = 1,
    280		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
    281			 | SND_SOC_DAIFMT_GATED,
    282		.ops = &mt2701_cs42448_be_ops,
    283		.dpcm_playback = 1,
    284		.dpcm_capture = 1,
    285		SND_SOC_DAILINK_REG(be_i2s1),
    286	},
    287	[DAI_LINK_BE_I2S2] = {
    288		.name = "mt2701-cs42448-I2S2",
    289		.no_pcm = 1,
    290		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
    291			 | SND_SOC_DAIFMT_GATED,
    292		.ops = &mt2701_cs42448_be_ops,
    293		.dpcm_playback = 1,
    294		.dpcm_capture = 1,
    295		SND_SOC_DAILINK_REG(be_i2s2),
    296	},
    297	[DAI_LINK_BE_I2S3] = {
    298		.name = "mt2701-cs42448-I2S3",
    299		.no_pcm = 1,
    300		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
    301			 | SND_SOC_DAIFMT_GATED,
    302		.ops = &mt2701_cs42448_be_ops,
    303		.dpcm_playback = 1,
    304		.dpcm_capture = 1,
    305		SND_SOC_DAILINK_REG(be_i2s3),
    306	},
    307	[DAI_LINK_BE_MRG_BT] = {
    308		.name = "mt2701-cs42448-MRG-BT",
    309		.no_pcm = 1,
    310		.dpcm_playback = 1,
    311		.dpcm_capture = 1,
    312		SND_SOC_DAILINK_REG(be_mrg_bt),
    313	},
    314};
    315
    316static struct snd_soc_card mt2701_cs42448_soc_card = {
    317	.name = "mt2701-cs42448",
    318	.owner = THIS_MODULE,
    319	.dai_link = mt2701_cs42448_dai_links,
    320	.num_links = ARRAY_SIZE(mt2701_cs42448_dai_links),
    321	.controls = mt2701_cs42448_controls,
    322	.num_controls = ARRAY_SIZE(mt2701_cs42448_controls),
    323	.dapm_widgets = mt2701_cs42448_asoc_card_dapm_widgets,
    324	.num_dapm_widgets = ARRAY_SIZE(mt2701_cs42448_asoc_card_dapm_widgets),
    325};
    326
    327static int mt2701_cs42448_machine_probe(struct platform_device *pdev)
    328{
    329	struct snd_soc_card *card = &mt2701_cs42448_soc_card;
    330	int ret;
    331	int i;
    332	struct device_node *platform_node, *codec_node, *codec_node_bt_mrg;
    333	struct mt2701_cs42448_private *priv =
    334		devm_kzalloc(&pdev->dev, sizeof(struct mt2701_cs42448_private),
    335			     GFP_KERNEL);
    336	struct device *dev = &pdev->dev;
    337	struct snd_soc_dai_link *dai_link;
    338
    339	if (!priv)
    340		return -ENOMEM;
    341
    342	platform_node = of_parse_phandle(pdev->dev.of_node,
    343					 "mediatek,platform", 0);
    344	if (!platform_node) {
    345		dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
    346		return -EINVAL;
    347	}
    348	for_each_card_prelinks(card, i, dai_link) {
    349		if (dai_link->platforms->name)
    350			continue;
    351		dai_link->platforms->of_node = platform_node;
    352	}
    353
    354	card->dev = dev;
    355
    356	codec_node = of_parse_phandle(pdev->dev.of_node,
    357				      "mediatek,audio-codec", 0);
    358	if (!codec_node) {
    359		dev_err(&pdev->dev,
    360			"Property 'audio-codec' missing or invalid\n");
    361		return -EINVAL;
    362	}
    363	for_each_card_prelinks(card, i, dai_link) {
    364		if (dai_link->codecs->name)
    365			continue;
    366		dai_link->codecs->of_node = codec_node;
    367	}
    368
    369	codec_node_bt_mrg = of_parse_phandle(pdev->dev.of_node,
    370					     "mediatek,audio-codec-bt-mrg", 0);
    371	if (!codec_node_bt_mrg) {
    372		dev_err(&pdev->dev,
    373			"Property 'audio-codec-bt-mrg' missing or invalid\n");
    374		return -EINVAL;
    375	}
    376	mt2701_cs42448_dai_links[DAI_LINK_BE_MRG_BT].codecs->of_node
    377							= codec_node_bt_mrg;
    378
    379	ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
    380	if (ret) {
    381		dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
    382		return ret;
    383	}
    384
    385	priv->i2s1_in_mux_gpio_sel_1 =
    386		of_get_named_gpio(dev->of_node, "i2s1-in-sel-gpio1", 0);
    387	if (gpio_is_valid(priv->i2s1_in_mux_gpio_sel_1)) {
    388		ret = devm_gpio_request(dev, priv->i2s1_in_mux_gpio_sel_1,
    389					"i2s1_in_mux_gpio_sel_1");
    390		if (ret)
    391			dev_warn(&pdev->dev, "%s devm_gpio_request fail %d\n",
    392				 __func__, ret);
    393		gpio_direction_output(priv->i2s1_in_mux_gpio_sel_1, 0);
    394	}
    395
    396	priv->i2s1_in_mux_gpio_sel_2 =
    397		of_get_named_gpio(dev->of_node, "i2s1-in-sel-gpio2", 0);
    398	if (gpio_is_valid(priv->i2s1_in_mux_gpio_sel_2)) {
    399		ret = devm_gpio_request(dev, priv->i2s1_in_mux_gpio_sel_2,
    400					"i2s1_in_mux_gpio_sel_2");
    401		if (ret)
    402			dev_warn(&pdev->dev, "%s devm_gpio_request fail2 %d\n",
    403				 __func__, ret);
    404		gpio_direction_output(priv->i2s1_in_mux_gpio_sel_2, 0);
    405	}
    406	snd_soc_card_set_drvdata(card, priv);
    407
    408	ret = devm_snd_soc_register_card(&pdev->dev, card);
    409
    410	if (ret)
    411		dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
    412			__func__, ret);
    413	return ret;
    414}
    415
    416#ifdef CONFIG_OF
    417static const struct of_device_id mt2701_cs42448_machine_dt_match[] = {
    418	{.compatible = "mediatek,mt2701-cs42448-machine",},
    419	{}
    420};
    421#endif
    422
    423static struct platform_driver mt2701_cs42448_machine = {
    424	.driver = {
    425		.name = "mt2701-cs42448",
    426		   #ifdef CONFIG_OF
    427		   .of_match_table = mt2701_cs42448_machine_dt_match,
    428		   #endif
    429	},
    430	.probe = mt2701_cs42448_machine_probe,
    431};
    432
    433module_platform_driver(mt2701_cs42448_machine);
    434
    435/* Module information */
    436MODULE_DESCRIPTION("MT2701 CS42448 ALSA SoC machine driver");
    437MODULE_AUTHOR("Ir Lian <ir.lian@mediatek.com>");
    438MODULE_LICENSE("GPL v2");
    439MODULE_ALIAS("mt2701 cs42448 soc card");