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