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_maxim_common.c (10737B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2//
      3// Copyright(c) 2020 Intel Corporation. All rights reserved.
      4#include <linux/module.h>
      5#include <linux/string.h>
      6#include <sound/pcm.h>
      7#include <sound/soc.h>
      8#include <sound/soc-acpi.h>
      9#include <sound/soc-dai.h>
     10#include <sound/soc-dapm.h>
     11#include <uapi/sound/asound.h>
     12#include "sof_maxim_common.h"
     13
     14#define MAX_98373_PIN_NAME 16
     15
     16const struct snd_soc_dapm_route max_98373_dapm_routes[] = {
     17	/* speaker */
     18	{ "Left Spk", NULL, "Left BE_OUT" },
     19	{ "Right Spk", NULL, "Right BE_OUT" },
     20};
     21EXPORT_SYMBOL_NS(max_98373_dapm_routes, SND_SOC_INTEL_SOF_MAXIM_COMMON);
     22
     23static struct snd_soc_codec_conf max_98373_codec_conf[] = {
     24	{
     25		.dlc = COMP_CODEC_CONF(MAX_98373_DEV0_NAME),
     26		.name_prefix = "Right",
     27	},
     28	{
     29		.dlc = COMP_CODEC_CONF(MAX_98373_DEV1_NAME),
     30		.name_prefix = "Left",
     31	},
     32};
     33
     34struct snd_soc_dai_link_component max_98373_components[] = {
     35	{  /* For Right */
     36		.name = MAX_98373_DEV0_NAME,
     37		.dai_name = MAX_98373_CODEC_DAI,
     38	},
     39	{  /* For Left */
     40		.name = MAX_98373_DEV1_NAME,
     41		.dai_name = MAX_98373_CODEC_DAI,
     42	},
     43};
     44EXPORT_SYMBOL_NS(max_98373_components, SND_SOC_INTEL_SOF_MAXIM_COMMON);
     45
     46static int max_98373_hw_params(struct snd_pcm_substream *substream,
     47			       struct snd_pcm_hw_params *params)
     48{
     49	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     50	struct snd_soc_dai *codec_dai;
     51	int j;
     52
     53	for_each_rtd_codec_dais(rtd, j, codec_dai) {
     54		if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) {
     55			/* DEV0 tdm slot configuration */
     56			snd_soc_dai_set_tdm_slot(codec_dai, 0x03, 3, 8, 32);
     57		}
     58		if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) {
     59			/* DEV1 tdm slot configuration */
     60			snd_soc_dai_set_tdm_slot(codec_dai, 0x0C, 3, 8, 32);
     61		}
     62	}
     63	return 0;
     64}
     65
     66int max_98373_trigger(struct snd_pcm_substream *substream, int cmd)
     67{
     68	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     69	struct snd_soc_dai *codec_dai;
     70	struct snd_soc_dai *cpu_dai;
     71	int j;
     72	int ret = 0;
     73
     74	/* set spk pin by playback only */
     75	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
     76		return 0;
     77
     78	cpu_dai = asoc_rtd_to_cpu(rtd, 0);
     79	for_each_rtd_codec_dais(rtd, j, codec_dai) {
     80		struct snd_soc_dapm_context *dapm =
     81				snd_soc_component_get_dapm(cpu_dai->component);
     82		char pin_name[MAX_98373_PIN_NAME];
     83
     84		snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk",
     85			 codec_dai->component->name_prefix);
     86
     87		switch (cmd) {
     88		case SNDRV_PCM_TRIGGER_START:
     89		case SNDRV_PCM_TRIGGER_RESUME:
     90		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
     91			ret = snd_soc_dapm_enable_pin(dapm, pin_name);
     92			if (!ret)
     93				snd_soc_dapm_sync(dapm);
     94			break;
     95		case SNDRV_PCM_TRIGGER_STOP:
     96		case SNDRV_PCM_TRIGGER_SUSPEND:
     97		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
     98			ret = snd_soc_dapm_disable_pin(dapm, pin_name);
     99			if (!ret)
    100				snd_soc_dapm_sync(dapm);
    101			break;
    102		default:
    103			break;
    104		}
    105	}
    106
    107	return ret;
    108}
    109EXPORT_SYMBOL_NS(max_98373_trigger, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    110
    111struct snd_soc_ops max_98373_ops = {
    112	.hw_params = max_98373_hw_params,
    113	.trigger = max_98373_trigger,
    114};
    115EXPORT_SYMBOL_NS(max_98373_ops, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    116
    117int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd)
    118{
    119	struct snd_soc_card *card = rtd->card;
    120	int ret;
    121
    122	ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes,
    123				      ARRAY_SIZE(max_98373_dapm_routes));
    124	if (ret)
    125		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
    126	return ret;
    127}
    128EXPORT_SYMBOL_NS(max_98373_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    129
    130void max_98373_set_codec_conf(struct snd_soc_card *card)
    131{
    132	card->codec_conf = max_98373_codec_conf;
    133	card->num_configs = ARRAY_SIZE(max_98373_codec_conf);
    134}
    135EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    136
    137/*
    138 * Maxim MAX98390
    139 */
    140static const struct snd_soc_dapm_route max_98390_dapm_routes[] = {
    141	/* speaker */
    142	{ "Left Spk", NULL, "Left BE_OUT" },
    143	{ "Right Spk", NULL, "Right BE_OUT" },
    144};
    145
    146static const struct snd_kcontrol_new max_98390_tt_kcontrols[] = {
    147	SOC_DAPM_PIN_SWITCH("TL Spk"),
    148	SOC_DAPM_PIN_SWITCH("TR Spk"),
    149};
    150
    151static const struct snd_soc_dapm_widget max_98390_tt_dapm_widgets[] = {
    152	SND_SOC_DAPM_SPK("TL Spk", NULL),
    153	SND_SOC_DAPM_SPK("TR Spk", NULL),
    154};
    155
    156static const struct snd_soc_dapm_route max_98390_tt_dapm_routes[] = {
    157	/* Tweeter speaker */
    158	{ "TL Spk", NULL, "Tweeter Left BE_OUT" },
    159	{ "TR Spk", NULL, "Tweeter Right BE_OUT" },
    160};
    161
    162static struct snd_soc_codec_conf max_98390_codec_conf[] = {
    163	{
    164		.dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME),
    165		.name_prefix = "Right",
    166	},
    167	{
    168		.dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME),
    169		.name_prefix = "Left",
    170	},
    171};
    172
    173static struct snd_soc_codec_conf max_98390_4spk_codec_conf[] = {
    174	{
    175		.dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME),
    176		.name_prefix = "Right",
    177	},
    178	{
    179		.dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME),
    180		.name_prefix = "Left",
    181	},
    182	{
    183		.dlc = COMP_CODEC_CONF(MAX_98390_DEV2_NAME),
    184		.name_prefix = "Tweeter Right",
    185	},
    186	{
    187		.dlc = COMP_CODEC_CONF(MAX_98390_DEV3_NAME),
    188		.name_prefix = "Tweeter Left",
    189	},
    190};
    191
    192struct snd_soc_dai_link_component max_98390_components[] = {
    193	{
    194		.name = MAX_98390_DEV0_NAME,
    195		.dai_name = MAX_98390_CODEC_DAI,
    196	},
    197	{
    198		.name = MAX_98390_DEV1_NAME,
    199		.dai_name = MAX_98390_CODEC_DAI,
    200	},
    201};
    202EXPORT_SYMBOL_NS(max_98390_components, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    203
    204struct snd_soc_dai_link_component max_98390_4spk_components[] = {
    205	{
    206		.name = MAX_98390_DEV0_NAME,
    207		.dai_name = MAX_98390_CODEC_DAI,
    208	},
    209	{
    210		.name = MAX_98390_DEV1_NAME,
    211		.dai_name = MAX_98390_CODEC_DAI,
    212	},
    213	{
    214		.name = MAX_98390_DEV2_NAME,
    215		.dai_name = MAX_98390_CODEC_DAI,
    216	},
    217	{
    218		.name = MAX_98390_DEV3_NAME,
    219		.dai_name = MAX_98390_CODEC_DAI,
    220	},
    221};
    222EXPORT_SYMBOL_NS(max_98390_4spk_components, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    223
    224static int max_98390_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;
    229	int i;
    230
    231	for_each_rtd_codec_dais(rtd, i, codec_dai) {
    232		if (i >= ARRAY_SIZE(max_98390_4spk_components)) {
    233			dev_err(codec_dai->dev, "invalid codec index %d\n", i);
    234			return -ENODEV;
    235		}
    236
    237		if (!strcmp(codec_dai->component->name, MAX_98390_DEV0_NAME)) {
    238			/* DEV0 tdm slot configuration Right */
    239			snd_soc_dai_set_tdm_slot(codec_dai, 0x01, 3, 4, 32);
    240		}
    241		if (!strcmp(codec_dai->component->name, MAX_98390_DEV1_NAME)) {
    242			/* DEV1 tdm slot configuration Left */
    243			snd_soc_dai_set_tdm_slot(codec_dai, 0x02, 3, 4, 32);
    244		}
    245
    246		if (!strcmp(codec_dai->component->name, MAX_98390_DEV2_NAME)) {
    247			/* DEVi2 tdm slot configuration Tweeter Right */
    248			snd_soc_dai_set_tdm_slot(codec_dai, 0x04, 3, 4, 32);
    249		}
    250		if (!strcmp(codec_dai->component->name, MAX_98390_DEV3_NAME)) {
    251			/* DEV3 tdm slot configuration Tweeter Left */
    252			snd_soc_dai_set_tdm_slot(codec_dai, 0x08, 3, 4, 32);
    253		}
    254	}
    255	return 0;
    256}
    257
    258int max_98390_spk_codec_init(struct snd_soc_pcm_runtime *rtd)
    259{
    260	struct snd_soc_card *card = rtd->card;
    261	int ret;
    262
    263	/* add regular speakers dapm route */
    264	ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_dapm_routes,
    265				      ARRAY_SIZE(max_98390_dapm_routes));
    266	if (ret) {
    267		dev_err(rtd->dev, "unable to add Left/Right Speaker dapm, ret %d\n", ret);
    268		return ret;
    269	}
    270
    271	/* add widgets/controls/dapm for tweeter speakers */
    272	if (acpi_dev_present("MX98390", "3", -1)) {
    273		ret = snd_soc_dapm_new_controls(&card->dapm, max_98390_tt_dapm_widgets,
    274						ARRAY_SIZE(max_98390_tt_dapm_widgets));
    275
    276		if (ret) {
    277			dev_err(rtd->dev, "unable to add tweeter dapm controls, ret %d\n", ret);
    278			/* Don't need to add routes if widget addition failed */
    279			return ret;
    280		}
    281
    282		ret = snd_soc_add_card_controls(card, max_98390_tt_kcontrols,
    283						ARRAY_SIZE(max_98390_tt_kcontrols));
    284		if (ret) {
    285			dev_err(rtd->dev, "unable to add tweeter card controls, ret %d\n", ret);
    286			return ret;
    287		}
    288
    289		ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_tt_dapm_routes,
    290					      ARRAY_SIZE(max_98390_tt_dapm_routes));
    291		if (ret)
    292			dev_err(rtd->dev,
    293				"unable to add Tweeter Left/Right Speaker dapm, ret %d\n", ret);
    294	}
    295	return ret;
    296}
    297EXPORT_SYMBOL_NS(max_98390_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    298
    299const struct snd_soc_ops max_98390_ops = {
    300	.hw_params = max_98390_hw_params,
    301};
    302EXPORT_SYMBOL_NS(max_98390_ops, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    303
    304void max_98390_set_codec_conf(struct snd_soc_card *card, int ch)
    305{
    306	if (ch == ARRAY_SIZE(max_98390_4spk_codec_conf)) {
    307		card->codec_conf = max_98390_4spk_codec_conf;
    308		card->num_configs = ARRAY_SIZE(max_98390_4spk_codec_conf);
    309	} else {
    310		card->codec_conf = max_98390_codec_conf;
    311		card->num_configs = ARRAY_SIZE(max_98390_codec_conf);
    312	}
    313}
    314EXPORT_SYMBOL_NS(max_98390_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    315
    316/*
    317 * Maxim MAX98357A/MAX98360A
    318 */
    319static const struct snd_kcontrol_new max_98357a_kcontrols[] = {
    320	SOC_DAPM_PIN_SWITCH("Spk"),
    321};
    322
    323static const struct snd_soc_dapm_widget max_98357a_dapm_widgets[] = {
    324	SND_SOC_DAPM_SPK("Spk", NULL),
    325};
    326
    327static const struct snd_soc_dapm_route max_98357a_dapm_routes[] = {
    328	/* speaker */
    329	{"Spk", NULL, "Speaker"},
    330};
    331
    332static struct snd_soc_dai_link_component max_98357a_components[] = {
    333	{
    334		.name = MAX_98357A_DEV0_NAME,
    335		.dai_name = MAX_98357A_CODEC_DAI,
    336	}
    337};
    338
    339static struct snd_soc_dai_link_component max_98360a_components[] = {
    340	{
    341		.name = MAX_98360A_DEV0_NAME,
    342		.dai_name = MAX_98357A_CODEC_DAI,
    343	}
    344};
    345
    346static int max_98357a_init(struct snd_soc_pcm_runtime *rtd)
    347{
    348	struct snd_soc_card *card = rtd->card;
    349	int ret;
    350
    351	ret = snd_soc_dapm_new_controls(&card->dapm, max_98357a_dapm_widgets,
    352					ARRAY_SIZE(max_98357a_dapm_widgets));
    353	if (ret) {
    354		dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
    355		/* Don't need to add routes if widget addition failed */
    356		return ret;
    357	}
    358
    359	ret = snd_soc_add_card_controls(card, max_98357a_kcontrols,
    360					ARRAY_SIZE(max_98357a_kcontrols));
    361	if (ret) {
    362		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
    363		return ret;
    364	}
    365
    366	ret = snd_soc_dapm_add_routes(&card->dapm, max_98357a_dapm_routes,
    367				      ARRAY_SIZE(max_98357a_dapm_routes));
    368
    369	if (ret)
    370		dev_err(rtd->dev, "unable to add dapm routes, ret %d\n", ret);
    371
    372	return ret;
    373}
    374
    375void max_98357a_dai_link(struct snd_soc_dai_link *link)
    376{
    377	link->codecs = max_98357a_components;
    378	link->num_codecs = ARRAY_SIZE(max_98357a_components);
    379	link->init = max_98357a_init;
    380}
    381EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    382
    383void max_98360a_dai_link(struct snd_soc_dai_link *link)
    384{
    385	link->codecs = max_98360a_components;
    386	link->num_codecs = ARRAY_SIZE(max_98360a_components);
    387	link->init = max_98357a_init;
    388}
    389EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
    390
    391MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers");
    392MODULE_LICENSE("GPL");