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

wl1273.c (12487B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ALSA SoC WL1273 codec driver
      4 *
      5 * Author:      Matti Aaltonen, <matti.j.aaltonen@nokia.com>
      6 *
      7 * Copyright:   (C) 2010, 2011 Nokia Corporation
      8 */
      9
     10#include <linux/mfd/wl1273-core.h>
     11#include <linux/slab.h>
     12#include <linux/module.h>
     13#include <sound/pcm.h>
     14#include <sound/pcm_params.h>
     15#include <sound/soc.h>
     16#include <sound/initval.h>
     17
     18#include "wl1273.h"
     19
     20enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX };
     21
     22/* codec private data */
     23struct wl1273_priv {
     24	enum wl1273_mode mode;
     25	struct wl1273_core *core;
     26	unsigned int channels;
     27};
     28
     29static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core,
     30				      int rate, int width)
     31{
     32	struct device *dev = &core->client->dev;
     33	int r = 0;
     34	u16 mode;
     35
     36	dev_dbg(dev, "rate: %d\n", rate);
     37	dev_dbg(dev, "width: %d\n", width);
     38
     39	mutex_lock(&core->lock);
     40
     41	mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE;
     42
     43	switch (rate) {
     44	case 48000:
     45		mode |= WL1273_IS2_RATE_48K;
     46		break;
     47	case 44100:
     48		mode |= WL1273_IS2_RATE_44_1K;
     49		break;
     50	case 32000:
     51		mode |= WL1273_IS2_RATE_32K;
     52		break;
     53	case 22050:
     54		mode |= WL1273_IS2_RATE_22_05K;
     55		break;
     56	case 16000:
     57		mode |= WL1273_IS2_RATE_16K;
     58		break;
     59	case 12000:
     60		mode |= WL1273_IS2_RATE_12K;
     61		break;
     62	case 11025:
     63		mode |= WL1273_IS2_RATE_11_025;
     64		break;
     65	case 8000:
     66		mode |= WL1273_IS2_RATE_8K;
     67		break;
     68	default:
     69		dev_err(dev, "Sampling rate: %d not supported\n", rate);
     70		r = -EINVAL;
     71		goto out;
     72	}
     73
     74	switch (width) {
     75	case 16:
     76		mode |= WL1273_IS2_WIDTH_32;
     77		break;
     78	case 20:
     79		mode |= WL1273_IS2_WIDTH_40;
     80		break;
     81	case 24:
     82		mode |= WL1273_IS2_WIDTH_48;
     83		break;
     84	case 25:
     85		mode |= WL1273_IS2_WIDTH_50;
     86		break;
     87	case 30:
     88		mode |= WL1273_IS2_WIDTH_60;
     89		break;
     90	case 32:
     91		mode |= WL1273_IS2_WIDTH_64;
     92		break;
     93	case 40:
     94		mode |= WL1273_IS2_WIDTH_80;
     95		break;
     96	case 48:
     97		mode |= WL1273_IS2_WIDTH_96;
     98		break;
     99	case 64:
    100		mode |= WL1273_IS2_WIDTH_128;
    101		break;
    102	default:
    103		dev_err(dev, "Data width: %d not supported\n", width);
    104		r = -EINVAL;
    105		goto out;
    106	}
    107
    108	dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n",  WL1273_I2S_DEF_MODE);
    109	dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode);
    110	dev_dbg(dev, "mode: 0x%04x\n", mode);
    111
    112	if (core->i2s_mode != mode) {
    113		r = core->write(core, WL1273_I2S_MODE_CONFIG_SET, mode);
    114		if (r)
    115			goto out;
    116
    117		core->i2s_mode = mode;
    118		r = core->write(core, WL1273_AUDIO_ENABLE,
    119				WL1273_AUDIO_ENABLE_I2S);
    120		if (r)
    121			goto out;
    122	}
    123out:
    124	mutex_unlock(&core->lock);
    125
    126	return r;
    127}
    128
    129static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core,
    130					    int channel_number)
    131{
    132	struct device *dev = &core->client->dev;
    133	int r = 0;
    134
    135	dev_dbg(dev, "%s\n", __func__);
    136
    137	mutex_lock(&core->lock);
    138
    139	if (core->channel_number == channel_number)
    140		goto out;
    141
    142	if (channel_number == 1 && core->mode == WL1273_MODE_RX)
    143		r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO);
    144	else if (channel_number == 1 && core->mode == WL1273_MODE_TX)
    145		r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO);
    146	else if (channel_number == 2 && core->mode == WL1273_MODE_RX)
    147		r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO);
    148	else if (channel_number == 2 && core->mode == WL1273_MODE_TX)
    149		r = core->write(core, WL1273_MONO_SET, WL1273_TX_STEREO);
    150	else
    151		r = -EINVAL;
    152out:
    153	mutex_unlock(&core->lock);
    154
    155	return r;
    156}
    157
    158static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
    159				      struct snd_ctl_elem_value *ucontrol)
    160{
    161	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    162	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    163
    164	ucontrol->value.enumerated.item[0] = wl1273->mode;
    165
    166	return 0;
    167}
    168
    169/*
    170 * TODO: Implement the audio routing in the driver. Now this control
    171 * only indicates the setting that has been done elsewhere (in the user
    172 * space).
    173 */
    174static const char * const wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" };
    175
    176static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
    177				      struct snd_ctl_elem_value *ucontrol)
    178{
    179	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    180	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    181
    182	if (wl1273->mode == ucontrol->value.enumerated.item[0])
    183		return 0;
    184
    185	/* Do not allow changes while stream is running */
    186	if (snd_soc_component_active(component))
    187		return -EPERM;
    188
    189	if (ucontrol->value.enumerated.item[0] >=  ARRAY_SIZE(wl1273_audio_route))
    190		return -EINVAL;
    191
    192	wl1273->mode = ucontrol->value.enumerated.item[0];
    193
    194	return 1;
    195}
    196
    197static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route);
    198
    199static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
    200				   struct snd_ctl_elem_value *ucontrol)
    201{
    202	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    203	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    204
    205	dev_dbg(component->dev, "%s: enter.\n", __func__);
    206
    207	ucontrol->value.enumerated.item[0] = wl1273->core->audio_mode;
    208
    209	return 0;
    210}
    211
    212static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
    213				   struct snd_ctl_elem_value *ucontrol)
    214{
    215	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    216	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    217	int val, r = 0;
    218
    219	dev_dbg(component->dev, "%s: enter.\n", __func__);
    220
    221	val = ucontrol->value.enumerated.item[0];
    222	if (wl1273->core->audio_mode == val)
    223		return 0;
    224
    225	r = wl1273->core->set_audio(wl1273->core, val);
    226	if (r < 0)
    227		return r;
    228
    229	return 1;
    230}
    231
    232static const char * const wl1273_audio_strings[] = { "Digital", "Analog" };
    233
    234static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings);
    235
    236static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
    237				    struct snd_ctl_elem_value *ucontrol)
    238{
    239	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    240	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    241
    242	dev_dbg(component->dev, "%s: enter.\n", __func__);
    243
    244	ucontrol->value.integer.value[0] = wl1273->core->volume;
    245
    246	return 0;
    247}
    248
    249static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol,
    250				    struct snd_ctl_elem_value *ucontrol)
    251{
    252	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    253	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    254	int r;
    255
    256	dev_dbg(component->dev, "%s: enter.\n", __func__);
    257
    258	r = wl1273->core->set_volume(wl1273->core,
    259				     ucontrol->value.integer.value[0]);
    260	if (r)
    261		return r;
    262
    263	return 1;
    264}
    265
    266static const struct snd_kcontrol_new wl1273_controls[] = {
    267	SOC_ENUM_EXT("Codec Mode", wl1273_enum,
    268		     snd_wl1273_get_audio_route, snd_wl1273_set_audio_route),
    269	SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum,
    270		     snd_wl1273_fm_audio_get,  snd_wl1273_fm_audio_put),
    271	SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0,
    272		       snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put),
    273};
    274
    275static const struct snd_soc_dapm_widget wl1273_dapm_widgets[] = {
    276	SND_SOC_DAPM_INPUT("RX"),
    277
    278	SND_SOC_DAPM_OUTPUT("TX"),
    279};
    280
    281static const struct snd_soc_dapm_route wl1273_dapm_routes[] = {
    282	{ "Capture", NULL, "RX" },
    283
    284	{ "TX", NULL, "Playback" },
    285};
    286
    287static int wl1273_startup(struct snd_pcm_substream *substream,
    288			  struct snd_soc_dai *dai)
    289{
    290	struct snd_soc_component *component = dai->component;
    291	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    292
    293	switch (wl1273->mode) {
    294	case WL1273_MODE_BT:
    295		snd_pcm_hw_constraint_single(substream->runtime,
    296					     SNDRV_PCM_HW_PARAM_RATE, 8000);
    297		snd_pcm_hw_constraint_single(substream->runtime,
    298					     SNDRV_PCM_HW_PARAM_CHANNELS, 1);
    299		break;
    300	case WL1273_MODE_FM_RX:
    301		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    302			pr_err("Cannot play in RX mode.\n");
    303			return -EINVAL;
    304		}
    305		break;
    306	case WL1273_MODE_FM_TX:
    307		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
    308			pr_err("Cannot capture in TX mode.\n");
    309			return -EINVAL;
    310		}
    311		break;
    312	default:
    313		return -EINVAL;
    314	}
    315
    316	return 0;
    317}
    318
    319static int wl1273_hw_params(struct snd_pcm_substream *substream,
    320			    struct snd_pcm_hw_params *params,
    321			    struct snd_soc_dai *dai)
    322{
    323	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(dai->component);
    324	struct wl1273_core *core = wl1273->core;
    325	unsigned int rate, width, r;
    326
    327	if (params_width(params) != 16) {
    328		dev_err(dai->dev, "%d bits/sample not supported\n",
    329			params_width(params));
    330		return -EINVAL;
    331	}
    332
    333	rate = params_rate(params);
    334	width =  hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
    335
    336	if (wl1273->mode == WL1273_MODE_BT) {
    337		if (rate != 8000) {
    338			pr_err("Rate %d not supported.\n", params_rate(params));
    339			return -EINVAL;
    340		}
    341
    342		if (params_channels(params) != 1) {
    343			pr_err("Only mono supported.\n");
    344			return -EINVAL;
    345		}
    346
    347		return 0;
    348	}
    349
    350	if (wl1273->mode == WL1273_MODE_FM_TX &&
    351	    substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
    352		pr_err("Only playback supported with TX.\n");
    353		return -EINVAL;
    354	}
    355
    356	if (wl1273->mode == WL1273_MODE_FM_RX  &&
    357	    substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    358		pr_err("Only capture supported with RX.\n");
    359		return -EINVAL;
    360	}
    361
    362	if (wl1273->mode != WL1273_MODE_FM_RX  &&
    363	    wl1273->mode != WL1273_MODE_FM_TX) {
    364		pr_err("Unexpected mode: %d.\n", wl1273->mode);
    365		return -EINVAL;
    366	}
    367
    368	r = snd_wl1273_fm_set_i2s_mode(core, rate, width);
    369	if (r)
    370		return r;
    371
    372	wl1273->channels = params_channels(params);
    373	r = snd_wl1273_fm_set_channel_number(core, wl1273->channels);
    374	if (r)
    375		return r;
    376
    377	return 0;
    378}
    379
    380static const struct snd_soc_dai_ops wl1273_dai_ops = {
    381	.startup	= wl1273_startup,
    382	.hw_params	= wl1273_hw_params,
    383};
    384
    385static struct snd_soc_dai_driver wl1273_dai = {
    386	.name = "wl1273-fm",
    387	.playback = {
    388		.stream_name = "Playback",
    389		.channels_min = 1,
    390		.channels_max = 2,
    391		.rates = SNDRV_PCM_RATE_8000_48000,
    392		.formats = SNDRV_PCM_FMTBIT_S16_LE},
    393	.capture = {
    394		.stream_name = "Capture",
    395		.channels_min = 1,
    396		.channels_max = 2,
    397		.rates = SNDRV_PCM_RATE_8000_48000,
    398		.formats = SNDRV_PCM_FMTBIT_S16_LE},
    399	.ops = &wl1273_dai_ops,
    400};
    401
    402/* Audio interface format for the soc_card driver */
    403int wl1273_get_format(struct snd_soc_component *component, unsigned int *fmt)
    404{
    405	struct wl1273_priv *wl1273;
    406
    407	if (component == NULL || fmt == NULL)
    408		return -EINVAL;
    409
    410	wl1273 = snd_soc_component_get_drvdata(component);
    411
    412	switch (wl1273->mode) {
    413	case WL1273_MODE_FM_RX:
    414	case WL1273_MODE_FM_TX:
    415		*fmt =	SND_SOC_DAIFMT_I2S |
    416			SND_SOC_DAIFMT_NB_NF |
    417			SND_SOC_DAIFMT_CBP_CFP;
    418
    419		break;
    420	case WL1273_MODE_BT:
    421		*fmt =	SND_SOC_DAIFMT_DSP_A |
    422			SND_SOC_DAIFMT_IB_NF |
    423			SND_SOC_DAIFMT_CBP_CFP;
    424
    425		break;
    426	default:
    427		return -EINVAL;
    428	}
    429
    430	return 0;
    431}
    432EXPORT_SYMBOL_GPL(wl1273_get_format);
    433
    434static int wl1273_probe(struct snd_soc_component *component)
    435{
    436	struct wl1273_core **core = component->dev->platform_data;
    437	struct wl1273_priv *wl1273;
    438
    439	dev_dbg(component->dev, "%s.\n", __func__);
    440
    441	if (!core) {
    442		dev_err(component->dev, "Platform data is missing.\n");
    443		return -EINVAL;
    444	}
    445
    446	wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
    447	if (!wl1273)
    448		return -ENOMEM;
    449
    450	wl1273->mode = WL1273_MODE_BT;
    451	wl1273->core = *core;
    452
    453	snd_soc_component_set_drvdata(component, wl1273);
    454
    455	return 0;
    456}
    457
    458static void wl1273_remove(struct snd_soc_component *component)
    459{
    460	struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
    461
    462	dev_dbg(component->dev, "%s\n", __func__);
    463	kfree(wl1273);
    464}
    465
    466static const struct snd_soc_component_driver soc_component_dev_wl1273 = {
    467	.probe			= wl1273_probe,
    468	.remove			= wl1273_remove,
    469	.controls		= wl1273_controls,
    470	.num_controls		= ARRAY_SIZE(wl1273_controls),
    471	.dapm_widgets		= wl1273_dapm_widgets,
    472	.num_dapm_widgets	= ARRAY_SIZE(wl1273_dapm_widgets),
    473	.dapm_routes		= wl1273_dapm_routes,
    474	.num_dapm_routes	= ARRAY_SIZE(wl1273_dapm_routes),
    475	.idle_bias_on		= 1,
    476	.use_pmdown_time	= 1,
    477	.endianness		= 1,
    478	.non_legacy_dai_naming	= 1,
    479};
    480
    481static int wl1273_platform_probe(struct platform_device *pdev)
    482{
    483	return devm_snd_soc_register_component(&pdev->dev,
    484				      &soc_component_dev_wl1273,
    485				      &wl1273_dai, 1);
    486}
    487
    488static int wl1273_platform_remove(struct platform_device *pdev)
    489{
    490	return 0;
    491}
    492
    493MODULE_ALIAS("platform:wl1273-codec");
    494
    495static struct platform_driver wl1273_platform_driver = {
    496	.driver		= {
    497		.name	= "wl1273-codec",
    498	},
    499	.probe		= wl1273_platform_probe,
    500	.remove		= wl1273_platform_remove,
    501};
    502
    503module_platform_driver(wl1273_platform_driver);
    504
    505MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
    506MODULE_DESCRIPTION("ASoC WL1273 codec driver");
    507MODULE_LICENSE("GPL");