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

sof_realtek_common.c (12457B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2//
      3// Copyright(c) 2020 Intel Corporation. All rights reserved.
      4
      5#include <linux/device.h>
      6#include <linux/kernel.h>
      7#include <sound/pcm.h>
      8#include <sound/pcm_params.h>
      9#include <sound/soc.h>
     10#include <sound/soc-acpi.h>
     11#include <sound/soc-dai.h>
     12#include <sound/soc-dapm.h>
     13#include <sound/sof.h>
     14#include <uapi/sound/asound.h>
     15#include "../../codecs/rt1011.h"
     16#include "../../codecs/rt1015.h"
     17#include "../../codecs/rt1308.h"
     18#include "sof_realtek_common.h"
     19
     20/*
     21 * Current only 2-amp configuration is supported for rt1011
     22 */
     23static const struct snd_soc_dapm_route speaker_map_lr[] = {
     24	/* speaker */
     25	{ "Left Spk", NULL, "Left SPO" },
     26	{ "Right Spk", NULL, "Right SPO" },
     27};
     28
     29/*
     30 * Make sure device's Unique ID follows this configuration:
     31 *
     32 * Two speakers:
     33 *         0: left, 1: right
     34 * Four speakers:
     35 *         0: Woofer left, 1: Woofer right
     36 *         2: Tweeter left, 3: Tweeter right
     37 */
     38static struct snd_soc_codec_conf rt1011_codec_confs[] = {
     39	{
     40		.dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
     41		.name_prefix = "Left",
     42	},
     43	{
     44		.dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME),
     45		.name_prefix = "Right",
     46	},
     47};
     48
     49static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
     50	{
     51		.name = RT1011_DEV0_NAME,
     52		.dai_name = RT1011_CODEC_DAI,
     53	},
     54	{
     55		.name = RT1011_DEV1_NAME,
     56		.dai_name = RT1011_CODEC_DAI,
     57	},
     58};
     59
     60static const struct {
     61	unsigned int tx;
     62	unsigned int rx;
     63} rt1011_tdm_mask[] = {
     64	{.tx = 0x4, .rx = 0x1},
     65	{.tx = 0x8, .rx = 0x2},
     66};
     67
     68static int rt1011_hw_params(struct snd_pcm_substream *substream,
     69			    struct snd_pcm_hw_params *params)
     70{
     71	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     72	struct snd_soc_dai *codec_dai;
     73	int srate, i, ret = 0;
     74
     75	srate = params_rate(params);
     76
     77	for_each_rtd_codec_dais(rtd, i, codec_dai) {
     78		/* 100 Fs to drive 24 bit data */
     79		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK,
     80					  100 * srate, 256 * srate);
     81		if (ret < 0) {
     82			dev_err(codec_dai->dev, "fail to set pll, ret %d\n",
     83				ret);
     84			return ret;
     85		}
     86
     87		ret = snd_soc_dai_set_sysclk(codec_dai, RT1011_FS_SYS_PRE_S_PLL1,
     88					     256 * srate, SND_SOC_CLOCK_IN);
     89		if (ret < 0) {
     90			dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n",
     91				ret);
     92			return ret;
     93		}
     94
     95		if (i >= ARRAY_SIZE(rt1011_tdm_mask)) {
     96			dev_err(codec_dai->dev, "invalid codec index %d\n",
     97				i);
     98			return -ENODEV;
     99		}
    100
    101		ret = snd_soc_dai_set_tdm_slot(codec_dai, rt1011_tdm_mask[i].tx,
    102					       rt1011_tdm_mask[i].rx, 4,
    103					       params_width(params));
    104		if (ret < 0) {
    105			dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
    106				ret);
    107			return ret;
    108		}
    109	}
    110
    111	return 0;
    112}
    113
    114static const struct snd_soc_ops rt1011_ops = {
    115	.hw_params = rt1011_hw_params,
    116};
    117
    118static int rt1011_init(struct snd_soc_pcm_runtime *rtd)
    119{
    120	struct snd_soc_card *card = rtd->card;
    121	int ret;
    122
    123	ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr,
    124				      ARRAY_SIZE(speaker_map_lr));
    125	if (ret)
    126		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
    127	return ret;
    128}
    129
    130void sof_rt1011_dai_link(struct snd_soc_dai_link *link)
    131{
    132	link->codecs = rt1011_dai_link_components;
    133	link->num_codecs = ARRAY_SIZE(rt1011_dai_link_components);
    134	link->init = rt1011_init;
    135	link->ops = &rt1011_ops;
    136}
    137EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    138
    139void sof_rt1011_codec_conf(struct snd_soc_card *card)
    140{
    141	card->codec_conf = rt1011_codec_confs;
    142	card->num_configs = ARRAY_SIZE(rt1011_codec_confs);
    143}
    144EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    145
    146/*
    147 * rt1015:  i2c mode driver for ALC1015 and ALC1015Q
    148 * rt1015p: auto-mode driver for ALC1015, ALC1015Q, and ALC1015Q-VB
    149 *
    150 * For stereo output, there are always two amplifiers on the board.
    151 * However, the ACPI implements only one device instance (UID=0) if they
    152 * are sharing the same enable pin. The code will detect the number of
    153 * device instance and use corresponding DAPM structures for
    154 * initialization.
    155 */
    156static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = {
    157	/* speaker */
    158	{ "Left Spk", NULL, "Speaker" },
    159	{ "Right Spk", NULL, "Speaker" },
    160};
    161
    162static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = {
    163	/* speaker */
    164	{ "Left Spk", NULL, "Left Speaker" },
    165	{ "Right Spk", NULL, "Right Speaker" },
    166};
    167
    168static struct snd_soc_codec_conf rt1015p_codec_confs[] = {
    169	{
    170		.dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME),
    171		.name_prefix = "Left",
    172	},
    173	{
    174		.dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME),
    175		.name_prefix = "Right",
    176	},
    177};
    178
    179static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = {
    180	{
    181		.name = RT1015P_DEV0_NAME,
    182		.dai_name = RT1015P_CODEC_DAI,
    183	},
    184	{
    185		.name = RT1015P_DEV1_NAME,
    186		.dai_name = RT1015P_CODEC_DAI,
    187	},
    188};
    189
    190static int rt1015p_get_num_codecs(void)
    191{
    192	static int dev_num;
    193
    194	if (dev_num)
    195		return dev_num;
    196
    197	if (!acpi_dev_present("RTL1015", "1", -1))
    198		dev_num = 1;
    199	else
    200		dev_num = 2;
    201
    202	return dev_num;
    203}
    204
    205static int rt1015p_hw_params(struct snd_pcm_substream *substream,
    206			     struct snd_pcm_hw_params *params)
    207{
    208	/* reserved for debugging purpose */
    209
    210	return 0;
    211}
    212
    213static const struct snd_soc_ops rt1015p_ops = {
    214	.hw_params = rt1015p_hw_params,
    215};
    216
    217static int rt1015p_init(struct snd_soc_pcm_runtime *rtd)
    218{
    219	struct snd_soc_card *card = rtd->card;
    220	int ret;
    221
    222	if (rt1015p_get_num_codecs() == 1)
    223		ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes,
    224					      ARRAY_SIZE(rt1015p_1dev_dapm_routes));
    225	else
    226		ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes,
    227					      ARRAY_SIZE(rt1015p_2dev_dapm_routes));
    228	if (ret)
    229		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
    230	return ret;
    231}
    232
    233void sof_rt1015p_dai_link(struct snd_soc_dai_link *link)
    234{
    235	link->codecs = rt1015p_dai_link_components;
    236	link->num_codecs = rt1015p_get_num_codecs();
    237	link->init = rt1015p_init;
    238	link->ops = &rt1015p_ops;
    239}
    240EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    241
    242void sof_rt1015p_codec_conf(struct snd_soc_card *card)
    243{
    244	if (rt1015p_get_num_codecs() == 1)
    245		return;
    246
    247	card->codec_conf = rt1015p_codec_confs;
    248	card->num_configs = ARRAY_SIZE(rt1015p_codec_confs);
    249}
    250EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    251
    252/*
    253 * RT1015 audio amplifier
    254 */
    255
    256static int rt1015_hw_params(struct snd_pcm_substream *substream,
    257			    struct snd_pcm_hw_params *params)
    258{
    259	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    260	struct snd_soc_dai *codec_dai;
    261	int i, fs = 64, ret;
    262
    263	for_each_rtd_codec_dais(rtd, i, codec_dai) {
    264		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
    265					  params_rate(params) * fs,
    266					  params_rate(params) * 256);
    267		if (ret)
    268			return ret;
    269
    270		ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
    271					     params_rate(params) * 256,
    272					     SND_SOC_CLOCK_IN);
    273		if (ret)
    274			return ret;
    275	}
    276
    277	return 0;
    278}
    279
    280static int rt1015_hw_params_pll_and_tdm(struct snd_pcm_substream *substream,
    281					 struct snd_pcm_hw_params *params)
    282{
    283	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    284	struct snd_soc_dai *codec_dai;
    285	int i, fs = 100, ret;
    286
    287	for_each_rtd_codec_dais(rtd, i, codec_dai) {
    288		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
    289					  params_rate(params) * fs,
    290					  params_rate(params) * 256);
    291		if (ret)
    292			return ret;
    293
    294		ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
    295					     params_rate(params) * 256,
    296					     SND_SOC_CLOCK_IN);
    297		if (ret)
    298			return ret;
    299	}
    300	/* rx slot 1 for RT1015_DEV0_NAME */
    301	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0),
    302				       0x0, 0x1, 4, 24);
    303	if (ret)
    304		return ret;
    305
    306	/* rx slot 2 for RT1015_DEV1_NAME */
    307	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 1),
    308				       0x0, 0x2, 4, 24);
    309	if (ret)
    310		return ret;
    311
    312	return 0;
    313}
    314
    315static struct snd_soc_ops rt1015_ops = {
    316	.hw_params = rt1015_hw_params,
    317};
    318
    319static struct snd_soc_codec_conf rt1015_amp_conf[] = {
    320	{
    321		.dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),
    322		.name_prefix = "Left",
    323	},
    324	{
    325		.dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),
    326		.name_prefix = "Right",
    327	},
    328};
    329
    330static struct snd_soc_dai_link_component rt1015_components[] = {
    331	{
    332		.name = RT1015_DEV0_NAME,
    333		.dai_name = RT1015_CODEC_DAI,
    334	},
    335	{
    336		.name = RT1015_DEV1_NAME,
    337		.dai_name = RT1015_CODEC_DAI,
    338	},
    339};
    340
    341static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
    342{
    343	return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr,
    344					ARRAY_SIZE(speaker_map_lr));
    345}
    346
    347void sof_rt1015_codec_conf(struct snd_soc_card *card)
    348{
    349	card->codec_conf = rt1015_amp_conf;
    350	card->num_configs = ARRAY_SIZE(rt1015_amp_conf);
    351}
    352EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    353
    354void sof_rt1015_dai_link(struct snd_soc_dai_link *link, unsigned int fs)
    355{
    356	link->codecs = rt1015_components;
    357	link->num_codecs = ARRAY_SIZE(rt1015_components);
    358	link->init = speaker_codec_init_lr;
    359	link->ops = &rt1015_ops;
    360
    361	if (fs == 100)
    362		rt1015_ops.hw_params = rt1015_hw_params_pll_and_tdm;
    363}
    364EXPORT_SYMBOL_NS(sof_rt1015_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    365
    366/*
    367 * RT1308 audio amplifier
    368 */
    369static const struct snd_kcontrol_new rt1308_kcontrols[] = {
    370	SOC_DAPM_PIN_SWITCH("Speakers"),
    371};
    372
    373static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = {
    374	SND_SOC_DAPM_SPK("Speakers", NULL),
    375};
    376
    377static const struct snd_soc_dapm_route rt1308_dapm_routes[] = {
    378	/* speaker */
    379	{"Speakers", NULL, "SPOL"},
    380	{"Speakers", NULL, "SPOR"},
    381};
    382
    383static struct snd_soc_dai_link_component rt1308_components[] = {
    384	{
    385		.name = RT1308_DEV0_NAME,
    386		.dai_name = RT1308_CODEC_DAI,
    387	}
    388};
    389
    390static int rt1308_init(struct snd_soc_pcm_runtime *rtd)
    391{
    392	struct snd_soc_card *card = rtd->card;
    393	int ret;
    394
    395	ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_dapm_widgets,
    396					ARRAY_SIZE(rt1308_dapm_widgets));
    397	if (ret) {
    398		dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret);
    399		return ret;
    400	}
    401
    402	ret = snd_soc_add_card_controls(card, rt1308_kcontrols,
    403					ARRAY_SIZE(rt1308_kcontrols));
    404	if (ret) {
    405		dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret);
    406		return ret;
    407	}
    408
    409	ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_dapm_routes,
    410				      ARRAY_SIZE(rt1308_dapm_routes));
    411
    412	if (ret)
    413		dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret);
    414
    415	return ret;
    416}
    417
    418static int rt1308_hw_params(struct snd_pcm_substream *substream,
    419			    struct snd_pcm_hw_params *params)
    420{
    421	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    422	struct snd_soc_card *card = rtd->card;
    423	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
    424	int clk_id, clk_freq, pll_out;
    425	int ret;
    426
    427	clk_id = RT1308_PLL_S_MCLK;
    428	/* get the tplg configured mclk. */
    429	clk_freq = sof_dai_get_mclk(rtd);
    430
    431	pll_out = params_rate(params) * 512;
    432
    433	/* Set rt1308 pll */
    434	ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out);
    435	if (ret < 0) {
    436		dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", ret);
    437		return ret;
    438	}
    439
    440	/* Set rt1308 sysclk */
    441	ret = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out,
    442				     SND_SOC_CLOCK_IN);
    443	if (ret < 0)
    444		dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", ret);
    445
    446	return ret;
    447}
    448
    449static const struct snd_soc_ops rt1308_ops = {
    450	.hw_params = rt1308_hw_params,
    451};
    452
    453void sof_rt1308_dai_link(struct snd_soc_dai_link *link)
    454{
    455	link->codecs = rt1308_components;
    456	link->num_codecs = ARRAY_SIZE(rt1308_components);
    457	link->init = rt1308_init;
    458	link->ops = &rt1308_ops;
    459}
    460EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    461
    462/*
    463 * 2-amp Configuration for RT1019
    464 */
    465
    466static const struct snd_soc_dapm_route rt1019_dapm_routes[] = {
    467	/* speaker */
    468	{ "Left Spk", NULL, "Speaker" },
    469	{ "Right Spk", NULL, "Speaker" },
    470};
    471
    472static struct snd_soc_dai_link_component rt1019_components[] = {
    473	{
    474		.name = RT1019_DEV0_NAME,
    475		.dai_name = RT1019_CODEC_DAI,
    476	},
    477};
    478
    479static int rt1019_init(struct snd_soc_pcm_runtime *rtd)
    480{
    481	struct snd_soc_card *card = rtd->card;
    482	int ret;
    483
    484	ret = snd_soc_dapm_add_routes(&card->dapm, rt1019_dapm_routes,
    485				      ARRAY_SIZE(rt1019_dapm_routes));
    486	if (ret) {
    487		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
    488		return ret;
    489	}
    490	return ret;
    491}
    492
    493void sof_rt1019_dai_link(struct snd_soc_dai_link *link)
    494{
    495	link->codecs = rt1019_components;
    496	link->num_codecs = ARRAY_SIZE(rt1019_components);
    497	link->init = rt1019_init;
    498}
    499EXPORT_SYMBOL_NS(sof_rt1019_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
    500
    501MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers");
    502MODULE_LICENSE("GPL");