powerpc/perf/hv-24x7: Move cpumask file to top folder of hv-24x7 driver
[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         int i;
416
417         switch (event) {
418         case SND_SOC_DAPM_POST_PMU:
419         case SND_SOC_DAPM_PRE_PMU:
420                 for (i = 0; i < 3; i++)
421                         wm8958_dsp_apply(component, i, 1);
422                 break;
423         case SND_SOC_DAPM_POST_PMD:
424         case SND_SOC_DAPM_PRE_PMD:
425                 for (i = 0; i < 3; i++)
426                         wm8958_dsp_apply(component, i, 0);
427                 break;
428         }
429
430         return 0;
431 }
432
433 /* Check if DSP2 is in use on another AIF */
434 static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif)
435 {
436         int i;
437
438         for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) {
439                 if (i == aif)
440                         continue;
441                 if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] ||
442                     wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i])
443                         return 1;
444         }
445
446         return 0;
447 }
448
449 static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
450                                struct snd_ctl_elem_value *ucontrol)
451 {
452         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
453         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
454         struct wm8994 *control = wm8994->wm8994;
455         int value = ucontrol->value.enumerated.item[0];
456         int reg;
457
458         /* Don't allow on the fly reconfiguration */
459         reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
460         if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
461                 return -EBUSY;
462
463         if (value >= control->pdata.num_mbc_cfgs)
464                 return -EINVAL;
465
466         wm8994->mbc_cfg = value;
467
468         return 0;
469 }
470
471 static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
472                                struct snd_ctl_elem_value *ucontrol)
473 {
474         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
475         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
476
477         ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
478
479         return 0;
480 }
481
482 static int wm8958_mbc_info(struct snd_kcontrol *kcontrol,
483                            struct snd_ctl_elem_info *uinfo)
484 {
485         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
486         uinfo->count = 1;
487         uinfo->value.integer.min = 0;
488         uinfo->value.integer.max = 1;
489         return 0;
490 }
491
492 static int wm8958_mbc_get(struct snd_kcontrol *kcontrol,
493                           struct snd_ctl_elem_value *ucontrol)
494 {
495         int mbc = kcontrol->private_value;
496         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
497         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
498
499         ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc];
500
501         return 0;
502 }
503
504 static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
505                           struct snd_ctl_elem_value *ucontrol)
506 {
507         int mbc = kcontrol->private_value;
508         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
509         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
510
511         if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0])
512                 return 0;
513
514         if (ucontrol->value.integer.value[0] > 1)
515                 return -EINVAL;
516
517         if (wm8958_dsp2_busy(wm8994, mbc)) {
518                 dev_dbg(component->dev, "DSP2 active on %d already\n", mbc);
519                 return -EBUSY;
520         }
521
522         if (wm8994->enh_eq_ena[mbc])
523                 return -EBUSY;
524
525         wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0];
526
527         wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]);
528
529         return 0;
530 }
531
532 #define WM8958_MBC_SWITCH(xname, xval) {\
533         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
534         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
535         .info = wm8958_mbc_info, \
536         .get = wm8958_mbc_get, .put = wm8958_mbc_put, \
537         .private_value = xval }
538
539 static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
540                                struct snd_ctl_elem_value *ucontrol)
541 {
542         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
543         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
544         struct wm8994 *control = wm8994->wm8994;
545         int value = ucontrol->value.enumerated.item[0];
546         int reg;
547
548         /* Don't allow on the fly reconfiguration */
549         reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
550         if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
551                 return -EBUSY;
552
553         if (value >= control->pdata.num_vss_cfgs)
554                 return -EINVAL;
555
556         wm8994->vss_cfg = value;
557
558         return 0;
559 }
560
561 static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
562                                struct snd_ctl_elem_value *ucontrol)
563 {
564         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
565         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
566
567         ucontrol->value.enumerated.item[0] = wm8994->vss_cfg;
568
569         return 0;
570 }
571
572 static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
573                                    struct snd_ctl_elem_value *ucontrol)
574 {
575         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
576         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
577         struct wm8994 *control = wm8994->wm8994;
578         int value = ucontrol->value.enumerated.item[0];
579         int reg;
580
581         /* Don't allow on the fly reconfiguration */
582         reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
583         if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
584                 return -EBUSY;
585
586         if (value >= control->pdata.num_vss_hpf_cfgs)
587                 return -EINVAL;
588
589         wm8994->vss_hpf_cfg = value;
590
591         return 0;
592 }
593
594 static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol,
595                                    struct snd_ctl_elem_value *ucontrol)
596 {
597         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
598         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
599
600         ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg;
601
602         return 0;
603 }
604
605 static int wm8958_vss_info(struct snd_kcontrol *kcontrol,
606                            struct snd_ctl_elem_info *uinfo)
607 {
608         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
609         uinfo->count = 1;
610         uinfo->value.integer.min = 0;
611         uinfo->value.integer.max = 1;
612         return 0;
613 }
614
615 static int wm8958_vss_get(struct snd_kcontrol *kcontrol,
616                           struct snd_ctl_elem_value *ucontrol)
617 {
618         int vss = kcontrol->private_value;
619         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
620         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
621
622         ucontrol->value.integer.value[0] = wm8994->vss_ena[vss];
623
624         return 0;
625 }
626
627 static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
628                           struct snd_ctl_elem_value *ucontrol)
629 {
630         int vss = kcontrol->private_value;
631         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
632         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
633
634         if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0])
635                 return 0;
636
637         if (ucontrol->value.integer.value[0] > 1)
638                 return -EINVAL;
639
640         if (!wm8994->mbc_vss)
641                 return -ENODEV;
642
643         if (wm8958_dsp2_busy(wm8994, vss)) {
644                 dev_dbg(component->dev, "DSP2 active on %d already\n", vss);
645                 return -EBUSY;
646         }
647
648         if (wm8994->enh_eq_ena[vss])
649                 return -EBUSY;
650
651         wm8994->vss_ena[vss] = ucontrol->value.integer.value[0];
652
653         wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]);
654
655         return 0;
656 }
657
658
659 #define WM8958_VSS_SWITCH(xname, xval) {\
660         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
661         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
662         .info = wm8958_vss_info, \
663         .get = wm8958_vss_get, .put = wm8958_vss_put, \
664         .private_value = xval }
665
666 static int wm8958_hpf_info(struct snd_kcontrol *kcontrol,
667                            struct snd_ctl_elem_info *uinfo)
668 {
669         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
670         uinfo->count = 1;
671         uinfo->value.integer.min = 0;
672         uinfo->value.integer.max = 1;
673         return 0;
674 }
675
676 static int wm8958_hpf_get(struct snd_kcontrol *kcontrol,
677                           struct snd_ctl_elem_value *ucontrol)
678 {
679         int hpf = kcontrol->private_value;
680         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
681         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
682
683         if (hpf < 3)
684                 ucontrol->value.integer.value[0] = wm8994->hpf1_ena[hpf % 3];
685         else
686                 ucontrol->value.integer.value[0] = wm8994->hpf2_ena[hpf % 3];
687
688         return 0;
689 }
690
691 static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
692                           struct snd_ctl_elem_value *ucontrol)
693 {
694         int hpf = kcontrol->private_value;
695         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
696         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
697
698         if (hpf < 3) {
699                 if (wm8994->hpf1_ena[hpf % 3] ==
700                     ucontrol->value.integer.value[0])
701                         return 0;
702         } else {
703                 if (wm8994->hpf2_ena[hpf % 3] ==
704                     ucontrol->value.integer.value[0])
705                         return 0;
706         }
707
708         if (ucontrol->value.integer.value[0] > 1)
709                 return -EINVAL;
710
711         if (!wm8994->mbc_vss)
712                 return -ENODEV;
713
714         if (wm8958_dsp2_busy(wm8994, hpf % 3)) {
715                 dev_dbg(component->dev, "DSP2 active on %d already\n", hpf);
716                 return -EBUSY;
717         }
718
719         if (wm8994->enh_eq_ena[hpf % 3])
720                 return -EBUSY;
721
722         if (hpf < 3)
723                 wm8994->hpf1_ena[hpf % 3] = ucontrol->value.integer.value[0];
724         else
725                 wm8994->hpf2_ena[hpf % 3] = ucontrol->value.integer.value[0];
726
727         wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]);
728
729         return 0;
730 }
731
732 #define WM8958_HPF_SWITCH(xname, xval) {\
733         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
734         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
735         .info = wm8958_hpf_info, \
736         .get = wm8958_hpf_get, .put = wm8958_hpf_put, \
737         .private_value = xval }
738
739 static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
740                                   struct snd_ctl_elem_value *ucontrol)
741 {
742         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
743         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
744         struct wm8994 *control = wm8994->wm8994;
745         int value = ucontrol->value.enumerated.item[0];
746         int reg;
747
748         /* Don't allow on the fly reconfiguration */
749         reg = snd_soc_component_read(component, WM8994_CLOCKING_1);
750         if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
751                 return -EBUSY;
752
753         if (value >= control->pdata.num_enh_eq_cfgs)
754                 return -EINVAL;
755
756         wm8994->enh_eq_cfg = value;
757
758         return 0;
759 }
760
761 static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol,
762                                   struct snd_ctl_elem_value *ucontrol)
763 {
764         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
765         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
766
767         ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg;
768
769         return 0;
770 }
771
772 static int wm8958_enh_eq_info(struct snd_kcontrol *kcontrol,
773                            struct snd_ctl_elem_info *uinfo)
774 {
775         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
776         uinfo->count = 1;
777         uinfo->value.integer.min = 0;
778         uinfo->value.integer.max = 1;
779         return 0;
780 }
781
782 static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol,
783                           struct snd_ctl_elem_value *ucontrol)
784 {
785         int eq = kcontrol->private_value;
786         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
787         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
788
789         ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq];
790
791         return 0;
792 }
793
794 static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
795                           struct snd_ctl_elem_value *ucontrol)
796 {
797         int eq = kcontrol->private_value;
798         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
799         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
800
801         if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0])
802                 return 0;
803
804         if (ucontrol->value.integer.value[0] > 1)
805                 return -EINVAL;
806
807         if (!wm8994->enh_eq)
808                 return -ENODEV;
809
810         if (wm8958_dsp2_busy(wm8994, eq)) {
811                 dev_dbg(component->dev, "DSP2 active on %d already\n", eq);
812                 return -EBUSY;
813         }
814
815         if (wm8994->mbc_ena[eq] || wm8994->vss_ena[eq] ||
816             wm8994->hpf1_ena[eq] || wm8994->hpf2_ena[eq])
817                 return -EBUSY;
818
819         wm8994->enh_eq_ena[eq] = ucontrol->value.integer.value[0];
820
821         wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]);
822
823         return 0;
824 }
825
826 #define WM8958_ENH_EQ_SWITCH(xname, xval) {\
827         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
828         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
829         .info = wm8958_enh_eq_info, \
830         .get = wm8958_enh_eq_get, .put = wm8958_enh_eq_put, \
831         .private_value = xval }
832
833 static const struct snd_kcontrol_new wm8958_mbc_snd_controls[] = {
834 WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0),
835 WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1),
836 WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2),
837 };
838
839 static const struct snd_kcontrol_new wm8958_vss_snd_controls[] = {
840 WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0),
841 WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1),
842 WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2),
843 WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0),
844 WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1),
845 WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2),
846 WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3),
847 WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4),
848 WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5),
849 };
850
851 static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls[] = {
852 WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0),
853 WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1),
854 WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2),
855 };
856
857 static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context)
858 {
859         struct snd_soc_component *component = context;
860         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
861
862         if (fw && (wm8958_dsp2_fw(component, "ENH_EQ", fw, true) == 0)) {
863                 mutex_lock(&wm8994->fw_lock);
864                 wm8994->enh_eq = fw;
865                 mutex_unlock(&wm8994->fw_lock);
866         }
867 }
868
869 static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
870 {
871         struct snd_soc_component *component = context;
872         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
873
874         if (fw && (wm8958_dsp2_fw(component, "MBC+VSS", fw, true) == 0)) {
875                 mutex_lock(&wm8994->fw_lock);
876                 wm8994->mbc_vss = fw;
877                 mutex_unlock(&wm8994->fw_lock);
878         }
879 }
880
881 static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
882 {
883         struct snd_soc_component *component = context;
884         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
885
886         if (fw && (wm8958_dsp2_fw(component, "MBC", fw, true) == 0)) {
887                 mutex_lock(&wm8994->fw_lock);
888                 wm8994->mbc = fw;
889                 mutex_unlock(&wm8994->fw_lock);
890         }
891 }
892
893 void wm8958_dsp2_init(struct snd_soc_component *component)
894 {
895         struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
896         struct wm8994 *control = wm8994->wm8994;
897         struct wm8994_pdata *pdata = &control->pdata;
898         int ret, i;
899
900         wm8994->dsp_active = -1;
901
902         snd_soc_add_component_controls(component, wm8958_mbc_snd_controls,
903                              ARRAY_SIZE(wm8958_mbc_snd_controls));
904         snd_soc_add_component_controls(component, wm8958_vss_snd_controls,
905                              ARRAY_SIZE(wm8958_vss_snd_controls));
906         snd_soc_add_component_controls(component, wm8958_enh_eq_snd_controls,
907                              ARRAY_SIZE(wm8958_enh_eq_snd_controls));
908
909
910         /* We don't *require* firmware and don't want to delay boot */
911         request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
912                                 "wm8958_mbc.wfw", component->dev, GFP_KERNEL,
913                                 component, wm8958_mbc_loaded);
914         request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
915                                 "wm8958_mbc_vss.wfw", component->dev, GFP_KERNEL,
916                                 component, wm8958_mbc_vss_loaded);
917         request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
918                                 "wm8958_enh_eq.wfw", component->dev, GFP_KERNEL,
919                                 component, wm8958_enh_eq_loaded);
920
921         if (pdata->num_mbc_cfgs) {
922                 struct snd_kcontrol_new control[] = {
923                         SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum,
924                                      wm8958_get_mbc_enum, wm8958_put_mbc_enum),
925                 };
926
927                 /* We need an array of texts for the enum API */
928                 wm8994->mbc_texts = kmalloc_array(pdata->num_mbc_cfgs,
929                                                   sizeof(char *),
930                                                   GFP_KERNEL);
931                 if (!wm8994->mbc_texts)
932                         return;
933
934                 for (i = 0; i < pdata->num_mbc_cfgs; i++)
935                         wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
936
937                 wm8994->mbc_enum.items = pdata->num_mbc_cfgs;
938                 wm8994->mbc_enum.texts = wm8994->mbc_texts;
939
940                 ret = snd_soc_add_component_controls(wm8994->hubs.component,
941                                                  control, 1);
942                 if (ret != 0)
943                         dev_err(wm8994->hubs.component->dev,
944                                 "Failed to add MBC mode controls: %d\n", ret);
945         }
946
947         if (pdata->num_vss_cfgs) {
948                 struct snd_kcontrol_new control[] = {
949                         SOC_ENUM_EXT("VSS Mode", wm8994->vss_enum,
950                                      wm8958_get_vss_enum, wm8958_put_vss_enum),
951                 };
952
953                 /* We need an array of texts for the enum API */
954                 wm8994->vss_texts = kmalloc_array(pdata->num_vss_cfgs,
955                                                   sizeof(char *),
956                                                   GFP_KERNEL);
957                 if (!wm8994->vss_texts)
958                         return;
959
960                 for (i = 0; i < pdata->num_vss_cfgs; i++)
961                         wm8994->vss_texts[i] = pdata->vss_cfgs[i].name;
962
963                 wm8994->vss_enum.items = pdata->num_vss_cfgs;
964                 wm8994->vss_enum.texts = wm8994->vss_texts;
965
966                 ret = snd_soc_add_component_controls(wm8994->hubs.component,
967                                                  control, 1);
968                 if (ret != 0)
969                         dev_err(wm8994->hubs.component->dev,
970                                 "Failed to add VSS mode controls: %d\n", ret);
971         }
972
973         if (pdata->num_vss_hpf_cfgs) {
974                 struct snd_kcontrol_new control[] = {
975                         SOC_ENUM_EXT("VSS HPF Mode", wm8994->vss_hpf_enum,
976                                      wm8958_get_vss_hpf_enum,
977                                      wm8958_put_vss_hpf_enum),
978                 };
979
980                 /* We need an array of texts for the enum API */
981                 wm8994->vss_hpf_texts = kmalloc_array(pdata->num_vss_hpf_cfgs,
982                                                       sizeof(char *),
983                                                       GFP_KERNEL);
984                 if (!wm8994->vss_hpf_texts)
985                         return;
986
987                 for (i = 0; i < pdata->num_vss_hpf_cfgs; i++)
988                         wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name;
989
990                 wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs;
991                 wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
992
993                 ret = snd_soc_add_component_controls(wm8994->hubs.component,
994                                                  control, 1);
995                 if (ret != 0)
996                         dev_err(wm8994->hubs.component->dev,
997                                 "Failed to add VSS HPFmode controls: %d\n",
998                                 ret);
999         }
1000
1001         if (pdata->num_enh_eq_cfgs) {
1002                 struct snd_kcontrol_new control[] = {
1003                         SOC_ENUM_EXT("Enhanced EQ Mode", wm8994->enh_eq_enum,
1004                                      wm8958_get_enh_eq_enum,
1005                                      wm8958_put_enh_eq_enum),
1006                 };
1007
1008                 /* We need an array of texts for the enum API */
1009                 wm8994->enh_eq_texts = kmalloc_array(pdata->num_enh_eq_cfgs,
1010                                                      sizeof(char *),
1011                                                      GFP_KERNEL);
1012                 if (!wm8994->enh_eq_texts)
1013                         return;
1014
1015                 for (i = 0; i < pdata->num_enh_eq_cfgs; i++)
1016                         wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name;
1017
1018                 wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs;
1019                 wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
1020
1021                 ret = snd_soc_add_component_controls(wm8994->hubs.component,
1022                                                  control, 1);
1023                 if (ret != 0)
1024                         dev_err(wm8994->hubs.component->dev,
1025                                 "Failed to add enhanced EQ controls: %d\n",
1026                                 ret);
1027         }
1028 }