2 * wm8958-dsp2.c -- WM8958 DSP2 support
4 * Copyright 2011 Wolfson Microelectronics plc
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
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.
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/init.h>
16 #include <linux/delay.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>
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>
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
42 static int wm8958_dsp2_fw(struct snd_soc_codec
*codec
, const char *name
,
43 const struct firmware
*fw
, bool check
)
45 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
50 size_t block_len
, len
;
53 /* Suppress unneeded downloads */
54 if (wm8994
->cur_fw
== fw
)
58 dev_err(codec
->dev
, "%s: firmware too short (%d bytes)\n",
63 if (memcmp(fw
->data
, "WMFW", 4) != 0) {
64 dev_err(codec
->dev
, "%s: firmware has bad file magic %08x\n",
69 memcpy(&data32
, fw
->data
+ 4, sizeof(data32
));
70 len
= be32_to_cpu(data32
);
72 memcpy(&data32
, fw
->data
+ 8, sizeof(data32
));
73 data32
= be32_to_cpu(data32
);
74 if ((data32
>> 24) & 0xff) {
75 dev_err(codec
->dev
, "%s: unsupported firmware version %d\n",
76 name
, (data32
>> 24) & 0xff);
79 if ((data32
& 0xffff) != 8958) {
80 dev_err(codec
->dev
, "%s: unsupported target device %d\n",
81 name
, data32
& 0xffff);
84 if (((data32
>> 16) & 0xff) != 0xc) {
85 dev_err(codec
->dev
, "%s: unsupported target core %d\n",
86 name
, (data32
>> 16) & 0xff);
91 memcpy(&data64
, fw
->data
+ 24, sizeof(u64
));
92 dev_info(codec
->dev
, "%s timestamp %llx\n",
93 name
, be64_to_cpu(data64
));
95 snd_soc_write(codec
, 0x102, 0x2);
96 snd_soc_write(codec
, 0x900, 0x2);
99 data
= fw
->data
+ len
;
100 len
= fw
->size
- len
;
103 dev_err(codec
->dev
, "%s short data block of %zd\n",
108 memcpy(&data32
, data
+ 4, sizeof(data32
));
109 block_len
= be32_to_cpu(data32
);
110 if (block_len
+ 8 > len
) {
111 dev_err(codec
->dev
, "%zd byte block longer than file\n",
115 if (block_len
== 0) {
116 dev_err(codec
->dev
, "Zero length block\n");
120 memcpy(&data32
, data
, sizeof(data32
));
121 data32
= be32_to_cpu(data32
);
123 switch ((data32
>> 24) & 0xff) {
124 case WM_FW_BLOCK_INFO
:
125 /* Informational text */
129 str
= kzalloc(block_len
+ 1, GFP_KERNEL
);
131 memcpy(str
, data
+ 8, block_len
);
132 dev_info(codec
->dev
, "%s: %s\n", name
, str
);
135 dev_err(codec
->dev
, "Out of memory\n");
145 dev_dbg(codec
->dev
, "%s: %zd bytes of %x@%x\n", name
,
146 block_len
, (data32
>> 24) & 0xff,
154 wm8994_bulk_write(codec
->control_data
,
161 dev_warn(codec
->dev
, "%s: unknown block type %d\n",
162 name
, (data32
>> 24) & 0xff);
166 /* Round up to the next 32 bit word */
167 block_len
+= block_len
% 4;
169 data
+= block_len
+ 8;
170 len
-= block_len
+ 8;
174 dev_dbg(codec
->dev
, "%s: download done\n", name
);
177 dev_info(codec
->dev
, "%s: got firmware\n", name
);
186 snd_soc_write(codec
, 0x900, 0x0);
187 snd_soc_write(codec
, 0x102, 0x0);
193 static void wm8958_dsp_start_mbc(struct snd_soc_codec
*codec
, int path
)
195 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
196 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
199 /* If the DSP is already running then noop */
200 if (snd_soc_read(codec
, WM8958_DSP2_PROGRAM
) & WM8958_DSP2_ENA
)
203 /* If we have MBC firmware download it */
205 wm8958_dsp2_fw(codec
, "MBC", wm8994
->mbc
, false);
207 snd_soc_update_bits(codec
, WM8958_DSP2_PROGRAM
,
208 WM8958_DSP2_ENA
, WM8958_DSP2_ENA
);
210 /* If we've got user supplied MBC settings use them */
211 if (pdata
&& pdata
->num_mbc_cfgs
) {
212 struct wm8958_mbc_cfg
*cfg
213 = &pdata
->mbc_cfgs
[wm8994
->mbc_cfg
];
215 for (i
= 0; i
< ARRAY_SIZE(cfg
->coeff_regs
); i
++)
216 snd_soc_write(codec
, i
+ WM8958_MBC_BAND_1_K_1
,
219 for (i
= 0; i
< ARRAY_SIZE(cfg
->cutoff_regs
); i
++)
221 i
+ WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1
,
222 cfg
->cutoff_regs
[i
]);
226 snd_soc_write(codec
, WM8958_DSP2_EXECCONTROL
,
230 snd_soc_update_bits(codec
, WM8958_DSP2_CONFIG
,
233 path
<< WM8958_MBC_SEL_SHIFT
|
237 static void wm8958_dsp_start_vss(struct snd_soc_codec
*codec
, int path
)
239 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
240 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
244 wm8958_dsp2_fw(codec
, "MBC+VSS", wm8994
->mbc_vss
, false);
246 snd_soc_update_bits(codec
, WM8958_DSP2_PROGRAM
,
247 WM8958_DSP2_ENA
, WM8958_DSP2_ENA
);
249 /* If we've got user supplied settings use them */
250 if (pdata
&& pdata
->num_mbc_cfgs
) {
251 struct wm8958_mbc_cfg
*cfg
252 = &pdata
->mbc_cfgs
[wm8994
->mbc_cfg
];
254 for (i
= 0; i
< ARRAY_SIZE(cfg
->combined_regs
); i
++)
255 snd_soc_write(codec
, i
+ 0x2800,
256 cfg
->combined_regs
[i
]);
259 if (pdata
&& pdata
->num_vss_cfgs
) {
260 struct wm8958_vss_cfg
*cfg
261 = &pdata
->vss_cfgs
[wm8994
->vss_cfg
];
263 for (i
= 0; i
< ARRAY_SIZE(cfg
->regs
); i
++)
264 snd_soc_write(codec
, i
+ 0x2600, cfg
->regs
[i
]);
267 if (pdata
&& pdata
->num_vss_hpf_cfgs
) {
268 struct wm8958_vss_hpf_cfg
*cfg
269 = &pdata
->vss_hpf_cfgs
[wm8994
->vss_hpf_cfg
];
271 for (i
= 0; i
< ARRAY_SIZE(cfg
->regs
); i
++)
272 snd_soc_write(codec
, i
+ 0x2400, cfg
->regs
[i
]);
276 snd_soc_write(codec
, WM8958_DSP2_EXECCONTROL
,
279 /* Enable the algorithms we've selected */
281 if (wm8994
->mbc_ena
[path
])
283 if (wm8994
->hpf2_ena
[path
])
285 if (wm8994
->hpf1_ena
[path
])
287 if (wm8994
->vss_ena
[path
])
290 snd_soc_write(codec
, 0x2201, ena
);
292 /* Switch the DSP into the data path */
293 snd_soc_update_bits(codec
, WM8958_DSP2_CONFIG
,
294 WM8958_MBC_SEL_MASK
| WM8958_MBC_ENA
,
295 path
<< WM8958_MBC_SEL_SHIFT
| WM8958_MBC_ENA
);
298 static void wm8958_dsp_start_enh_eq(struct snd_soc_codec
*codec
, int path
)
300 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
301 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
304 wm8958_dsp2_fw(codec
, "ENH_EQ", wm8994
->enh_eq
, false);
306 snd_soc_update_bits(codec
, WM8958_DSP2_PROGRAM
,
307 WM8958_DSP2_ENA
, WM8958_DSP2_ENA
);
309 /* If we've got user supplied settings use them */
310 if (pdata
&& pdata
->num_enh_eq_cfgs
) {
311 struct wm8958_enh_eq_cfg
*cfg
312 = &pdata
->enh_eq_cfgs
[wm8994
->enh_eq_cfg
];
314 for (i
= 0; i
< ARRAY_SIZE(cfg
->regs
); i
++)
315 snd_soc_write(codec
, i
+ 0x2200,
320 snd_soc_write(codec
, WM8958_DSP2_EXECCONTROL
,
323 /* Switch the DSP into the data path */
324 snd_soc_update_bits(codec
, WM8958_DSP2_CONFIG
,
325 WM8958_MBC_SEL_MASK
| WM8958_MBC_ENA
,
326 path
<< WM8958_MBC_SEL_SHIFT
| WM8958_MBC_ENA
);
329 static void wm8958_dsp_apply(struct snd_soc_codec
*codec
, int path
, int start
)
331 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
332 int pwr_reg
= snd_soc_read(codec
, WM8994_POWER_MANAGEMENT_5
);
337 pwr_reg
&= (WM8994_AIF1DAC1L_ENA
| WM8994_AIF1DAC1R_ENA
);
341 pwr_reg
&= (WM8994_AIF1DAC2L_ENA
| WM8994_AIF1DAC2R_ENA
);
345 pwr_reg
&= (WM8994_AIF2DACL_ENA
| WM8994_AIF2DACR_ENA
);
353 /* Do we have both an active AIF and an active algorithm? */
354 ena
= wm8994
->mbc_ena
[path
] || wm8994
->vss_ena
[path
] ||
355 wm8994
->hpf1_ena
[path
] || wm8994
->hpf2_ena
[path
] ||
356 wm8994
->enh_eq_ena
[path
];
360 reg
= snd_soc_read(codec
, WM8958_DSP2_PROGRAM
);
362 dev_dbg(codec
->dev
, "DSP path %d %d startup: %d, power: %x, DSP: %x\n",
363 path
, wm8994
->dsp_active
, start
, pwr_reg
, reg
);
366 /* If the DSP is already running then noop */
367 if (reg
& WM8958_DSP2_ENA
)
370 /* If either AIFnCLK is not yet enabled postpone */
371 if (!(snd_soc_read(codec
, WM8994_AIF1_CLOCKING_1
)
372 & WM8994_AIF1CLK_ENA_MASK
) &&
373 !(snd_soc_read(codec
, WM8994_AIF2_CLOCKING_1
)
374 & WM8994_AIF2CLK_ENA_MASK
))
377 /* Switch the clock over to the appropriate AIF */
378 snd_soc_update_bits(codec
, WM8994_CLOCKING_1
,
379 WM8958_DSP2CLK_SRC
| WM8958_DSP2CLK_ENA
,
380 aif
<< WM8958_DSP2CLK_SRC_SHIFT
|
383 if (wm8994
->enh_eq_ena
[path
])
384 wm8958_dsp_start_enh_eq(codec
, path
);
385 else if (wm8994
->vss_ena
[path
] || wm8994
->hpf1_ena
[path
] ||
386 wm8994
->hpf2_ena
[path
])
387 wm8958_dsp_start_vss(codec
, path
);
388 else if (wm8994
->mbc_ena
[path
])
389 wm8958_dsp_start_mbc(codec
, path
);
391 wm8994
->dsp_active
= path
;
393 dev_dbg(codec
->dev
, "DSP running in path %d\n", path
);
396 if (!start
&& wm8994
->dsp_active
== path
) {
397 /* If the DSP is already stopped then noop */
398 if (!(reg
& WM8958_DSP2_ENA
))
401 snd_soc_update_bits(codec
, WM8958_DSP2_CONFIG
,
403 snd_soc_write(codec
, WM8958_DSP2_EXECCONTROL
,
405 snd_soc_update_bits(codec
, WM8958_DSP2_PROGRAM
,
407 snd_soc_update_bits(codec
, WM8994_CLOCKING_1
,
408 WM8958_DSP2CLK_ENA
, 0);
410 wm8994
->dsp_active
= -1;
412 dev_dbg(codec
->dev
, "DSP stopped\n");
416 int wm8958_aif_ev(struct snd_soc_dapm_widget
*w
,
417 struct snd_kcontrol
*kcontrol
, int event
)
419 struct snd_soc_codec
*codec
= w
->codec
;
423 case SND_SOC_DAPM_POST_PMU
:
424 case SND_SOC_DAPM_PRE_PMU
:
425 for (i
= 0; i
< 3; i
++)
426 wm8958_dsp_apply(codec
, i
, 1);
428 case SND_SOC_DAPM_POST_PMD
:
429 case SND_SOC_DAPM_PRE_PMD
:
430 for (i
= 0; i
< 3; i
++)
431 wm8958_dsp_apply(codec
, i
, 0);
438 /* Check if DSP2 is in use on another AIF */
439 static int wm8958_dsp2_busy(struct wm8994_priv
*wm8994
, int aif
)
443 for (i
= 0; i
< ARRAY_SIZE(wm8994
->mbc_ena
); i
++) {
446 if (wm8994
->mbc_ena
[i
] || wm8994
->vss_ena
[i
] ||
447 wm8994
->hpf1_ena
[i
] || wm8994
->hpf2_ena
[i
])
454 static int wm8958_put_mbc_enum(struct snd_kcontrol
*kcontrol
,
455 struct snd_ctl_elem_value
*ucontrol
)
457 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
458 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
459 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
460 int value
= ucontrol
->value
.integer
.value
[0];
463 /* Don't allow on the fly reconfiguration */
464 reg
= snd_soc_read(codec
, WM8994_CLOCKING_1
);
465 if (reg
< 0 || reg
& WM8958_DSP2CLK_ENA
)
468 if (value
>= pdata
->num_mbc_cfgs
)
471 wm8994
->mbc_cfg
= value
;
476 static int wm8958_get_mbc_enum(struct snd_kcontrol
*kcontrol
,
477 struct snd_ctl_elem_value
*ucontrol
)
479 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
480 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
482 ucontrol
->value
.enumerated
.item
[0] = wm8994
->mbc_cfg
;
487 static int wm8958_mbc_info(struct snd_kcontrol
*kcontrol
,
488 struct snd_ctl_elem_info
*uinfo
)
490 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
492 uinfo
->value
.integer
.min
= 0;
493 uinfo
->value
.integer
.max
= 1;
497 static int wm8958_mbc_get(struct snd_kcontrol
*kcontrol
,
498 struct snd_ctl_elem_value
*ucontrol
)
500 int mbc
= kcontrol
->private_value
;
501 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
502 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
504 ucontrol
->value
.integer
.value
[0] = wm8994
->mbc_ena
[mbc
];
509 static int wm8958_mbc_put(struct snd_kcontrol
*kcontrol
,
510 struct snd_ctl_elem_value
*ucontrol
)
512 int mbc
= kcontrol
->private_value
;
513 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
514 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
516 if (wm8994
->mbc_ena
[mbc
] == ucontrol
->value
.integer
.value
[0])
519 if (ucontrol
->value
.integer
.value
[0] > 1)
522 if (wm8958_dsp2_busy(wm8994
, mbc
)) {
523 dev_dbg(codec
->dev
, "DSP2 active on %d already\n", mbc
);
527 if (wm8994
->enh_eq_ena
[mbc
])
530 wm8994
->mbc_ena
[mbc
] = ucontrol
->value
.integer
.value
[0];
532 wm8958_dsp_apply(codec
, mbc
, wm8994
->mbc_ena
[mbc
]);
537 #define WM8958_MBC_SWITCH(xname, xval) {\
538 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
539 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
540 .info = wm8958_mbc_info, \
541 .get = wm8958_mbc_get, .put = wm8958_mbc_put, \
542 .private_value = xval }
544 static int wm8958_put_vss_enum(struct snd_kcontrol
*kcontrol
,
545 struct snd_ctl_elem_value
*ucontrol
)
547 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
548 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
549 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
550 int value
= ucontrol
->value
.integer
.value
[0];
553 /* Don't allow on the fly reconfiguration */
554 reg
= snd_soc_read(codec
, WM8994_CLOCKING_1
);
555 if (reg
< 0 || reg
& WM8958_DSP2CLK_ENA
)
558 if (value
>= pdata
->num_vss_cfgs
)
561 wm8994
->vss_cfg
= value
;
566 static int wm8958_get_vss_enum(struct snd_kcontrol
*kcontrol
,
567 struct snd_ctl_elem_value
*ucontrol
)
569 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
570 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
572 ucontrol
->value
.enumerated
.item
[0] = wm8994
->vss_cfg
;
577 static int wm8958_put_vss_hpf_enum(struct snd_kcontrol
*kcontrol
,
578 struct snd_ctl_elem_value
*ucontrol
)
580 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
581 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
582 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
583 int value
= ucontrol
->value
.integer
.value
[0];
586 /* Don't allow on the fly reconfiguration */
587 reg
= snd_soc_read(codec
, WM8994_CLOCKING_1
);
588 if (reg
< 0 || reg
& WM8958_DSP2CLK_ENA
)
591 if (value
>= pdata
->num_vss_hpf_cfgs
)
594 wm8994
->vss_hpf_cfg
= value
;
599 static int wm8958_get_vss_hpf_enum(struct snd_kcontrol
*kcontrol
,
600 struct snd_ctl_elem_value
*ucontrol
)
602 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
603 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
605 ucontrol
->value
.enumerated
.item
[0] = wm8994
->vss_hpf_cfg
;
610 static int wm8958_vss_info(struct snd_kcontrol
*kcontrol
,
611 struct snd_ctl_elem_info
*uinfo
)
613 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
615 uinfo
->value
.integer
.min
= 0;
616 uinfo
->value
.integer
.max
= 1;
620 static int wm8958_vss_get(struct snd_kcontrol
*kcontrol
,
621 struct snd_ctl_elem_value
*ucontrol
)
623 int vss
= kcontrol
->private_value
;
624 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
625 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
627 ucontrol
->value
.integer
.value
[0] = wm8994
->vss_ena
[vss
];
632 static int wm8958_vss_put(struct snd_kcontrol
*kcontrol
,
633 struct snd_ctl_elem_value
*ucontrol
)
635 int vss
= kcontrol
->private_value
;
636 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
637 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
639 if (wm8994
->vss_ena
[vss
] == ucontrol
->value
.integer
.value
[0])
642 if (ucontrol
->value
.integer
.value
[0] > 1)
645 if (!wm8994
->mbc_vss
)
648 if (wm8958_dsp2_busy(wm8994
, vss
)) {
649 dev_dbg(codec
->dev
, "DSP2 active on %d already\n", vss
);
653 if (wm8994
->enh_eq_ena
[vss
])
656 wm8994
->vss_ena
[vss
] = ucontrol
->value
.integer
.value
[0];
658 wm8958_dsp_apply(codec
, vss
, wm8994
->vss_ena
[vss
]);
664 #define WM8958_VSS_SWITCH(xname, xval) {\
665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
666 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
667 .info = wm8958_vss_info, \
668 .get = wm8958_vss_get, .put = wm8958_vss_put, \
669 .private_value = xval }
671 static int wm8958_hpf_info(struct snd_kcontrol
*kcontrol
,
672 struct snd_ctl_elem_info
*uinfo
)
674 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
676 uinfo
->value
.integer
.min
= 0;
677 uinfo
->value
.integer
.max
= 1;
681 static int wm8958_hpf_get(struct snd_kcontrol
*kcontrol
,
682 struct snd_ctl_elem_value
*ucontrol
)
684 int hpf
= kcontrol
->private_value
;
685 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
686 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
689 ucontrol
->value
.integer
.value
[0] = wm8994
->hpf1_ena
[hpf
% 3];
691 ucontrol
->value
.integer
.value
[0] = wm8994
->hpf2_ena
[hpf
% 3];
696 static int wm8958_hpf_put(struct snd_kcontrol
*kcontrol
,
697 struct snd_ctl_elem_value
*ucontrol
)
699 int hpf
= kcontrol
->private_value
;
700 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
701 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
704 if (wm8994
->hpf1_ena
[hpf
% 3] ==
705 ucontrol
->value
.integer
.value
[0])
708 if (wm8994
->hpf2_ena
[hpf
% 3] ==
709 ucontrol
->value
.integer
.value
[0])
713 if (ucontrol
->value
.integer
.value
[0] > 1)
716 if (!wm8994
->mbc_vss
)
719 if (wm8958_dsp2_busy(wm8994
, hpf
% 3)) {
720 dev_dbg(codec
->dev
, "DSP2 active on %d already\n", hpf
);
724 if (wm8994
->enh_eq_ena
[hpf
% 3])
728 wm8994
->hpf1_ena
[hpf
% 3] = ucontrol
->value
.integer
.value
[0];
730 wm8994
->hpf2_ena
[hpf
% 3] = ucontrol
->value
.integer
.value
[0];
732 wm8958_dsp_apply(codec
, hpf
% 3, ucontrol
->value
.integer
.value
[0]);
737 #define WM8958_HPF_SWITCH(xname, xval) {\
738 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
739 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
740 .info = wm8958_hpf_info, \
741 .get = wm8958_hpf_get, .put = wm8958_hpf_put, \
742 .private_value = xval }
744 static int wm8958_put_enh_eq_enum(struct snd_kcontrol
*kcontrol
,
745 struct snd_ctl_elem_value
*ucontrol
)
747 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
748 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
749 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
750 int value
= ucontrol
->value
.integer
.value
[0];
753 /* Don't allow on the fly reconfiguration */
754 reg
= snd_soc_read(codec
, WM8994_CLOCKING_1
);
755 if (reg
< 0 || reg
& WM8958_DSP2CLK_ENA
)
758 if (value
>= pdata
->num_enh_eq_cfgs
)
761 wm8994
->enh_eq_cfg
= value
;
766 static int wm8958_get_enh_eq_enum(struct snd_kcontrol
*kcontrol
,
767 struct snd_ctl_elem_value
*ucontrol
)
769 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
770 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
772 ucontrol
->value
.enumerated
.item
[0] = wm8994
->enh_eq_cfg
;
777 static int wm8958_enh_eq_info(struct snd_kcontrol
*kcontrol
,
778 struct snd_ctl_elem_info
*uinfo
)
780 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
782 uinfo
->value
.integer
.min
= 0;
783 uinfo
->value
.integer
.max
= 1;
787 static int wm8958_enh_eq_get(struct snd_kcontrol
*kcontrol
,
788 struct snd_ctl_elem_value
*ucontrol
)
790 int eq
= kcontrol
->private_value
;
791 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
792 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
794 ucontrol
->value
.integer
.value
[0] = wm8994
->enh_eq_ena
[eq
];
799 static int wm8958_enh_eq_put(struct snd_kcontrol
*kcontrol
,
800 struct snd_ctl_elem_value
*ucontrol
)
802 int eq
= kcontrol
->private_value
;
803 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
804 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
806 if (wm8994
->enh_eq_ena
[eq
] == ucontrol
->value
.integer
.value
[0])
809 if (ucontrol
->value
.integer
.value
[0] > 1)
815 if (wm8958_dsp2_busy(wm8994
, eq
)) {
816 dev_dbg(codec
->dev
, "DSP2 active on %d already\n", eq
);
820 if (wm8994
->mbc_ena
[eq
] || wm8994
->vss_ena
[eq
] ||
821 wm8994
->hpf1_ena
[eq
] || wm8994
->hpf2_ena
[eq
])
824 wm8994
->enh_eq_ena
[eq
] = ucontrol
->value
.integer
.value
[0];
826 wm8958_dsp_apply(codec
, eq
, ucontrol
->value
.integer
.value
[0]);
831 #define WM8958_ENH_EQ_SWITCH(xname, xval) {\
832 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
833 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
834 .info = wm8958_enh_eq_info, \
835 .get = wm8958_enh_eq_get, .put = wm8958_enh_eq_put, \
836 .private_value = xval }
838 static const struct snd_kcontrol_new wm8958_mbc_snd_controls
[] = {
839 WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0),
840 WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1),
841 WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2),
844 static const struct snd_kcontrol_new wm8958_vss_snd_controls
[] = {
845 WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0),
846 WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1),
847 WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2),
848 WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0),
849 WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1),
850 WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2),
851 WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3),
852 WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4),
853 WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5),
856 static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls
[] = {
857 WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0),
858 WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1),
859 WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2),
862 static void wm8958_enh_eq_loaded(const struct firmware
*fw
, void *context
)
864 struct snd_soc_codec
*codec
= context
;
865 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
867 if (fw
&& (wm8958_dsp2_fw(codec
, "ENH_EQ", fw
, true) == 0)) {
868 mutex_lock(&codec
->mutex
);
870 mutex_unlock(&codec
->mutex
);
874 static void wm8958_mbc_vss_loaded(const struct firmware
*fw
, void *context
)
876 struct snd_soc_codec
*codec
= context
;
877 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
879 if (fw
&& (wm8958_dsp2_fw(codec
, "MBC+VSS", fw
, true) == 0)) {
880 mutex_lock(&codec
->mutex
);
881 wm8994
->mbc_vss
= fw
;
882 mutex_unlock(&codec
->mutex
);
885 /* We can't have more than one request outstanding at once so
888 request_firmware_nowait(THIS_MODULE
, FW_ACTION_HOTPLUG
,
889 "wm8958_enh_eq.wfw", codec
->dev
, GFP_KERNEL
,
890 codec
, wm8958_enh_eq_loaded
);
893 static void wm8958_mbc_loaded(const struct firmware
*fw
, void *context
)
895 struct snd_soc_codec
*codec
= context
;
896 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
898 if (wm8958_dsp2_fw(codec
, "MBC", fw
, true) != 0)
901 mutex_lock(&codec
->mutex
);
903 mutex_unlock(&codec
->mutex
);
905 /* We can't have more than one request outstanding at once so
908 request_firmware_nowait(THIS_MODULE
, FW_ACTION_HOTPLUG
,
909 "wm8958_mbc_vss.wfw", codec
->dev
, GFP_KERNEL
,
910 codec
, wm8958_mbc_vss_loaded
);
913 void wm8958_dsp2_init(struct snd_soc_codec
*codec
)
915 struct wm8994_priv
*wm8994
= snd_soc_codec_get_drvdata(codec
);
916 struct wm8994_pdata
*pdata
= wm8994
->pdata
;
919 wm8994
->dsp_active
= -1;
921 snd_soc_add_controls(codec
, wm8958_mbc_snd_controls
,
922 ARRAY_SIZE(wm8958_mbc_snd_controls
));
923 snd_soc_add_controls(codec
, wm8958_vss_snd_controls
,
924 ARRAY_SIZE(wm8958_vss_snd_controls
));
925 snd_soc_add_controls(codec
, wm8958_enh_eq_snd_controls
,
926 ARRAY_SIZE(wm8958_enh_eq_snd_controls
));
929 /* We don't *require* firmware and don't want to delay boot */
930 request_firmware_nowait(THIS_MODULE
, FW_ACTION_HOTPLUG
,
931 "wm8958_mbc.wfw", codec
->dev
, GFP_KERNEL
,
932 codec
, wm8958_mbc_loaded
);
937 if (pdata
->num_mbc_cfgs
) {
938 struct snd_kcontrol_new control
[] = {
939 SOC_ENUM_EXT("MBC Mode", wm8994
->mbc_enum
,
940 wm8958_get_mbc_enum
, wm8958_put_mbc_enum
),
943 /* We need an array of texts for the enum API */
944 wm8994
->mbc_texts
= kmalloc(sizeof(char *)
945 * pdata
->num_mbc_cfgs
, GFP_KERNEL
);
946 if (!wm8994
->mbc_texts
) {
947 dev_err(wm8994
->codec
->dev
,
948 "Failed to allocate %d MBC config texts\n",
949 pdata
->num_mbc_cfgs
);
953 for (i
= 0; i
< pdata
->num_mbc_cfgs
; i
++)
954 wm8994
->mbc_texts
[i
] = pdata
->mbc_cfgs
[i
].name
;
956 wm8994
->mbc_enum
.max
= pdata
->num_mbc_cfgs
;
957 wm8994
->mbc_enum
.texts
= wm8994
->mbc_texts
;
959 ret
= snd_soc_add_controls(wm8994
->codec
, control
, 1);
961 dev_err(wm8994
->codec
->dev
,
962 "Failed to add MBC mode controls: %d\n", ret
);
965 if (pdata
->num_vss_cfgs
) {
966 struct snd_kcontrol_new control
[] = {
967 SOC_ENUM_EXT("VSS Mode", wm8994
->vss_enum
,
968 wm8958_get_vss_enum
, wm8958_put_vss_enum
),
971 /* We need an array of texts for the enum API */
972 wm8994
->vss_texts
= kmalloc(sizeof(char *)
973 * pdata
->num_vss_cfgs
, GFP_KERNEL
);
974 if (!wm8994
->vss_texts
) {
975 dev_err(wm8994
->codec
->dev
,
976 "Failed to allocate %d VSS config texts\n",
977 pdata
->num_vss_cfgs
);
981 for (i
= 0; i
< pdata
->num_vss_cfgs
; i
++)
982 wm8994
->vss_texts
[i
] = pdata
->vss_cfgs
[i
].name
;
984 wm8994
->vss_enum
.max
= pdata
->num_vss_cfgs
;
985 wm8994
->vss_enum
.texts
= wm8994
->vss_texts
;
987 ret
= snd_soc_add_controls(wm8994
->codec
, control
, 1);
989 dev_err(wm8994
->codec
->dev
,
990 "Failed to add VSS mode controls: %d\n", ret
);
993 if (pdata
->num_vss_hpf_cfgs
) {
994 struct snd_kcontrol_new control
[] = {
995 SOC_ENUM_EXT("VSS HPF Mode", wm8994
->vss_hpf_enum
,
996 wm8958_get_vss_hpf_enum
,
997 wm8958_put_vss_hpf_enum
),
1000 /* We need an array of texts for the enum API */
1001 wm8994
->vss_hpf_texts
= kmalloc(sizeof(char *)
1002 * pdata
->num_vss_hpf_cfgs
, GFP_KERNEL
);
1003 if (!wm8994
->vss_hpf_texts
) {
1004 dev_err(wm8994
->codec
->dev
,
1005 "Failed to allocate %d VSS HPF config texts\n",
1006 pdata
->num_vss_hpf_cfgs
);
1010 for (i
= 0; i
< pdata
->num_vss_hpf_cfgs
; i
++)
1011 wm8994
->vss_hpf_texts
[i
] = pdata
->vss_hpf_cfgs
[i
].name
;
1013 wm8994
->vss_hpf_enum
.max
= pdata
->num_vss_hpf_cfgs
;
1014 wm8994
->vss_hpf_enum
.texts
= wm8994
->vss_hpf_texts
;
1016 ret
= snd_soc_add_controls(wm8994
->codec
, control
, 1);
1018 dev_err(wm8994
->codec
->dev
,
1019 "Failed to add VSS HPFmode controls: %d\n",
1023 if (pdata
->num_enh_eq_cfgs
) {
1024 struct snd_kcontrol_new control
[] = {
1025 SOC_ENUM_EXT("Enhanced EQ Mode", wm8994
->enh_eq_enum
,
1026 wm8958_get_enh_eq_enum
,
1027 wm8958_put_enh_eq_enum
),
1030 /* We need an array of texts for the enum API */
1031 wm8994
->enh_eq_texts
= kmalloc(sizeof(char *)
1032 * pdata
->num_enh_eq_cfgs
, GFP_KERNEL
);
1033 if (!wm8994
->enh_eq_texts
) {
1034 dev_err(wm8994
->codec
->dev
,
1035 "Failed to allocate %d enhanced EQ config texts\n",
1036 pdata
->num_enh_eq_cfgs
);
1040 for (i
= 0; i
< pdata
->num_enh_eq_cfgs
; i
++)
1041 wm8994
->enh_eq_texts
[i
] = pdata
->enh_eq_cfgs
[i
].name
;
1043 wm8994
->enh_eq_enum
.max
= pdata
->num_enh_eq_cfgs
;
1044 wm8994
->enh_eq_enum
.texts
= wm8994
->enh_eq_texts
;
1046 ret
= snd_soc_add_controls(wm8994
->codec
, control
, 1);
1048 dev_err(wm8994
->codec
->dev
,
1049 "Failed to add enhanced EQ controls: %d\n",