linux/sound/soc/codecs/wm8958-dsp2.c
<<
>>
Prefs
   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
  39static 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
 181err:
 182        ret = -EINVAL;
 183ok:
 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
 192static 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
 236static 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
 297static 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
 328static 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
 415int 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 */
 438static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif)
 439{
 440        int i;
 441
 442        for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) {
 443                if (i == aif)
 444                        continue;
 445                if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] ||
 446                    wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i])
 447                        return 1;
 448        }
 449
 450        return 0;
 451}
 452
 453static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
 454                               struct snd_ctl_elem_value *ucontrol)
 455{
 456        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 457        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 458        struct wm8994 *control = wm8994->wm8994;
 459        int value = ucontrol->value.enumerated.item[0];
 460        int reg;
 461
 462        /* Don't allow on the fly reconfiguration */
 463        reg = snd_soc_component_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
 475static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
 476                               struct snd_ctl_elem_value *ucontrol)
 477{
 478        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 479        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 480
 481        ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
 482
 483        return 0;
 484}
 485
 486static int wm8958_mbc_info(struct snd_kcontrol *kcontrol,
 487                           struct snd_ctl_elem_info *uinfo)
 488{
 489        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 490        uinfo->count = 1;
 491        uinfo->value.integer.min = 0;
 492        uinfo->value.integer.max = 1;
 493        return 0;
 494}
 495
 496static int wm8958_mbc_get(struct snd_kcontrol *kcontrol,
 497                          struct snd_ctl_elem_value *ucontrol)
 498{
 499        int mbc = kcontrol->private_value;
 500        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 501        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 502
 503        ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc];
 504
 505        return 0;
 506}
 507
 508static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
 509                          struct snd_ctl_elem_value *ucontrol)
 510{
 511        int mbc = kcontrol->private_value;
 512        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 513        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 514
 515        if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0])
 516                return 0;
 517
 518        if (ucontrol->value.integer.value[0] > 1)
 519                return -EINVAL;
 520
 521        if (wm8958_dsp2_busy(wm8994, mbc)) {
 522                dev_dbg(component->dev, "DSP2 active on %d already\n", mbc);
 523                return -EBUSY;
 524        }
 525
 526        if (wm8994->enh_eq_ena[mbc])
 527                return -EBUSY;
 528
 529        wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0];
 530
 531        wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]);
 532
 533        return 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
 543static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
 544                               struct snd_ctl_elem_value *ucontrol)
 545{
 546        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 547        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 548        struct wm8994 *control = wm8994->wm8994;
 549        int value = ucontrol->value.enumerated.item[0];
 550        int reg;
 551
 552        /* Don't allow on the fly reconfiguration */
 553        reg = snd_soc_component_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
 565static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
 566                               struct snd_ctl_elem_value *ucontrol)
 567{
 568        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 569        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 570
 571        ucontrol->value.enumerated.item[0] = wm8994->vss_cfg;
 572
 573        return 0;
 574}
 575
 576static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
 577                                   struct snd_ctl_elem_value *ucontrol)
 578{
 579        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 580        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 581        struct wm8994 *control = wm8994->wm8994;
 582        int value = ucontrol->value.enumerated.item[0];
 583        int reg;
 584
 585        /* Don't allow on the fly reconfiguration */
 586        reg = snd_soc_component_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
 598static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol,
 599                                   struct snd_ctl_elem_value *ucontrol)
 600{
 601        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 602        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 603
 604        ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg;
 605
 606        return 0;
 607}
 608
 609static int wm8958_vss_info(struct snd_kcontrol *kcontrol,
 610                           struct snd_ctl_elem_info *uinfo)
 611{
 612        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 613        uinfo->count = 1;
 614        uinfo->value.integer.min = 0;
 615        uinfo->value.integer.max = 1;
 616        return 0;
 617}
 618
 619static int wm8958_vss_get(struct snd_kcontrol *kcontrol,
 620                          struct snd_ctl_elem_value *ucontrol)
 621{
 622        int vss = kcontrol->private_value;
 623        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 624        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 625
 626        ucontrol->value.integer.value[0] = wm8994->vss_ena[vss];
 627
 628        return 0;
 629}
 630
 631static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
 632                          struct snd_ctl_elem_value *ucontrol)
 633{
 634        int vss = kcontrol->private_value;
 635        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 636        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 637
 638        if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0])
 639                return 0;
 640
 641        if (ucontrol->value.integer.value[0] > 1)
 642                return -EINVAL;
 643
 644        if (!wm8994->mbc_vss)
 645                return -ENODEV;
 646
 647        if (wm8958_dsp2_busy(wm8994, vss)) {
 648                dev_dbg(component->dev, "DSP2 active on %d already\n", vss);
 649                return -EBUSY;
 650        }
 651
 652        if (wm8994->enh_eq_ena[vss])
 653                return -EBUSY;
 654
 655        wm8994->vss_ena[vss] = ucontrol->value.integer.value[0];
 656
 657        wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]);
 658
 659        return 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
 670static int wm8958_hpf_info(struct snd_kcontrol *kcontrol,
 671                           struct snd_ctl_elem_info *uinfo)
 672{
 673        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 674        uinfo->count = 1;
 675        uinfo->value.integer.min = 0;
 676        uinfo->value.integer.max = 1;
 677        return 0;
 678}
 679
 680static int wm8958_hpf_get(struct snd_kcontrol *kcontrol,
 681                          struct snd_ctl_elem_value *ucontrol)
 682{
 683        int hpf = kcontrol->private_value;
 684        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 685        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 686
 687        if (hpf < 3)
 688                ucontrol->value.integer.value[0] = wm8994->hpf1_ena[hpf % 3];
 689        else
 690                ucontrol->value.integer.value[0] = wm8994->hpf2_ena[hpf % 3];
 691
 692        return 0;
 693}
 694
 695static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
 696                          struct snd_ctl_elem_value *ucontrol)
 697{
 698        int hpf = kcontrol->private_value;
 699        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 700        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 701
 702        if (hpf < 3) {
 703                if (wm8994->hpf1_ena[hpf % 3] ==
 704                    ucontrol->value.integer.value[0])
 705                        return 0;
 706        } else {
 707                if (wm8994->hpf2_ena[hpf % 3] ==
 708                    ucontrol->value.integer.value[0])
 709                        return 0;
 710        }
 711
 712        if (ucontrol->value.integer.value[0] > 1)
 713                return -EINVAL;
 714
 715        if (!wm8994->mbc_vss)
 716                return -ENODEV;
 717
 718        if (wm8958_dsp2_busy(wm8994, hpf % 3)) {
 719                dev_dbg(component->dev, "DSP2 active on %d already\n", hpf);
 720                return -EBUSY;
 721        }
 722
 723        if (wm8994->enh_eq_ena[hpf % 3])
 724                return -EBUSY;
 725
 726        if (hpf < 3)
 727                wm8994->hpf1_ena[hpf % 3] = ucontrol->value.integer.value[0];
 728        else
 729                wm8994->hpf2_ena[hpf % 3] = ucontrol->value.integer.value[0];
 730
 731        wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]);
 732
 733        return 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
 743static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
 744                                  struct snd_ctl_elem_value *ucontrol)
 745{
 746        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 747        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 748        struct wm8994 *control = wm8994->wm8994;
 749        int value = ucontrol->value.enumerated.item[0];
 750        int reg;
 751
 752        /* Don't allow on the fly reconfiguration */
 753        reg = snd_soc_component_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
 765static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol,
 766                                  struct snd_ctl_elem_value *ucontrol)
 767{
 768        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 769        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 770
 771        ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg;
 772
 773        return 0;
 774}
 775
 776static int wm8958_enh_eq_info(struct snd_kcontrol *kcontrol,
 777                           struct snd_ctl_elem_info *uinfo)
 778{
 779        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 780        uinfo->count = 1;
 781        uinfo->value.integer.min = 0;
 782        uinfo->value.integer.max = 1;
 783        return 0;
 784}
 785
 786static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol,
 787                          struct snd_ctl_elem_value *ucontrol)
 788{
 789        int eq = kcontrol->private_value;
 790        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 791        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 792
 793        ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq];
 794
 795        return 0;
 796}
 797
 798static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
 799                          struct snd_ctl_elem_value *ucontrol)
 800{
 801        int eq = kcontrol->private_value;
 802        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 803        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 804
 805        if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0])
 806                return 0;
 807
 808        if (ucontrol->value.integer.value[0] > 1)
 809                return -EINVAL;
 810
 811        if (!wm8994->enh_eq)
 812                return -ENODEV;
 813
 814        if (wm8958_dsp2_busy(wm8994, eq)) {
 815                dev_dbg(component->dev, "DSP2 active on %d already\n", eq);
 816                return -EBUSY;
 817        }
 818
 819        if (wm8994->mbc_ena[eq] || wm8994->vss_ena[eq] ||
 820            wm8994->hpf1_ena[eq] || wm8994->hpf2_ena[eq])
 821                return -EBUSY;
 822
 823        wm8994->enh_eq_ena[eq] = ucontrol->value.integer.value[0];
 824
 825        wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]);
 826
 827        return 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
 837static const struct snd_kcontrol_new wm8958_mbc_snd_controls[] = {
 838WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0),
 839WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1),
 840WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2),
 841};
 842
 843static const struct snd_kcontrol_new wm8958_vss_snd_controls[] = {
 844WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0),
 845WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1),
 846WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2),
 847WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0),
 848WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1),
 849WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2),
 850WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3),
 851WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4),
 852WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5),
 853};
 854
 855static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls[] = {
 856WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0),
 857WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1),
 858WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2),
 859};
 860
 861static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context)
 862{
 863        struct snd_soc_component *component = context;
 864        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 865
 866        if (fw && (wm8958_dsp2_fw(component, "ENH_EQ", fw, true) == 0)) {
 867                mutex_lock(&wm8994->fw_lock);
 868                wm8994->enh_eq = fw;
 869                mutex_unlock(&wm8994->fw_lock);
 870        }
 871}
 872
 873static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
 874{
 875        struct snd_soc_component *component = context;
 876        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 877
 878        if (fw && (wm8958_dsp2_fw(component, "MBC+VSS", fw, true) == 0)) {
 879                mutex_lock(&wm8994->fw_lock);
 880                wm8994->mbc_vss = fw;
 881                mutex_unlock(&wm8994->fw_lock);
 882        }
 883}
 884
 885static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
 886{
 887        struct snd_soc_component *component = context;
 888        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 889
 890        if (fw && (wm8958_dsp2_fw(component, "MBC", fw, true) == 0)) {
 891                mutex_lock(&wm8994->fw_lock);
 892                wm8994->mbc = fw;
 893                mutex_unlock(&wm8994->fw_lock);
 894        }
 895}
 896
 897void wm8958_dsp2_init(struct snd_soc_component *component)
 898{
 899        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 900        struct wm8994 *control = wm8994->wm8994;
 901        struct wm8994_pdata *pdata = &control->pdata;
 902        int ret, i;
 903
 904        wm8994->dsp_active = -1;
 905
 906        snd_soc_add_component_controls(component, wm8958_mbc_snd_controls,
 907                             ARRAY_SIZE(wm8958_mbc_snd_controls));
 908        snd_soc_add_component_controls(component, wm8958_vss_snd_controls,
 909                             ARRAY_SIZE(wm8958_vss_snd_controls));
 910        snd_soc_add_component_controls(component, wm8958_enh_eq_snd_controls,
 911                             ARRAY_SIZE(wm8958_enh_eq_snd_controls));
 912
 913
 914        /* We don't *require* firmware and don't want to delay boot */
 915        request_firmware_nowait(THIS_MODULE, FW_ACTION_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}
1033