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