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