root/sound/soc/codecs/wm8958-dsp2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wm8958_dsp2_fw
  2. wm8958_dsp_start_mbc
  3. wm8958_dsp_start_vss
  4. wm8958_dsp_start_enh_eq
  5. wm8958_dsp_apply
  6. wm8958_aif_ev
  7. wm8958_dsp2_busy
  8. wm8958_put_mbc_enum
  9. wm8958_get_mbc_enum
  10. wm8958_mbc_info
  11. wm8958_mbc_get
  12. wm8958_mbc_put
  13. wm8958_put_vss_enum
  14. wm8958_get_vss_enum
  15. wm8958_put_vss_hpf_enum
  16. wm8958_get_vss_hpf_enum
  17. wm8958_vss_info
  18. wm8958_vss_get
  19. wm8958_vss_put
  20. wm8958_hpf_info
  21. wm8958_hpf_get
  22. wm8958_hpf_put
  23. wm8958_put_enh_eq_enum
  24. wm8958_get_enh_eq_enum
  25. wm8958_enh_eq_info
  26. wm8958_enh_eq_get
  27. wm8958_enh_eq_put
  28. wm8958_enh_eq_loaded
  29. wm8958_mbc_vss_loaded
  30. wm8958_mbc_loaded
  31. wm8958_dsp2_init

   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 "wm8994.h"
  29 
  30 #define WM_FW_BLOCK_INFO 0xff
  31 #define WM_FW_BLOCK_PM   0x00
  32 #define WM_FW_BLOCK_X    0x01
  33 #define WM_FW_BLOCK_Y    0x02
  34 #define WM_FW_BLOCK_Z    0x03
  35 #define WM_FW_BLOCK_I    0x06
  36 #define WM_FW_BLOCK_A    0x08
  37 #define WM_FW_BLOCK_C    0x0c
  38 
  39 static int wm8958_dsp2_fw(struct snd_soc_component *component, const char *name,
  40                           const struct firmware *fw, bool check)
  41 {
  42         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
  43         u64 data64;
  44         u32 data32;
  45         const u8 *data;
  46         char *str;
  47         size_t block_len, len;
  48         int ret = 0;
  49 
  50         /* Suppress unneeded downloads */
  51         if (wm8994->cur_fw == fw)
  52                 return 0;
  53 
  54         if (fw->size < 32) {
  55                 dev_err(component->dev, "%s: firmware too short (%zd bytes)\n",
  56                         name, fw->size);
  57                 goto err;
  58         }
  59 
  60         if (memcmp(fw->data, "WMFW", 4) != 0) {
  61                 memcpy(&data32, fw->data, sizeof(data32));
  62                 data32 = be32_to_cpu(data32);
  63                 dev_err(component->dev, "%s: firmware has bad file magic %08x\n",
  64                         name, data32);
  65                 goto err;
  66         }
  67 
  68         memcpy(&data32, fw->data + 4, sizeof(data32));
  69         len = be32_to_cpu(data32);
  70 
  71         memcpy(&data32, fw->data + 8, sizeof(data32));
  72         data32 = be32_to_cpu(data32);
  73         if ((data32 >> 24) & 0xff) {
  74                 dev_err(component->dev, "%s: unsupported firmware version %d\n",
  75                         name, (data32 >> 24) & 0xff);
  76                 goto err;
  77         }
  78         if ((data32 & 0xffff) != 8958) {
  79                 dev_err(component->dev, "%s: unsupported target device %d\n",
  80                         name, data32 & 0xffff);
  81                 goto err;
  82         }
  83         if (((data32 >> 16) & 0xff) != 0xc) {
  84                 dev_err(component->dev, "%s: unsupported target core %d\n",
  85                         name, (data32 >> 16) & 0xff);
  86                 goto err;
  87         }
  88 
  89         if (check) {
  90                 memcpy(&data64, fw->data + 24, sizeof(u64));
  91                 dev_info(component->dev, "%s timestamp %llx\n",
  92                          name, be64_to_cpu(data64));
  93         } else {
  94                 snd_soc_component_write(component, 0x102, 0x2);
  95                 snd_soc_component_write(component, 0x900, 0x2);
  96         }
  97 
  98         data = fw->data + len;
  99         len = fw->size - len;
 100         while (len) {
 101                 if (len < 12) {
 102                         dev_err(component->dev, "%s short data block of %zd\n",
 103                                 name, len);
 104                         goto err;
 105                 }
 106 
 107                 memcpy(&data32, data + 4, sizeof(data32));
 108                 block_len = be32_to_cpu(data32);
 109                 if (block_len + 8 > len) {
 110                         dev_err(component->dev, "%zd byte block longer than file\n",
 111                                 block_len);
 112                         goto err;
 113                 }
 114                 if (block_len == 0) {
 115                         dev_err(component->dev, "Zero length block\n");
 116                         goto err;
 117                 }
 118 
 119                 memcpy(&data32, data, sizeof(data32));
 120                 data32 = be32_to_cpu(data32);
 121 
 122                 switch ((data32 >> 24) & 0xff) {
 123                 case WM_FW_BLOCK_INFO:
 124                         /* Informational text */
 125                         if (!check)
 126                                 break;
 127 
 128                         str = kzalloc(block_len + 1, GFP_KERNEL);
 129                         if (str) {
 130                                 memcpy(str, data + 8, block_len);
 131                                 dev_info(component->dev, "%s: %s\n", name, str);
 132                                 kfree(str);
 133                         } else {
 134                                 dev_err(component->dev, "Out of memory\n");
 135                         }
 136                         break;
 137                 case WM_FW_BLOCK_PM:
 138                 case WM_FW_BLOCK_X:
 139                 case WM_FW_BLOCK_Y:
 140                 case WM_FW_BLOCK_Z:
 141                 case WM_FW_BLOCK_I:
 142                 case WM_FW_BLOCK_A:
 143                 case WM_FW_BLOCK_C:
 144                         dev_dbg(component->dev, "%s: %zd bytes of %x@%x\n", name,
 145                                 block_len, (data32 >> 24) & 0xff,
 146                                 data32 & 0xffffff);
 147 
 148                         if (check)
 149                                 break;
 150 
 151                         data32 &= 0xffffff;
 152 
 153                         wm8994_bulk_write(wm8994->wm8994,
 154                                           data32 & 0xffffff,
 155                                           block_len / 2,
 156                                           (void *)(data + 8));
 157 
 158                         break;
 159                 default:
 160                         dev_warn(component->dev, "%s: unknown block type %d\n",
 161                                  name, (data32 >> 24) & 0xff);
 162                         break;
 163                 }
 164 
 165                 /* Round up to the next 32 bit word */
 166                 block_len += block_len % 4;
 167 
 168                 data += block_len + 8;
 169                 len -= block_len + 8;
 170         }
 171 
 172         if (!check) {
 173                 dev_dbg(component->dev, "%s: download done\n", name);
 174                 wm8994->cur_fw = fw;
 175         } else {
 176                 dev_info(component->dev, "%s: got firmware\n", name);
 177         }
 178 
 179         goto ok;
 180 
 181 err:
 182         ret = -EINVAL;
 183 ok:
 184         if (!check) {
 185                 snd_soc_component_write(component, 0x900, 0x0);
 186                 snd_soc_component_write(component, 0x102, 0x0);
 187         }
 188 
 189         return ret;
 190 }
 191 
 192 static void wm8958_dsp_start_mbc(struct snd_soc_component *component, int path)
 193 {
 194         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 195         struct wm8994 *control = wm8994->wm8994;
 196         int i;
 197 
 198         /* If the DSP is already running then noop */
 199         if (snd_soc_component_read32(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA)
 200                 return;
 201 
 202         /* If we have MBC firmware download it */
 203         if (wm8994->mbc)
 204                 wm8958_dsp2_fw(component, "MBC", wm8994->mbc, false);
 205 
 206         snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
 207                             WM8958_DSP2_ENA, WM8958_DSP2_ENA);
 208 
 209         /* If we've got user supplied MBC settings use them */
 210         if (control->pdata.num_mbc_cfgs) {
 211                 struct wm8958_mbc_cfg *cfg
 212                         = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
 213 
 214                 for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
 215                         snd_soc_component_write(component, i + WM8958_MBC_BAND_1_K_1,
 216                                       cfg->coeff_regs[i]);
 217 
 218                 for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++)
 219                         snd_soc_component_write(component,
 220                                       i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1,
 221                                       cfg->cutoff_regs[i]);
 222         }
 223 
 224         /* Run the DSP */
 225         snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
 226                       WM8958_DSP2_RUNR);
 227 
 228         /* And we're off! */
 229         snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
 230                             WM8958_MBC_ENA |
 231                             WM8958_MBC_SEL_MASK,
 232                             path << WM8958_MBC_SEL_SHIFT |
 233                             WM8958_MBC_ENA);
 234 }
 235 
 236 static void wm8958_dsp_start_vss(struct snd_soc_component *component, int path)
 237 {
 238         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 239         struct wm8994 *control = wm8994->wm8994;
 240         int i, ena;
 241 
 242         if (wm8994->mbc_vss)
 243                 wm8958_dsp2_fw(component, "MBC+VSS", wm8994->mbc_vss, false);
 244 
 245         snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
 246                             WM8958_DSP2_ENA, WM8958_DSP2_ENA);
 247 
 248         /* If we've got user supplied settings use them */
 249         if (control->pdata.num_mbc_cfgs) {
 250                 struct wm8958_mbc_cfg *cfg
 251                         = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
 252 
 253                 for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++)
 254                         snd_soc_component_write(component, i + 0x2800,
 255                                       cfg->combined_regs[i]);
 256         }
 257 
 258         if (control->pdata.num_vss_cfgs) {
 259                 struct wm8958_vss_cfg *cfg
 260                         = &control->pdata.vss_cfgs[wm8994->vss_cfg];
 261 
 262                 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
 263                         snd_soc_component_write(component, i + 0x2600, cfg->regs[i]);
 264         }
 265 
 266         if (control->pdata.num_vss_hpf_cfgs) {
 267                 struct wm8958_vss_hpf_cfg *cfg
 268                         = &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg];
 269 
 270                 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
 271                         snd_soc_component_write(component, i + 0x2400, cfg->regs[i]);
 272         }
 273 
 274         /* Run the DSP */
 275         snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
 276                       WM8958_DSP2_RUNR);
 277 
 278         /* Enable the algorithms we've selected */
 279         ena = 0;
 280         if (wm8994->mbc_ena[path])
 281                 ena |= 0x8;
 282         if (wm8994->hpf2_ena[path])
 283                 ena |= 0x4;
 284         if (wm8994->hpf1_ena[path])
 285                 ena |= 0x2;
 286         if (wm8994->vss_ena[path])
 287                 ena |= 0x1;
 288 
 289         snd_soc_component_write(component, 0x2201, ena);
 290 
 291         /* Switch the DSP into the data path */
 292         snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
 293                             WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
 294                             path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
 295 }
 296 
 297 static void wm8958_dsp_start_enh_eq(struct snd_soc_component *component, int path)
 298 {
 299         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 300         struct wm8994 *control = wm8994->wm8994;
 301         int i;
 302 
 303         wm8958_dsp2_fw(component, "ENH_EQ", wm8994->enh_eq, false);
 304 
 305         snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
 306                             WM8958_DSP2_ENA, WM8958_DSP2_ENA);
 307 
 308         /* If we've got user supplied settings use them */
 309         if (control->pdata.num_enh_eq_cfgs) {
 310                 struct wm8958_enh_eq_cfg *cfg
 311                         = &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg];
 312 
 313                 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
 314                         snd_soc_component_write(component, i + 0x2200,
 315                                       cfg->regs[i]);
 316         }
 317 
 318         /* Run the DSP */
 319         snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
 320                       WM8958_DSP2_RUNR);
 321 
 322         /* Switch the DSP into the data path */
 323         snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
 324                             WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
 325                             path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
 326 }
 327 
 328 static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int start)
 329 {
 330         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 331         int pwr_reg = snd_soc_component_read32(component, WM8994_POWER_MANAGEMENT_5);
 332         int ena, reg, aif;
 333 
 334         switch (path) {
 335         case 0:
 336                 pwr_reg &= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA);
 337                 aif = 0;
 338                 break;
 339         case 1:
 340                 pwr_reg &= (WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
 341                 aif = 0;
 342                 break;
 343         case 2:
 344                 pwr_reg &= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA);
 345                 aif = 1;
 346                 break;
 347         default:
 348                 WARN(1, "Invalid path %d\n", path);
 349                 return;
 350         }
 351 
 352         /* Do we have both an active AIF and an active algorithm? */
 353         ena = wm8994->mbc_ena[path] || wm8994->vss_ena[path] ||
 354                 wm8994->hpf1_ena[path] || wm8994->hpf2_ena[path] ||
 355                 wm8994->enh_eq_ena[path];
 356         if (!pwr_reg)
 357                 ena = 0;
 358 
 359         reg = snd_soc_component_read32(component, WM8958_DSP2_PROGRAM);
 360 
 361         dev_dbg(component->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n",
 362                 path, wm8994->dsp_active, start, pwr_reg, reg);
 363 
 364         if (start && ena) {
 365                 /* If the DSP is already running then noop */
 366                 if (reg & WM8958_DSP2_ENA)
 367                         return;
 368 
 369                 /* If either AIFnCLK is not yet enabled postpone */
 370                 if (!(snd_soc_component_read32(component, WM8994_AIF1_CLOCKING_1)
 371                       & WM8994_AIF1CLK_ENA_MASK) &&
 372                     !(snd_soc_component_read32(component, WM8994_AIF2_CLOCKING_1)
 373                       & WM8994_AIF2CLK_ENA_MASK))
 374                         return;
 375 
 376                 /* Switch the clock over to the appropriate AIF */
 377                 snd_soc_component_update_bits(component, WM8994_CLOCKING_1,
 378                                     WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA,
 379                                     aif << WM8958_DSP2CLK_SRC_SHIFT |
 380                                     WM8958_DSP2CLK_ENA);
 381 
 382                 if (wm8994->enh_eq_ena[path])
 383                         wm8958_dsp_start_enh_eq(component, path);
 384                 else if (wm8994->vss_ena[path] || wm8994->hpf1_ena[path] ||
 385                     wm8994->hpf2_ena[path])
 386                         wm8958_dsp_start_vss(component, path);
 387                 else if (wm8994->mbc_ena[path])
 388                         wm8958_dsp_start_mbc(component, path);
 389 
 390                 wm8994->dsp_active = path;
 391 
 392                 dev_dbg(component->dev, "DSP running in path %d\n", path);
 393         }
 394 
 395         if (!start && wm8994->dsp_active == path) {
 396                 /* If the DSP is already stopped then noop */
 397                 if (!(reg & WM8958_DSP2_ENA))
 398                         return;
 399 
 400                 snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
 401                                     WM8958_MBC_ENA, 0); 
 402                 snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
 403                               WM8958_DSP2_STOP);
 404                 snd_soc_component_update_bits(component, WM8958_DSP2_PROGRAM,
 405                                     WM8958_DSP2_ENA, 0);
 406                 snd_soc_component_update_bits(component, WM8994_CLOCKING_1,
 407                                     WM8958_DSP2CLK_ENA, 0);
 408 
 409                 wm8994->dsp_active = -1;
 410 
 411                 dev_dbg(component->dev, "DSP stopped\n");
 412         }
 413 }
 414 
 415 int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
 416                   struct snd_kcontrol *kcontrol, int event)
 417 {
 418         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 419         int i;
 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 */
 438 static 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 
 453 static 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_read32(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 
 475 static 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 
 486 static 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 
 496 static 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 
 508 static 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 0;
 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 
 543 static 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_read32(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 
 565 static 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 
 576 static 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_read32(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 
 598 static 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 
 609 static 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 
 619 static 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 
 631 static 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 0;
 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 
 670 static 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 
 680 static 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 
 695 static 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 0;
 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 
 743 static 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_read32(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 
 765 static 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 
 776 static 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 
 786 static 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 
 798 static 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 0;
 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 
 837 static const struct snd_kcontrol_new wm8958_mbc_snd_controls[] = {
 838 WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0),
 839 WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1),
 840 WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2),
 841 };
 842 
 843 static const struct snd_kcontrol_new wm8958_vss_snd_controls[] = {
 844 WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0),
 845 WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1),
 846 WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2),
 847 WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0),
 848 WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1),
 849 WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2),
 850 WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3),
 851 WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4),
 852 WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5),
 853 };
 854 
 855 static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls[] = {
 856 WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0),
 857 WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1),
 858 WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2),
 859 };
 860 
 861 static 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 
 873 static 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 
 885 static 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 
 897 void 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_HOTPLUG,
 916                                 "wm8958_mbc.wfw", component->dev, GFP_KERNEL,
 917                                 component, wm8958_mbc_loaded);
 918         request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
 919                                 "wm8958_mbc_vss.wfw", component->dev, GFP_KERNEL,
 920                                 component, wm8958_mbc_vss_loaded);
 921         request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
 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 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                                                  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 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                                                  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 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                                                  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 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                                                  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 }

/* [<][>][^][v][top][bottom][index][help] */