Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * wm8958-dsp2.c  --  WM8958 DSP2 support
0004  *
0005  * Copyright 2011 Wolfson Microelectronics plc
0006  *
0007  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
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     /* Suppress unneeded downloads */
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             /* Informational text */
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         /* Round up to the next 32 bit word */
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     /* If the DSP is already running then noop */
0195     if (snd_soc_component_read(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA)
0196         return;
0197 
0198     /* If we have MBC firmware download it */
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     /* If we've got user supplied MBC settings use them */
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     /* Run the DSP */
0221     snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
0222               WM8958_DSP2_RUNR);
0223 
0224     /* And we're off! */
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     /* If we've got user supplied settings use them */
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     /* Run the DSP */
0271     snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
0272               WM8958_DSP2_RUNR);
0273 
0274     /* Enable the algorithms we've selected */
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     /* Switch the DSP into the data path */
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     /* If we've got user supplied settings use them */
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     /* Run the DSP */
0315     snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
0316               WM8958_DSP2_RUNR);
0317 
0318     /* Switch the DSP into the data path */
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     /* Do we have both an active AIF and an active algorithm? */
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         /* If the DSP is already running then noop */
0362         if (reg & WM8958_DSP2_ENA)
0363             return;
0364 
0365         /* If either AIFnCLK is not yet enabled postpone */
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         /* Switch the clock over to the appropriate AIF */
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         /* If the DSP is already stopped then noop */
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 /* Check if DSP2 is in use on another AIF */
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     /* Don't allow on the fly reconfiguration */
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     /* Don't allow on the fly reconfiguration */
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     /* Don't allow on the fly reconfiguration */
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     /* Don't allow on the fly reconfiguration */
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     /* We don't *require* firmware and don't want to delay boot */
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         /* We need an array of texts for the enum API */
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         /* We need an array of texts for the enum API */
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         /* We need an array of texts for the enum API */
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         /* 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 }