0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/moduleparam.h>
0012 #include <linux/init.h>
0013 #include <linux/delay.h>
0014 #include <linux/pm.h>
0015 #include <linux/i2c.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/slab.h>
0018 #include <sound/soc.h>
0019 #include <sound/initval.h>
0020 #include <sound/tlv.h>
0021 #include <trace/events/asoc.h>
0022
0023 #include <linux/mfd/wm8994/core.h>
0024 #include <linux/mfd/wm8994/registers.h>
0025 #include <linux/mfd/wm8994/pdata.h>
0026 #include <linux/mfd/wm8994/gpio.h>
0027
0028 #include <asm/unaligned.h>
0029
0030 #include "wm8994.h"
0031
0032 #define WM_FW_BLOCK_INFO 0xff
0033 #define WM_FW_BLOCK_PM 0x00
0034 #define WM_FW_BLOCK_X 0x01
0035 #define WM_FW_BLOCK_Y 0x02
0036 #define WM_FW_BLOCK_Z 0x03
0037 #define WM_FW_BLOCK_I 0x06
0038 #define WM_FW_BLOCK_A 0x08
0039 #define WM_FW_BLOCK_C 0x0c
0040
0041 static int wm8958_dsp2_fw(struct snd_soc_component *component, const char *name,
0042 const struct firmware *fw, bool check)
0043 {
0044 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0045 u64 data64;
0046 u32 data32;
0047 const u8 *data;
0048 char *str;
0049 size_t block_len, len;
0050 int ret = 0;
0051
0052
0053 if (wm8994->cur_fw == fw)
0054 return 0;
0055
0056 if (fw->size < 32) {
0057 dev_err(component->dev, "%s: firmware too short (%zd bytes)\n",
0058 name, fw->size);
0059 goto err;
0060 }
0061
0062 if (memcmp(fw->data, "WMFW", 4) != 0) {
0063 data32 = get_unaligned_be32(fw->data);
0064 dev_err(component->dev, "%s: firmware has bad file magic %08x\n",
0065 name, data32);
0066 goto err;
0067 }
0068
0069 len = get_unaligned_be32(fw->data + 4);
0070 data32 = get_unaligned_be32(fw->data + 8);
0071
0072 if ((data32 >> 24) & 0xff) {
0073 dev_err(component->dev, "%s: unsupported firmware version %d\n",
0074 name, (data32 >> 24) & 0xff);
0075 goto err;
0076 }
0077 if ((data32 & 0xffff) != 8958) {
0078 dev_err(component->dev, "%s: unsupported target device %d\n",
0079 name, data32 & 0xffff);
0080 goto err;
0081 }
0082 if (((data32 >> 16) & 0xff) != 0xc) {
0083 dev_err(component->dev, "%s: unsupported target core %d\n",
0084 name, (data32 >> 16) & 0xff);
0085 goto err;
0086 }
0087
0088 if (check) {
0089 data64 = get_unaligned_be64(fw->data + 24);
0090 dev_info(component->dev, "%s timestamp %llx\n", name, data64);
0091 } else {
0092 snd_soc_component_write(component, 0x102, 0x2);
0093 snd_soc_component_write(component, 0x900, 0x2);
0094 }
0095
0096 data = fw->data + len;
0097 len = fw->size - len;
0098 while (len) {
0099 if (len < 12) {
0100 dev_err(component->dev, "%s short data block of %zd\n",
0101 name, len);
0102 goto err;
0103 }
0104
0105 block_len = get_unaligned_be32(data + 4);
0106 if (block_len + 8 > len) {
0107 dev_err(component->dev, "%zd byte block longer than file\n",
0108 block_len);
0109 goto err;
0110 }
0111 if (block_len == 0) {
0112 dev_err(component->dev, "Zero length block\n");
0113 goto err;
0114 }
0115
0116 data32 = get_unaligned_be32(data);
0117
0118 switch ((data32 >> 24) & 0xff) {
0119 case WM_FW_BLOCK_INFO:
0120
0121 if (!check)
0122 break;
0123
0124 str = kzalloc(block_len + 1, GFP_KERNEL);
0125 if (str) {
0126 memcpy(str, data + 8, block_len);
0127 dev_info(component->dev, "%s: %s\n", name, str);
0128 kfree(str);
0129 } else {
0130 dev_err(component->dev, "Out of memory\n");
0131 }
0132 break;
0133 case WM_FW_BLOCK_PM:
0134 case WM_FW_BLOCK_X:
0135 case WM_FW_BLOCK_Y:
0136 case WM_FW_BLOCK_Z:
0137 case WM_FW_BLOCK_I:
0138 case WM_FW_BLOCK_A:
0139 case WM_FW_BLOCK_C:
0140 dev_dbg(component->dev, "%s: %zd bytes of %x@%x\n", name,
0141 block_len, (data32 >> 24) & 0xff,
0142 data32 & 0xffffff);
0143
0144 if (check)
0145 break;
0146
0147 data32 &= 0xffffff;
0148
0149 wm8994_bulk_write(wm8994->wm8994,
0150 data32 & 0xffffff,
0151 block_len / 2,
0152 (void *)(data + 8));
0153
0154 break;
0155 default:
0156 dev_warn(component->dev, "%s: unknown block type %d\n",
0157 name, (data32 >> 24) & 0xff);
0158 break;
0159 }
0160
0161
0162 block_len += block_len % 4;
0163
0164 data += block_len + 8;
0165 len -= block_len + 8;
0166 }
0167
0168 if (!check) {
0169 dev_dbg(component->dev, "%s: download done\n", name);
0170 wm8994->cur_fw = fw;
0171 } else {
0172 dev_info(component->dev, "%s: got firmware\n", name);
0173 }
0174
0175 goto ok;
0176
0177 err:
0178 ret = -EINVAL;
0179 ok:
0180 if (!check) {
0181 snd_soc_component_write(component, 0x900, 0x0);
0182 snd_soc_component_write(component, 0x102, 0x0);
0183 }
0184
0185 return ret;
0186 }
0187
0188 static void wm8958_dsp_start_mbc(struct snd_soc_component *component, int path)
0189 {
0190 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0191 struct wm8994 *control = wm8994->wm8994;
0192 int i;
0193
0194
0195 if (snd_soc_component_read(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA)
0196 return;
0197
0198
0199 if (wm8994->mbc)
0200 wm8958_dsp2_fw(component, "MBC", wm8994->mbc, false);
0201
0202 snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
0203 WM8958_DSP2_ENA, WM8958_DSP2_ENA);
0204
0205
0206 if (control->pdata.num_mbc_cfgs) {
0207 struct wm8958_mbc_cfg *cfg
0208 = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
0209
0210 for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
0211 snd_soc_component_write(component, i + WM8958_MBC_BAND_1_K_1,
0212 cfg->coeff_regs[i]);
0213
0214 for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++)
0215 snd_soc_component_write(component,
0216 i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1,
0217 cfg->cutoff_regs[i]);
0218 }
0219
0220
0221 snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
0222 WM8958_DSP2_RUNR);
0223
0224
0225 snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
0226 WM8958_MBC_ENA |
0227 WM8958_MBC_SEL_MASK,
0228 path << WM8958_MBC_SEL_SHIFT |
0229 WM8958_MBC_ENA);
0230 }
0231
0232 static void wm8958_dsp_start_vss(struct snd_soc_component *component, int path)
0233 {
0234 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0235 struct wm8994 *control = wm8994->wm8994;
0236 int i, ena;
0237
0238 if (wm8994->mbc_vss)
0239 wm8958_dsp2_fw(component, "MBC+VSS", wm8994->mbc_vss, false);
0240
0241 snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
0242 WM8958_DSP2_ENA, WM8958_DSP2_ENA);
0243
0244
0245 if (control->pdata.num_mbc_cfgs) {
0246 struct wm8958_mbc_cfg *cfg
0247 = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
0248
0249 for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++)
0250 snd_soc_component_write(component, i + 0x2800,
0251 cfg->combined_regs[i]);
0252 }
0253
0254 if (control->pdata.num_vss_cfgs) {
0255 struct wm8958_vss_cfg *cfg
0256 = &control->pdata.vss_cfgs[wm8994->vss_cfg];
0257
0258 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
0259 snd_soc_component_write(component, i + 0x2600, cfg->regs[i]);
0260 }
0261
0262 if (control->pdata.num_vss_hpf_cfgs) {
0263 struct wm8958_vss_hpf_cfg *cfg
0264 = &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg];
0265
0266 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
0267 snd_soc_component_write(component, i + 0x2400, cfg->regs[i]);
0268 }
0269
0270
0271 snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
0272 WM8958_DSP2_RUNR);
0273
0274
0275 ena = 0;
0276 if (wm8994->mbc_ena[path])
0277 ena |= 0x8;
0278 if (wm8994->hpf2_ena[path])
0279 ena |= 0x4;
0280 if (wm8994->hpf1_ena[path])
0281 ena |= 0x2;
0282 if (wm8994->vss_ena[path])
0283 ena |= 0x1;
0284
0285 snd_soc_component_write(component, 0x2201, ena);
0286
0287
0288 snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
0289 WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
0290 path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
0291 }
0292
0293 static void wm8958_dsp_start_enh_eq(struct snd_soc_component *component, int path)
0294 {
0295 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0296 struct wm8994 *control = wm8994->wm8994;
0297 int i;
0298
0299 wm8958_dsp2_fw(component, "ENH_EQ", wm8994->enh_eq, false);
0300
0301 snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
0302 WM8958_DSP2_ENA, WM8958_DSP2_ENA);
0303
0304
0305 if (control->pdata.num_enh_eq_cfgs) {
0306 struct wm8958_enh_eq_cfg *cfg
0307 = &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg];
0308
0309 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
0310 snd_soc_component_write(component, i + 0x2200,
0311 cfg->regs[i]);
0312 }
0313
0314
0315 snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
0316 WM8958_DSP2_RUNR);
0317
0318
0319 snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
0320 WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
0321 path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
0322 }
0323
0324 static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int start)
0325 {
0326 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0327 int pwr_reg = snd_soc_component_read(component, WM8994_POWER_MANAGEMENT_5);
0328 int ena, reg, aif;
0329
0330 switch (path) {
0331 case 0:
0332 pwr_reg &= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA);
0333 aif = 0;
0334 break;
0335 case 1:
0336 pwr_reg &= (WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
0337 aif = 0;
0338 break;
0339 case 2:
0340 pwr_reg &= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA);
0341 aif = 1;
0342 break;
0343 default:
0344 WARN(1, "Invalid path %d\n", path);
0345 return;
0346 }
0347
0348
0349 ena = wm8994->mbc_ena[path] || wm8994->vss_ena[path] ||
0350 wm8994->hpf1_ena[path] || wm8994->hpf2_ena[path] ||
0351 wm8994->enh_eq_ena[path];
0352 if (!pwr_reg)
0353 ena = 0;
0354
0355 reg = snd_soc_component_read(component, WM8958_DSP2_PROGRAM);
0356
0357 dev_dbg(component->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n",
0358 path, wm8994->dsp_active, start, pwr_reg, reg);
0359
0360 if (start && ena) {
0361
0362 if (reg & WM8958_DSP2_ENA)
0363 return;
0364
0365
0366 if (!(snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1)
0367 & WM8994_AIF1CLK_ENA_MASK) &&
0368 !(snd_soc_component_read(component, WM8994_AIF2_CLOCKING_1)
0369 & WM8994_AIF2CLK_ENA_MASK))
0370 return;
0371
0372
0373 snd_soc_component_update_bits(component, WM8994_CLOCKING_1,
0374 WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA,
0375 aif << WM8958_DSP2CLK_SRC_SHIFT |
0376 WM8958_DSP2CLK_ENA);
0377
0378 if (wm8994->enh_eq_ena[path])
0379 wm8958_dsp_start_enh_eq(component, path);
0380 else if (wm8994->vss_ena[path] || wm8994->hpf1_ena[path] ||
0381 wm8994->hpf2_ena[path])
0382 wm8958_dsp_start_vss(component, path);
0383 else if (wm8994->mbc_ena[path])
0384 wm8958_dsp_start_mbc(component, path);
0385
0386 wm8994->dsp_active = path;
0387
0388 dev_dbg(component->dev, "DSP running in path %d\n", path);
0389 }
0390
0391 if (!start && wm8994->dsp_active == path) {
0392
0393 if (!(reg & WM8958_DSP2_ENA))
0394 return;
0395
0396 snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
0397 WM8958_MBC_ENA, 0);
0398 snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
0399 WM8958_DSP2_STOP);
0400 snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
0401 WM8958_DSP2_ENA, 0);
0402 snd_soc_component_update_bits(component, WM8994_CLOCKING_1,
0403 WM8958_DSP2CLK_ENA, 0);
0404
0405 wm8994->dsp_active = -1;
0406
0407 dev_dbg(component->dev, "DSP stopped\n");
0408 }
0409 }
0410
0411 int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
0412 struct snd_kcontrol *kcontrol, int event)
0413 {
0414 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0415 struct wm8994 *control = dev_get_drvdata(component->dev->parent);
0416 int i;
0417
0418 if (control->type != WM8958)
0419 return 0;
0420
0421 switch (event) {
0422 case SND_SOC_DAPM_POST_PMU:
0423 case SND_SOC_DAPM_PRE_PMU:
0424 for (i = 0; i < 3; i++)
0425 wm8958_dsp_apply(component, i, 1);
0426 break;
0427 case SND_SOC_DAPM_POST_PMD:
0428 case SND_SOC_DAPM_PRE_PMD:
0429 for (i = 0; i < 3; i++)
0430 wm8958_dsp_apply(component, i, 0);
0431 break;
0432 }
0433
0434 return 0;
0435 }
0436
0437
0438 static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif)
0439 {
0440 int i;
0441
0442 for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) {
0443 if (i == aif)
0444 continue;
0445 if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] ||
0446 wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i])
0447 return 1;
0448 }
0449
0450 return 0;
0451 }
0452
0453 static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
0454 struct snd_ctl_elem_value *ucontrol)
0455 {
0456 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0457 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0458 struct wm8994 *control = wm8994->wm8994;
0459 int value = ucontrol->value.enumerated.item[0];
0460 int reg;
0461
0462
0463 reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
0464 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
0465 return -EBUSY;
0466
0467 if (value >= control->pdata.num_mbc_cfgs)
0468 return -EINVAL;
0469
0470 wm8994->mbc_cfg = value;
0471
0472 return 0;
0473 }
0474
0475 static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
0476 struct snd_ctl_elem_value *ucontrol)
0477 {
0478 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0479 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0480
0481 ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
0482
0483 return 0;
0484 }
0485
0486 static int wm8958_mbc_info(struct snd_kcontrol *kcontrol,
0487 struct snd_ctl_elem_info *uinfo)
0488 {
0489 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0490 uinfo->count = 1;
0491 uinfo->value.integer.min = 0;
0492 uinfo->value.integer.max = 1;
0493 return 0;
0494 }
0495
0496 static int wm8958_mbc_get(struct snd_kcontrol *kcontrol,
0497 struct snd_ctl_elem_value *ucontrol)
0498 {
0499 int mbc = kcontrol->private_value;
0500 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0501 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0502
0503 ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc];
0504
0505 return 0;
0506 }
0507
0508 static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
0509 struct snd_ctl_elem_value *ucontrol)
0510 {
0511 int mbc = kcontrol->private_value;
0512 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0513 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0514
0515 if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0])
0516 return 0;
0517
0518 if (ucontrol->value.integer.value[0] > 1)
0519 return -EINVAL;
0520
0521 if (wm8958_dsp2_busy(wm8994, mbc)) {
0522 dev_dbg(component->dev, "DSP2 active on %d already\n", mbc);
0523 return -EBUSY;
0524 }
0525
0526 if (wm8994->enh_eq_ena[mbc])
0527 return -EBUSY;
0528
0529 wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0];
0530
0531 wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]);
0532
0533 return 1;
0534 }
0535
0536 #define WM8958_MBC_SWITCH(xname, xval) {\
0537 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
0538 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
0539 .info = wm8958_mbc_info, \
0540 .get = wm8958_mbc_get, .put = wm8958_mbc_put, \
0541 .private_value = xval }
0542
0543 static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
0544 struct snd_ctl_elem_value *ucontrol)
0545 {
0546 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0547 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0548 struct wm8994 *control = wm8994->wm8994;
0549 int value = ucontrol->value.enumerated.item[0];
0550 int reg;
0551
0552
0553 reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
0554 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
0555 return -EBUSY;
0556
0557 if (value >= control->pdata.num_vss_cfgs)
0558 return -EINVAL;
0559
0560 wm8994->vss_cfg = value;
0561
0562 return 0;
0563 }
0564
0565 static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
0566 struct snd_ctl_elem_value *ucontrol)
0567 {
0568 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0569 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0570
0571 ucontrol->value.enumerated.item[0] = wm8994->vss_cfg;
0572
0573 return 0;
0574 }
0575
0576 static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
0577 struct snd_ctl_elem_value *ucontrol)
0578 {
0579 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0580 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0581 struct wm8994 *control = wm8994->wm8994;
0582 int value = ucontrol->value.enumerated.item[0];
0583 int reg;
0584
0585
0586 reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
0587 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
0588 return -EBUSY;
0589
0590 if (value >= control->pdata.num_vss_hpf_cfgs)
0591 return -EINVAL;
0592
0593 wm8994->vss_hpf_cfg = value;
0594
0595 return 0;
0596 }
0597
0598 static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol,
0599 struct snd_ctl_elem_value *ucontrol)
0600 {
0601 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0602 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0603
0604 ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg;
0605
0606 return 0;
0607 }
0608
0609 static int wm8958_vss_info(struct snd_kcontrol *kcontrol,
0610 struct snd_ctl_elem_info *uinfo)
0611 {
0612 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0613 uinfo->count = 1;
0614 uinfo->value.integer.min = 0;
0615 uinfo->value.integer.max = 1;
0616 return 0;
0617 }
0618
0619 static int wm8958_vss_get(struct snd_kcontrol *kcontrol,
0620 struct snd_ctl_elem_value *ucontrol)
0621 {
0622 int vss = kcontrol->private_value;
0623 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0624 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0625
0626 ucontrol->value.integer.value[0] = wm8994->vss_ena[vss];
0627
0628 return 0;
0629 }
0630
0631 static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
0632 struct snd_ctl_elem_value *ucontrol)
0633 {
0634 int vss = kcontrol->private_value;
0635 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0636 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0637
0638 if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0])
0639 return 0;
0640
0641 if (ucontrol->value.integer.value[0] > 1)
0642 return -EINVAL;
0643
0644 if (!wm8994->mbc_vss)
0645 return -ENODEV;
0646
0647 if (wm8958_dsp2_busy(wm8994, vss)) {
0648 dev_dbg(component->dev, "DSP2 active on %d already\n", vss);
0649 return -EBUSY;
0650 }
0651
0652 if (wm8994->enh_eq_ena[vss])
0653 return -EBUSY;
0654
0655 wm8994->vss_ena[vss] = ucontrol->value.integer.value[0];
0656
0657 wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]);
0658
0659 return 1;
0660 }
0661
0662
0663 #define WM8958_VSS_SWITCH(xname, xval) {\
0664 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
0665 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
0666 .info = wm8958_vss_info, \
0667 .get = wm8958_vss_get, .put = wm8958_vss_put, \
0668 .private_value = xval }
0669
0670 static int wm8958_hpf_info(struct snd_kcontrol *kcontrol,
0671 struct snd_ctl_elem_info *uinfo)
0672 {
0673 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0674 uinfo->count = 1;
0675 uinfo->value.integer.min = 0;
0676 uinfo->value.integer.max = 1;
0677 return 0;
0678 }
0679
0680 static int wm8958_hpf_get(struct snd_kcontrol *kcontrol,
0681 struct snd_ctl_elem_value *ucontrol)
0682 {
0683 int hpf = kcontrol->private_value;
0684 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0685 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0686
0687 if (hpf < 3)
0688 ucontrol->value.integer.value[0] = wm8994->hpf1_ena[hpf % 3];
0689 else
0690 ucontrol->value.integer.value[0] = wm8994->hpf2_ena[hpf % 3];
0691
0692 return 0;
0693 }
0694
0695 static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
0696 struct snd_ctl_elem_value *ucontrol)
0697 {
0698 int hpf = kcontrol->private_value;
0699 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0700 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0701
0702 if (hpf < 3) {
0703 if (wm8994->hpf1_ena[hpf % 3] ==
0704 ucontrol->value.integer.value[0])
0705 return 0;
0706 } else {
0707 if (wm8994->hpf2_ena[hpf % 3] ==
0708 ucontrol->value.integer.value[0])
0709 return 0;
0710 }
0711
0712 if (ucontrol->value.integer.value[0] > 1)
0713 return -EINVAL;
0714
0715 if (!wm8994->mbc_vss)
0716 return -ENODEV;
0717
0718 if (wm8958_dsp2_busy(wm8994, hpf % 3)) {
0719 dev_dbg(component->dev, "DSP2 active on %d already\n", hpf);
0720 return -EBUSY;
0721 }
0722
0723 if (wm8994->enh_eq_ena[hpf % 3])
0724 return -EBUSY;
0725
0726 if (hpf < 3)
0727 wm8994->hpf1_ena[hpf % 3] = ucontrol->value.integer.value[0];
0728 else
0729 wm8994->hpf2_ena[hpf % 3] = ucontrol->value.integer.value[0];
0730
0731 wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]);
0732
0733 return 1;
0734 }
0735
0736 #define WM8958_HPF_SWITCH(xname, xval) {\
0737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
0738 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
0739 .info = wm8958_hpf_info, \
0740 .get = wm8958_hpf_get, .put = wm8958_hpf_put, \
0741 .private_value = xval }
0742
0743 static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
0744 struct snd_ctl_elem_value *ucontrol)
0745 {
0746 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0747 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0748 struct wm8994 *control = wm8994->wm8994;
0749 int value = ucontrol->value.enumerated.item[0];
0750 int reg;
0751
0752
0753 reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
0754 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
0755 return -EBUSY;
0756
0757 if (value >= control->pdata.num_enh_eq_cfgs)
0758 return -EINVAL;
0759
0760 wm8994->enh_eq_cfg = value;
0761
0762 return 0;
0763 }
0764
0765 static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol,
0766 struct snd_ctl_elem_value *ucontrol)
0767 {
0768 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0769 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0770
0771 ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg;
0772
0773 return 0;
0774 }
0775
0776 static int wm8958_enh_eq_info(struct snd_kcontrol *kcontrol,
0777 struct snd_ctl_elem_info *uinfo)
0778 {
0779 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0780 uinfo->count = 1;
0781 uinfo->value.integer.min = 0;
0782 uinfo->value.integer.max = 1;
0783 return 0;
0784 }
0785
0786 static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol,
0787 struct snd_ctl_elem_value *ucontrol)
0788 {
0789 int eq = kcontrol->private_value;
0790 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0791 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0792
0793 ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq];
0794
0795 return 0;
0796 }
0797
0798 static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
0799 struct snd_ctl_elem_value *ucontrol)
0800 {
0801 int eq = kcontrol->private_value;
0802 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0803 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0804
0805 if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0])
0806 return 0;
0807
0808 if (ucontrol->value.integer.value[0] > 1)
0809 return -EINVAL;
0810
0811 if (!wm8994->enh_eq)
0812 return -ENODEV;
0813
0814 if (wm8958_dsp2_busy(wm8994, eq)) {
0815 dev_dbg(component->dev, "DSP2 active on %d already\n", eq);
0816 return -EBUSY;
0817 }
0818
0819 if (wm8994->mbc_ena[eq] || wm8994->vss_ena[eq] ||
0820 wm8994->hpf1_ena[eq] || wm8994->hpf2_ena[eq])
0821 return -EBUSY;
0822
0823 wm8994->enh_eq_ena[eq] = ucontrol->value.integer.value[0];
0824
0825 wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]);
0826
0827 return 1;
0828 }
0829
0830 #define WM8958_ENH_EQ_SWITCH(xname, xval) {\
0831 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
0832 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
0833 .info = wm8958_enh_eq_info, \
0834 .get = wm8958_enh_eq_get, .put = wm8958_enh_eq_put, \
0835 .private_value = xval }
0836
0837 static const struct snd_kcontrol_new wm8958_mbc_snd_controls[] = {
0838 WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0),
0839 WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1),
0840 WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2),
0841 };
0842
0843 static const struct snd_kcontrol_new wm8958_vss_snd_controls[] = {
0844 WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0),
0845 WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1),
0846 WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2),
0847 WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0),
0848 WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1),
0849 WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2),
0850 WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3),
0851 WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4),
0852 WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5),
0853 };
0854
0855 static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls[] = {
0856 WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0),
0857 WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1),
0858 WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2),
0859 };
0860
0861 static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context)
0862 {
0863 struct snd_soc_component *component = context;
0864 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0865
0866 if (fw && (wm8958_dsp2_fw(component, "ENH_EQ", fw, true) == 0)) {
0867 mutex_lock(&wm8994->fw_lock);
0868 wm8994->enh_eq = fw;
0869 mutex_unlock(&wm8994->fw_lock);
0870 }
0871 }
0872
0873 static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
0874 {
0875 struct snd_soc_component *component = context;
0876 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0877
0878 if (fw && (wm8958_dsp2_fw(component, "MBC+VSS", fw, true) == 0)) {
0879 mutex_lock(&wm8994->fw_lock);
0880 wm8994->mbc_vss = fw;
0881 mutex_unlock(&wm8994->fw_lock);
0882 }
0883 }
0884
0885 static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
0886 {
0887 struct snd_soc_component *component = context;
0888 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0889
0890 if (fw && (wm8958_dsp2_fw(component, "MBC", fw, true) == 0)) {
0891 mutex_lock(&wm8994->fw_lock);
0892 wm8994->mbc = fw;
0893 mutex_unlock(&wm8994->fw_lock);
0894 }
0895 }
0896
0897 void wm8958_dsp2_init(struct snd_soc_component *component)
0898 {
0899 struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
0900 struct wm8994 *control = wm8994->wm8994;
0901 struct wm8994_pdata *pdata = &control->pdata;
0902 int ret, i;
0903
0904 wm8994->dsp_active = -1;
0905
0906 snd_soc_add_component_controls(component, wm8958_mbc_snd_controls,
0907 ARRAY_SIZE(wm8958_mbc_snd_controls));
0908 snd_soc_add_component_controls(component, wm8958_vss_snd_controls,
0909 ARRAY_SIZE(wm8958_vss_snd_controls));
0910 snd_soc_add_component_controls(component, wm8958_enh_eq_snd_controls,
0911 ARRAY_SIZE(wm8958_enh_eq_snd_controls));
0912
0913
0914
0915 request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
0916 "wm8958_mbc.wfw", component->dev, GFP_KERNEL,
0917 component, wm8958_mbc_loaded);
0918 request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
0919 "wm8958_mbc_vss.wfw", component->dev, GFP_KERNEL,
0920 component, wm8958_mbc_vss_loaded);
0921 request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
0922 "wm8958_enh_eq.wfw", component->dev, GFP_KERNEL,
0923 component, wm8958_enh_eq_loaded);
0924
0925 if (pdata->num_mbc_cfgs) {
0926 struct snd_kcontrol_new mbc_control[] = {
0927 SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum,
0928 wm8958_get_mbc_enum, wm8958_put_mbc_enum),
0929 };
0930
0931
0932 wm8994->mbc_texts = kmalloc_array(pdata->num_mbc_cfgs,
0933 sizeof(char *),
0934 GFP_KERNEL);
0935 if (!wm8994->mbc_texts)
0936 return;
0937
0938 for (i = 0; i < pdata->num_mbc_cfgs; i++)
0939 wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
0940
0941 wm8994->mbc_enum.items = pdata->num_mbc_cfgs;
0942 wm8994->mbc_enum.texts = wm8994->mbc_texts;
0943
0944 ret = snd_soc_add_component_controls(wm8994->hubs.component,
0945 mbc_control, 1);
0946 if (ret != 0)
0947 dev_err(wm8994->hubs.component->dev,
0948 "Failed to add MBC mode controls: %d\n", ret);
0949 }
0950
0951 if (pdata->num_vss_cfgs) {
0952 struct snd_kcontrol_new vss_control[] = {
0953 SOC_ENUM_EXT("VSS Mode", wm8994->vss_enum,
0954 wm8958_get_vss_enum, wm8958_put_vss_enum),
0955 };
0956
0957
0958 wm8994->vss_texts = kmalloc_array(pdata->num_vss_cfgs,
0959 sizeof(char *),
0960 GFP_KERNEL);
0961 if (!wm8994->vss_texts)
0962 return;
0963
0964 for (i = 0; i < pdata->num_vss_cfgs; i++)
0965 wm8994->vss_texts[i] = pdata->vss_cfgs[i].name;
0966
0967 wm8994->vss_enum.items = pdata->num_vss_cfgs;
0968 wm8994->vss_enum.texts = wm8994->vss_texts;
0969
0970 ret = snd_soc_add_component_controls(wm8994->hubs.component,
0971 vss_control, 1);
0972 if (ret != 0)
0973 dev_err(wm8994->hubs.component->dev,
0974 "Failed to add VSS mode controls: %d\n", ret);
0975 }
0976
0977 if (pdata->num_vss_hpf_cfgs) {
0978 struct snd_kcontrol_new hpf_control[] = {
0979 SOC_ENUM_EXT("VSS HPF Mode", wm8994->vss_hpf_enum,
0980 wm8958_get_vss_hpf_enum,
0981 wm8958_put_vss_hpf_enum),
0982 };
0983
0984
0985 wm8994->vss_hpf_texts = kmalloc_array(pdata->num_vss_hpf_cfgs,
0986 sizeof(char *),
0987 GFP_KERNEL);
0988 if (!wm8994->vss_hpf_texts)
0989 return;
0990
0991 for (i = 0; i < pdata->num_vss_hpf_cfgs; i++)
0992 wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name;
0993
0994 wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs;
0995 wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
0996
0997 ret = snd_soc_add_component_controls(wm8994->hubs.component,
0998 hpf_control, 1);
0999 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
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 }