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

wm8958-dsp2.c (28943B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * wm8958-dsp2.c  --  WM8958 DSP2 support
      4 *
      5 * Copyright 2011 Wolfson Microelectronics plc
      6 *
      7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/moduleparam.h>
     12#include <linux/init.h>
     13#include <linux/delay.h>
     14#include <linux/pm.h>
     15#include <linux/i2c.h>
     16#include <linux/platform_device.h>
     17#include <linux/slab.h>
     18#include <sound/soc.h>
     19#include <sound/initval.h>
     20#include <sound/tlv.h>
     21#include <trace/events/asoc.h>
     22
     23#include <linux/mfd/wm8994/core.h>
     24#include <linux/mfd/wm8994/registers.h>
     25#include <linux/mfd/wm8994/pdata.h>
     26#include <linux/mfd/wm8994/gpio.h>
     27
     28#include <asm/unaligned.h>
     29
     30#include "wm8994.h"
     31
     32#define WM_FW_BLOCK_INFO 0xff
     33#define WM_FW_BLOCK_PM   0x00
     34#define WM_FW_BLOCK_X    0x01
     35#define WM_FW_BLOCK_Y    0x02
     36#define WM_FW_BLOCK_Z    0x03
     37#define WM_FW_BLOCK_I    0x06
     38#define WM_FW_BLOCK_A    0x08
     39#define WM_FW_BLOCK_C    0x0c
     40
     41static int wm8958_dsp2_fw(struct snd_soc_component *component, const char *name,
     42			  const struct firmware *fw, bool check)
     43{
     44	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
     45	u64 data64;
     46	u32 data32;
     47	const u8 *data;
     48	char *str;
     49	size_t block_len, len;
     50	int ret = 0;
     51
     52	/* Suppress unneeded downloads */
     53	if (wm8994->cur_fw == fw)
     54		return 0;
     55
     56	if (fw->size < 32) {
     57		dev_err(component->dev, "%s: firmware too short (%zd bytes)\n",
     58			name, fw->size);
     59		goto err;
     60	}
     61
     62	if (memcmp(fw->data, "WMFW", 4) != 0) {
     63		data32 = get_unaligned_be32(fw->data);
     64		dev_err(component->dev, "%s: firmware has bad file magic %08x\n",
     65			name, data32);
     66		goto err;
     67	}
     68
     69	len = get_unaligned_be32(fw->data + 4);
     70	data32 = get_unaligned_be32(fw->data + 8);
     71
     72	if ((data32 >> 24) & 0xff) {
     73		dev_err(component->dev, "%s: unsupported firmware version %d\n",
     74			name, (data32 >> 24) & 0xff);
     75		goto err;
     76	}
     77	if ((data32 & 0xffff) != 8958) {
     78		dev_err(component->dev, "%s: unsupported target device %d\n",
     79			name, data32 & 0xffff);
     80		goto err;
     81	}
     82	if (((data32 >> 16) & 0xff) != 0xc) {
     83		dev_err(component->dev, "%s: unsupported target core %d\n",
     84			name, (data32 >> 16) & 0xff);
     85		goto err;
     86	}
     87
     88	if (check) {
     89		data64 = get_unaligned_be64(fw->data + 24);
     90		dev_info(component->dev, "%s timestamp %llx\n",  name, data64);
     91	} else {
     92		snd_soc_component_write(component, 0x102, 0x2);
     93		snd_soc_component_write(component, 0x900, 0x2);
     94	}
     95
     96	data = fw->data + len;
     97	len = fw->size - len;
     98	while (len) {
     99		if (len < 12) {
    100			dev_err(component->dev, "%s short data block of %zd\n",
    101				name, len);
    102			goto err;
    103		}
    104
    105		block_len = get_unaligned_be32(data + 4);
    106		if (block_len + 8 > len) {
    107			dev_err(component->dev, "%zd byte block longer than file\n",
    108				block_len);
    109			goto err;
    110		}
    111		if (block_len == 0) {
    112			dev_err(component->dev, "Zero length block\n");
    113			goto err;
    114		}
    115
    116		data32 = get_unaligned_be32(data);
    117
    118		switch ((data32 >> 24) & 0xff) {
    119		case WM_FW_BLOCK_INFO:
    120			/* Informational text */
    121			if (!check)
    122				break;
    123
    124			str = kzalloc(block_len + 1, GFP_KERNEL);
    125			if (str) {
    126				memcpy(str, data + 8, block_len);
    127				dev_info(component->dev, "%s: %s\n", name, str);
    128				kfree(str);
    129			} else {
    130				dev_err(component->dev, "Out of memory\n");
    131			}
    132			break;
    133		case WM_FW_BLOCK_PM:
    134		case WM_FW_BLOCK_X:
    135		case WM_FW_BLOCK_Y:
    136		case WM_FW_BLOCK_Z:
    137		case WM_FW_BLOCK_I:
    138		case WM_FW_BLOCK_A:
    139		case WM_FW_BLOCK_C:
    140			dev_dbg(component->dev, "%s: %zd bytes of %x@%x\n", name,
    141				block_len, (data32 >> 24) & 0xff,
    142				data32 & 0xffffff);
    143
    144			if (check)
    145				break;
    146
    147			data32 &= 0xffffff;
    148
    149			wm8994_bulk_write(wm8994->wm8994,
    150					  data32 & 0xffffff,
    151					  block_len / 2,
    152					  (void *)(data + 8));
    153
    154			break;
    155		default:
    156			dev_warn(component->dev, "%s: unknown block type %d\n",
    157				 name, (data32 >> 24) & 0xff);
    158			break;
    159		}
    160
    161		/* Round up to the next 32 bit word */
    162		block_len += block_len % 4;
    163
    164		data += block_len + 8;
    165		len -= block_len + 8;
    166	}
    167
    168	if (!check) {
    169		dev_dbg(component->dev, "%s: download done\n", name);
    170		wm8994->cur_fw = fw;
    171	} else {
    172		dev_info(component->dev, "%s: got firmware\n", name);
    173	}
    174
    175	goto ok;
    176
    177err:
    178	ret = -EINVAL;
    179ok:
    180	if (!check) {
    181		snd_soc_component_write(component, 0x900, 0x0);
    182		snd_soc_component_write(component, 0x102, 0x0);
    183	}
    184
    185	return ret;
    186}
    187
    188static void wm8958_dsp_start_mbc(struct snd_soc_component *component, int path)
    189{
    190	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    191	struct wm8994 *control = wm8994->wm8994;
    192	int i;
    193
    194	/* If the DSP is already running then noop */
    195	if (snd_soc_component_read(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA)
    196		return;
    197
    198	/* If we have MBC firmware download it */
    199	if (wm8994->mbc)
    200		wm8958_dsp2_fw(component, "MBC", wm8994->mbc, false);
    201
    202	snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
    203			    WM8958_DSP2_ENA, WM8958_DSP2_ENA);
    204
    205	/* If we've got user supplied MBC settings use them */
    206	if (control->pdata.num_mbc_cfgs) {
    207		struct wm8958_mbc_cfg *cfg
    208			= &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
    209
    210		for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
    211			snd_soc_component_write(component, i + WM8958_MBC_BAND_1_K_1,
    212				      cfg->coeff_regs[i]);
    213
    214		for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++)
    215			snd_soc_component_write(component,
    216				      i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1,
    217				      cfg->cutoff_regs[i]);
    218	}
    219
    220	/* Run the DSP */
    221	snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
    222		      WM8958_DSP2_RUNR);
    223
    224	/* And we're off! */
    225	snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
    226			    WM8958_MBC_ENA |
    227			    WM8958_MBC_SEL_MASK,
    228			    path << WM8958_MBC_SEL_SHIFT |
    229			    WM8958_MBC_ENA);
    230}
    231
    232static void wm8958_dsp_start_vss(struct snd_soc_component *component, int path)
    233{
    234	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    235	struct wm8994 *control = wm8994->wm8994;
    236	int i, ena;
    237
    238	if (wm8994->mbc_vss)
    239		wm8958_dsp2_fw(component, "MBC+VSS", wm8994->mbc_vss, false);
    240
    241	snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
    242			    WM8958_DSP2_ENA, WM8958_DSP2_ENA);
    243
    244	/* If we've got user supplied settings use them */
    245	if (control->pdata.num_mbc_cfgs) {
    246		struct wm8958_mbc_cfg *cfg
    247			= &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
    248
    249		for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++)
    250			snd_soc_component_write(component, i + 0x2800,
    251				      cfg->combined_regs[i]);
    252	}
    253
    254	if (control->pdata.num_vss_cfgs) {
    255		struct wm8958_vss_cfg *cfg
    256			= &control->pdata.vss_cfgs[wm8994->vss_cfg];
    257
    258		for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
    259			snd_soc_component_write(component, i + 0x2600, cfg->regs[i]);
    260	}
    261
    262	if (control->pdata.num_vss_hpf_cfgs) {
    263		struct wm8958_vss_hpf_cfg *cfg
    264			= &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg];
    265
    266		for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
    267			snd_soc_component_write(component, i + 0x2400, cfg->regs[i]);
    268	}
    269
    270	/* Run the DSP */
    271	snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
    272		      WM8958_DSP2_RUNR);
    273
    274	/* Enable the algorithms we've selected */
    275	ena = 0;
    276	if (wm8994->mbc_ena[path])
    277		ena |= 0x8;
    278	if (wm8994->hpf2_ena[path])
    279		ena |= 0x4;
    280	if (wm8994->hpf1_ena[path])
    281		ena |= 0x2;
    282	if (wm8994->vss_ena[path])
    283		ena |= 0x1;
    284
    285	snd_soc_component_write(component, 0x2201, ena);
    286
    287	/* Switch the DSP into the data path */
    288	snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
    289			    WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
    290			    path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
    291}
    292
    293static void wm8958_dsp_start_enh_eq(struct snd_soc_component *component, int path)
    294{
    295	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    296	struct wm8994 *control = wm8994->wm8994;
    297	int i;
    298
    299	wm8958_dsp2_fw(component, "ENH_EQ", wm8994->enh_eq, false);
    300
    301	snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
    302			    WM8958_DSP2_ENA, WM8958_DSP2_ENA);
    303
    304	/* If we've got user supplied settings use them */
    305	if (control->pdata.num_enh_eq_cfgs) {
    306		struct wm8958_enh_eq_cfg *cfg
    307			= &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg];
    308
    309		for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
    310			snd_soc_component_write(component, i + 0x2200,
    311				      cfg->regs[i]);
    312	}
    313
    314	/* Run the DSP */
    315	snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
    316		      WM8958_DSP2_RUNR);
    317
    318	/* Switch the DSP into the data path */
    319	snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
    320			    WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
    321			    path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
    322}
    323
    324static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int start)
    325{
    326	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    327	int pwr_reg = snd_soc_component_read(component, WM8994_POWER_MANAGEMENT_5);
    328	int ena, reg, aif;
    329
    330	switch (path) {
    331	case 0:
    332		pwr_reg &= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA);
    333		aif = 0;
    334		break;
    335	case 1:
    336		pwr_reg &= (WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
    337		aif = 0;
    338		break;
    339	case 2:
    340		pwr_reg &= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA);
    341		aif = 1;
    342		break;
    343	default:
    344		WARN(1, "Invalid path %d\n", path);
    345		return;
    346	}
    347
    348	/* Do we have both an active AIF and an active algorithm? */
    349	ena = wm8994->mbc_ena[path] || wm8994->vss_ena[path] ||
    350		wm8994->hpf1_ena[path] || wm8994->hpf2_ena[path] ||
    351		wm8994->enh_eq_ena[path];
    352	if (!pwr_reg)
    353		ena = 0;
    354
    355	reg = snd_soc_component_read(component, WM8958_DSP2_PROGRAM);
    356
    357	dev_dbg(component->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n",
    358		path, wm8994->dsp_active, start, pwr_reg, reg);
    359
    360	if (start && ena) {
    361		/* If the DSP is already running then noop */
    362		if (reg & WM8958_DSP2_ENA)
    363			return;
    364
    365		/* If either AIFnCLK is not yet enabled postpone */
    366		if (!(snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1)
    367		      & WM8994_AIF1CLK_ENA_MASK) &&
    368		    !(snd_soc_component_read(component, WM8994_AIF2_CLOCKING_1)
    369		      & WM8994_AIF2CLK_ENA_MASK))
    370			return;
    371
    372		/* Switch the clock over to the appropriate AIF */
    373		snd_soc_component_update_bits(component, WM8994_CLOCKING_1,
    374				    WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA,
    375				    aif << WM8958_DSP2CLK_SRC_SHIFT |
    376				    WM8958_DSP2CLK_ENA);
    377
    378		if (wm8994->enh_eq_ena[path])
    379			wm8958_dsp_start_enh_eq(component, path);
    380		else if (wm8994->vss_ena[path] || wm8994->hpf1_ena[path] ||
    381		    wm8994->hpf2_ena[path])
    382			wm8958_dsp_start_vss(component, path);
    383		else if (wm8994->mbc_ena[path])
    384			wm8958_dsp_start_mbc(component, path);
    385
    386		wm8994->dsp_active = path;
    387
    388		dev_dbg(component->dev, "DSP running in path %d\n", path);
    389	}
    390
    391	if (!start && wm8994->dsp_active == path) {
    392		/* If the DSP is already stopped then noop */
    393		if (!(reg & WM8958_DSP2_ENA))
    394			return;
    395
    396		snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
    397				    WM8958_MBC_ENA, 0);	
    398		snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
    399			      WM8958_DSP2_STOP);
    400		snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
    401				    WM8958_DSP2_ENA, 0);
    402		snd_soc_component_update_bits(component, WM8994_CLOCKING_1,
    403				    WM8958_DSP2CLK_ENA, 0);
    404
    405		wm8994->dsp_active = -1;
    406
    407		dev_dbg(component->dev, "DSP stopped\n");
    408	}
    409}
    410
    411int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
    412		  struct snd_kcontrol *kcontrol, int event)
    413{
    414	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
    415	struct wm8994 *control = dev_get_drvdata(component->dev->parent);
    416	int i;
    417
    418	if (control->type != WM8958)
    419		return 0;
    420
    421	switch (event) {
    422	case SND_SOC_DAPM_POST_PMU:
    423	case SND_SOC_DAPM_PRE_PMU:
    424		for (i = 0; i < 3; i++)
    425			wm8958_dsp_apply(component, i, 1);
    426		break;
    427	case SND_SOC_DAPM_POST_PMD:
    428	case SND_SOC_DAPM_PRE_PMD:
    429		for (i = 0; i < 3; i++)
    430			wm8958_dsp_apply(component, i, 0);
    431		break;
    432	}
    433
    434	return 0;
    435}
    436
    437/* Check if DSP2 is in use on another AIF */
    438static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif)
    439{
    440	int i;
    441
    442	for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) {
    443		if (i == aif)
    444			continue;
    445		if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] ||
    446		    wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i])
    447			return 1;
    448	}
    449
    450	return 0;
    451}
    452
    453static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
    454			       struct snd_ctl_elem_value *ucontrol)
    455{
    456	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    457	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    458	struct wm8994 *control = wm8994->wm8994;
    459	int value = ucontrol->value.enumerated.item[0];
    460	int reg;
    461
    462	/* Don't allow on the fly reconfiguration */
    463	reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
    464	if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
    465		return -EBUSY;
    466
    467	if (value >= control->pdata.num_mbc_cfgs)
    468		return -EINVAL;
    469
    470	wm8994->mbc_cfg = value;
    471
    472	return 0;
    473}
    474
    475static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
    476			       struct snd_ctl_elem_value *ucontrol)
    477{
    478	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    479	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    480
    481	ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
    482
    483	return 0;
    484}
    485
    486static int wm8958_mbc_info(struct snd_kcontrol *kcontrol,
    487			   struct snd_ctl_elem_info *uinfo)
    488{
    489	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
    490	uinfo->count = 1;
    491	uinfo->value.integer.min = 0;
    492	uinfo->value.integer.max = 1;
    493	return 0;
    494}
    495
    496static int wm8958_mbc_get(struct snd_kcontrol *kcontrol,
    497			  struct snd_ctl_elem_value *ucontrol)
    498{
    499	int mbc = kcontrol->private_value;
    500	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    501	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    502
    503	ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc];
    504
    505	return 0;
    506}
    507
    508static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
    509			  struct snd_ctl_elem_value *ucontrol)
    510{
    511	int mbc = kcontrol->private_value;
    512	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    513	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    514
    515	if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0])
    516		return 0;
    517
    518	if (ucontrol->value.integer.value[0] > 1)
    519		return -EINVAL;
    520
    521	if (wm8958_dsp2_busy(wm8994, mbc)) {
    522		dev_dbg(component->dev, "DSP2 active on %d already\n", mbc);
    523		return -EBUSY;
    524	}
    525
    526	if (wm8994->enh_eq_ena[mbc])
    527		return -EBUSY;
    528
    529	wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0];
    530
    531	wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]);
    532
    533	return 1;
    534}
    535
    536#define WM8958_MBC_SWITCH(xname, xval) {\
    537	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
    538	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
    539	.info = wm8958_mbc_info, \
    540	.get = wm8958_mbc_get, .put = wm8958_mbc_put, \
    541	.private_value = xval }
    542
    543static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
    544			       struct snd_ctl_elem_value *ucontrol)
    545{
    546	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    547	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    548	struct wm8994 *control = wm8994->wm8994;
    549	int value = ucontrol->value.enumerated.item[0];
    550	int reg;
    551
    552	/* Don't allow on the fly reconfiguration */
    553	reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
    554	if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
    555		return -EBUSY;
    556
    557	if (value >= control->pdata.num_vss_cfgs)
    558		return -EINVAL;
    559
    560	wm8994->vss_cfg = value;
    561
    562	return 0;
    563}
    564
    565static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
    566			       struct snd_ctl_elem_value *ucontrol)
    567{
    568	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    569	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    570
    571	ucontrol->value.enumerated.item[0] = wm8994->vss_cfg;
    572
    573	return 0;
    574}
    575
    576static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
    577				   struct snd_ctl_elem_value *ucontrol)
    578{
    579	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    580	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    581	struct wm8994 *control = wm8994->wm8994;
    582	int value = ucontrol->value.enumerated.item[0];
    583	int reg;
    584
    585	/* Don't allow on the fly reconfiguration */
    586	reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
    587	if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
    588		return -EBUSY;
    589
    590	if (value >= control->pdata.num_vss_hpf_cfgs)
    591		return -EINVAL;
    592
    593	wm8994->vss_hpf_cfg = value;
    594
    595	return 0;
    596}
    597
    598static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol,
    599				   struct snd_ctl_elem_value *ucontrol)
    600{
    601	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    602	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    603
    604	ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg;
    605
    606	return 0;
    607}
    608
    609static int wm8958_vss_info(struct snd_kcontrol *kcontrol,
    610			   struct snd_ctl_elem_info *uinfo)
    611{
    612	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
    613	uinfo->count = 1;
    614	uinfo->value.integer.min = 0;
    615	uinfo->value.integer.max = 1;
    616	return 0;
    617}
    618
    619static int wm8958_vss_get(struct snd_kcontrol *kcontrol,
    620			  struct snd_ctl_elem_value *ucontrol)
    621{
    622	int vss = kcontrol->private_value;
    623	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    624	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    625
    626	ucontrol->value.integer.value[0] = wm8994->vss_ena[vss];
    627
    628	return 0;
    629}
    630
    631static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
    632			  struct snd_ctl_elem_value *ucontrol)
    633{
    634	int vss = kcontrol->private_value;
    635	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    636	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    637
    638	if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0])
    639		return 0;
    640
    641	if (ucontrol->value.integer.value[0] > 1)
    642		return -EINVAL;
    643
    644	if (!wm8994->mbc_vss)
    645		return -ENODEV;
    646
    647	if (wm8958_dsp2_busy(wm8994, vss)) {
    648		dev_dbg(component->dev, "DSP2 active on %d already\n", vss);
    649		return -EBUSY;
    650	}
    651
    652	if (wm8994->enh_eq_ena[vss])
    653		return -EBUSY;
    654
    655	wm8994->vss_ena[vss] = ucontrol->value.integer.value[0];
    656
    657	wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]);
    658
    659	return 1;
    660}
    661
    662
    663#define WM8958_VSS_SWITCH(xname, xval) {\
    664	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
    665	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
    666	.info = wm8958_vss_info, \
    667	.get = wm8958_vss_get, .put = wm8958_vss_put, \
    668	.private_value = xval }
    669
    670static int wm8958_hpf_info(struct snd_kcontrol *kcontrol,
    671			   struct snd_ctl_elem_info *uinfo)
    672{
    673	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
    674	uinfo->count = 1;
    675	uinfo->value.integer.min = 0;
    676	uinfo->value.integer.max = 1;
    677	return 0;
    678}
    679
    680static int wm8958_hpf_get(struct snd_kcontrol *kcontrol,
    681			  struct snd_ctl_elem_value *ucontrol)
    682{
    683	int hpf = kcontrol->private_value;
    684	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    685	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    686
    687	if (hpf < 3)
    688		ucontrol->value.integer.value[0] = wm8994->hpf1_ena[hpf % 3];
    689	else
    690		ucontrol->value.integer.value[0] = wm8994->hpf2_ena[hpf % 3];
    691
    692	return 0;
    693}
    694
    695static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
    696			  struct snd_ctl_elem_value *ucontrol)
    697{
    698	int hpf = kcontrol->private_value;
    699	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    700	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    701
    702	if (hpf < 3) {
    703		if (wm8994->hpf1_ena[hpf % 3] ==
    704		    ucontrol->value.integer.value[0])
    705			return 0;
    706	} else {
    707		if (wm8994->hpf2_ena[hpf % 3] ==
    708		    ucontrol->value.integer.value[0])
    709			return 0;
    710	}
    711
    712	if (ucontrol->value.integer.value[0] > 1)
    713		return -EINVAL;
    714
    715	if (!wm8994->mbc_vss)
    716		return -ENODEV;
    717
    718	if (wm8958_dsp2_busy(wm8994, hpf % 3)) {
    719		dev_dbg(component->dev, "DSP2 active on %d already\n", hpf);
    720		return -EBUSY;
    721	}
    722
    723	if (wm8994->enh_eq_ena[hpf % 3])
    724		return -EBUSY;
    725
    726	if (hpf < 3)
    727		wm8994->hpf1_ena[hpf % 3] = ucontrol->value.integer.value[0];
    728	else
    729		wm8994->hpf2_ena[hpf % 3] = ucontrol->value.integer.value[0];
    730
    731	wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]);
    732
    733	return 1;
    734}
    735
    736#define WM8958_HPF_SWITCH(xname, xval) {\
    737	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
    738	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
    739	.info = wm8958_hpf_info, \
    740	.get = wm8958_hpf_get, .put = wm8958_hpf_put, \
    741	.private_value = xval }
    742
    743static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
    744				  struct snd_ctl_elem_value *ucontrol)
    745{
    746	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    747	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    748	struct wm8994 *control = wm8994->wm8994;
    749	int value = ucontrol->value.enumerated.item[0];
    750	int reg;
    751
    752	/* Don't allow on the fly reconfiguration */
    753	reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
    754	if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
    755		return -EBUSY;
    756
    757	if (value >= control->pdata.num_enh_eq_cfgs)
    758		return -EINVAL;
    759
    760	wm8994->enh_eq_cfg = value;
    761
    762	return 0;
    763}
    764
    765static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol,
    766				  struct snd_ctl_elem_value *ucontrol)
    767{
    768	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    769	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    770
    771	ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg;
    772
    773	return 0;
    774}
    775
    776static int wm8958_enh_eq_info(struct snd_kcontrol *kcontrol,
    777			   struct snd_ctl_elem_info *uinfo)
    778{
    779	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
    780	uinfo->count = 1;
    781	uinfo->value.integer.min = 0;
    782	uinfo->value.integer.max = 1;
    783	return 0;
    784}
    785
    786static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol,
    787			  struct snd_ctl_elem_value *ucontrol)
    788{
    789	int eq = kcontrol->private_value;
    790	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    791	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    792
    793	ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq];
    794
    795	return 0;
    796}
    797
    798static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
    799			  struct snd_ctl_elem_value *ucontrol)
    800{
    801	int eq = kcontrol->private_value;
    802	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
    803	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    804
    805	if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0])
    806		return 0;
    807
    808	if (ucontrol->value.integer.value[0] > 1)
    809		return -EINVAL;
    810
    811	if (!wm8994->enh_eq)
    812		return -ENODEV;
    813
    814	if (wm8958_dsp2_busy(wm8994, eq)) {
    815		dev_dbg(component->dev, "DSP2 active on %d already\n", eq);
    816		return -EBUSY;
    817	}
    818
    819	if (wm8994->mbc_ena[eq] || wm8994->vss_ena[eq] ||
    820	    wm8994->hpf1_ena[eq] || wm8994->hpf2_ena[eq])
    821		return -EBUSY;
    822
    823	wm8994->enh_eq_ena[eq] = ucontrol->value.integer.value[0];
    824
    825	wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]);
    826
    827	return 1;
    828}
    829
    830#define WM8958_ENH_EQ_SWITCH(xname, xval) {\
    831	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
    832	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
    833	.info = wm8958_enh_eq_info, \
    834	.get = wm8958_enh_eq_get, .put = wm8958_enh_eq_put, \
    835	.private_value = xval }
    836
    837static const struct snd_kcontrol_new wm8958_mbc_snd_controls[] = {
    838WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0),
    839WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1),
    840WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2),
    841};
    842
    843static const struct snd_kcontrol_new wm8958_vss_snd_controls[] = {
    844WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0),
    845WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1),
    846WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2),
    847WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0),
    848WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1),
    849WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2),
    850WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3),
    851WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4),
    852WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5),
    853};
    854
    855static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls[] = {
    856WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0),
    857WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1),
    858WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2),
    859};
    860
    861static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context)
    862{
    863	struct snd_soc_component *component = context;
    864	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    865
    866	if (fw && (wm8958_dsp2_fw(component, "ENH_EQ", fw, true) == 0)) {
    867		mutex_lock(&wm8994->fw_lock);
    868		wm8994->enh_eq = fw;
    869		mutex_unlock(&wm8994->fw_lock);
    870	}
    871}
    872
    873static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
    874{
    875	struct snd_soc_component *component = context;
    876	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    877
    878	if (fw && (wm8958_dsp2_fw(component, "MBC+VSS", fw, true) == 0)) {
    879		mutex_lock(&wm8994->fw_lock);
    880		wm8994->mbc_vss = fw;
    881		mutex_unlock(&wm8994->fw_lock);
    882	}
    883}
    884
    885static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
    886{
    887	struct snd_soc_component *component = context;
    888	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    889
    890	if (fw && (wm8958_dsp2_fw(component, "MBC", fw, true) == 0)) {
    891		mutex_lock(&wm8994->fw_lock);
    892		wm8994->mbc = fw;
    893		mutex_unlock(&wm8994->fw_lock);
    894	}
    895}
    896
    897void wm8958_dsp2_init(struct snd_soc_component *component)
    898{
    899	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
    900	struct wm8994 *control = wm8994->wm8994;
    901	struct wm8994_pdata *pdata = &control->pdata;
    902	int ret, i;
    903
    904	wm8994->dsp_active = -1;
    905
    906	snd_soc_add_component_controls(component, wm8958_mbc_snd_controls,
    907			     ARRAY_SIZE(wm8958_mbc_snd_controls));
    908	snd_soc_add_component_controls(component, wm8958_vss_snd_controls,
    909			     ARRAY_SIZE(wm8958_vss_snd_controls));
    910	snd_soc_add_component_controls(component, wm8958_enh_eq_snd_controls,
    911			     ARRAY_SIZE(wm8958_enh_eq_snd_controls));
    912
    913
    914	/* We don't *require* firmware and don't want to delay boot */
    915	request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
    916				"wm8958_mbc.wfw", component->dev, GFP_KERNEL,
    917				component, wm8958_mbc_loaded);
    918	request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
    919				"wm8958_mbc_vss.wfw", component->dev, GFP_KERNEL,
    920				component, wm8958_mbc_vss_loaded);
    921	request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
    922				"wm8958_enh_eq.wfw", component->dev, GFP_KERNEL,
    923				component, wm8958_enh_eq_loaded);
    924
    925	if (pdata->num_mbc_cfgs) {
    926		struct snd_kcontrol_new mbc_control[] = {
    927			SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum,
    928				     wm8958_get_mbc_enum, wm8958_put_mbc_enum),
    929		};
    930
    931		/* We need an array of texts for the enum API */
    932		wm8994->mbc_texts = kmalloc_array(pdata->num_mbc_cfgs,
    933						  sizeof(char *),
    934						  GFP_KERNEL);
    935		if (!wm8994->mbc_texts)
    936			return;
    937
    938		for (i = 0; i < pdata->num_mbc_cfgs; i++)
    939			wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
    940
    941		wm8994->mbc_enum.items = pdata->num_mbc_cfgs;
    942		wm8994->mbc_enum.texts = wm8994->mbc_texts;
    943
    944		ret = snd_soc_add_component_controls(wm8994->hubs.component,
    945						 mbc_control, 1);
    946		if (ret != 0)
    947			dev_err(wm8994->hubs.component->dev,
    948				"Failed to add MBC mode controls: %d\n", ret);
    949	}
    950
    951	if (pdata->num_vss_cfgs) {
    952		struct snd_kcontrol_new vss_control[] = {
    953			SOC_ENUM_EXT("VSS Mode", wm8994->vss_enum,
    954				     wm8958_get_vss_enum, wm8958_put_vss_enum),
    955		};
    956
    957		/* We need an array of texts for the enum API */
    958		wm8994->vss_texts = kmalloc_array(pdata->num_vss_cfgs,
    959						  sizeof(char *),
    960						  GFP_KERNEL);
    961		if (!wm8994->vss_texts)
    962			return;
    963
    964		for (i = 0; i < pdata->num_vss_cfgs; i++)
    965			wm8994->vss_texts[i] = pdata->vss_cfgs[i].name;
    966
    967		wm8994->vss_enum.items = pdata->num_vss_cfgs;
    968		wm8994->vss_enum.texts = wm8994->vss_texts;
    969
    970		ret = snd_soc_add_component_controls(wm8994->hubs.component,
    971						 vss_control, 1);
    972		if (ret != 0)
    973			dev_err(wm8994->hubs.component->dev,
    974				"Failed to add VSS mode controls: %d\n", ret);
    975	}
    976
    977	if (pdata->num_vss_hpf_cfgs) {
    978		struct snd_kcontrol_new hpf_control[] = {
    979			SOC_ENUM_EXT("VSS HPF Mode", wm8994->vss_hpf_enum,
    980				     wm8958_get_vss_hpf_enum,
    981				     wm8958_put_vss_hpf_enum),
    982		};
    983
    984		/* We need an array of texts for the enum API */
    985		wm8994->vss_hpf_texts = kmalloc_array(pdata->num_vss_hpf_cfgs,
    986						      sizeof(char *),
    987						      GFP_KERNEL);
    988		if (!wm8994->vss_hpf_texts)
    989			return;
    990
    991		for (i = 0; i < pdata->num_vss_hpf_cfgs; i++)
    992			wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name;
    993
    994		wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs;
    995		wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
    996
    997		ret = snd_soc_add_component_controls(wm8994->hubs.component,
    998						 hpf_control, 1);
    999		if (ret != 0)
   1000			dev_err(wm8994->hubs.component->dev,
   1001				"Failed to add VSS HPFmode controls: %d\n",
   1002				ret);
   1003	}
   1004
   1005	if (pdata->num_enh_eq_cfgs) {
   1006		struct snd_kcontrol_new eq_control[] = {
   1007			SOC_ENUM_EXT("Enhanced EQ Mode", wm8994->enh_eq_enum,
   1008				     wm8958_get_enh_eq_enum,
   1009				     wm8958_put_enh_eq_enum),
   1010		};
   1011
   1012		/* We need an array of texts for the enum API */
   1013		wm8994->enh_eq_texts = kmalloc_array(pdata->num_enh_eq_cfgs,
   1014						     sizeof(char *),
   1015						     GFP_KERNEL);
   1016		if (!wm8994->enh_eq_texts)
   1017			return;
   1018
   1019		for (i = 0; i < pdata->num_enh_eq_cfgs; i++)
   1020			wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name;
   1021
   1022		wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs;
   1023		wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
   1024
   1025		ret = snd_soc_add_component_controls(wm8994->hubs.component,
   1026						 eq_control, 1);
   1027		if (ret != 0)
   1028			dev_err(wm8994->hubs.component->dev,
   1029				"Failed to add enhanced EQ controls: %d\n",
   1030				ret);
   1031	}
   1032}