aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm_adsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm_adsp.c')
-rw-r--r--sound/soc/codecs/wm_adsp.c124
1 files changed, 113 insertions, 11 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 9af1bddc4c62..3470b649c0b2 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -31,6 +31,7 @@
31 31
32#include <linux/mfd/arizona/registers.h> 32#include <linux/mfd/arizona/registers.h>
33 33
34#include "arizona.h"
34#include "wm_adsp.h" 35#include "wm_adsp.h"
35 36
36#define adsp_crit(_dsp, fmt, ...) \ 37#define adsp_crit(_dsp, fmt, ...) \
@@ -193,17 +194,25 @@ static void wm_adsp_buf_free(struct list_head *list)
193 194
194#define WM_ADSP_NUM_FW 4 195#define WM_ADSP_NUM_FW 4
195 196
197#define WM_ADSP_FW_MBC_VSS 0
198#define WM_ADSP_FW_TX 1
199#define WM_ADSP_FW_TX_SPK 2
200#define WM_ADSP_FW_RX_ANC 3
201
196static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { 202static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
197 "MBC/VSS", "Tx", "Tx Speaker", "Rx ANC" 203 [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
204 [WM_ADSP_FW_TX] = "Tx",
205 [WM_ADSP_FW_TX_SPK] = "Tx Speaker",
206 [WM_ADSP_FW_RX_ANC] = "Rx ANC",
198}; 207};
199 208
200static struct { 209static struct {
201 const char *file; 210 const char *file;
202} wm_adsp_fw[WM_ADSP_NUM_FW] = { 211} wm_adsp_fw[WM_ADSP_NUM_FW] = {
203 { .file = "mbc-vss" }, 212 [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
204 { .file = "tx" }, 213 [WM_ADSP_FW_TX] = { .file = "tx" },
205 { .file = "tx-spk" }, 214 [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" },
206 { .file = "rx-anc" }, 215 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" },
207}; 216};
208 217
209static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 218static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
@@ -246,17 +255,52 @@ static const struct soc_enum wm_adsp_fw_enum[] = {
246 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 255 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
247}; 256};
248 257
249const struct snd_kcontrol_new wm_adsp_fw_controls[] = { 258const struct snd_kcontrol_new wm_adsp1_fw_controls[] = {
259 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
260 wm_adsp_fw_get, wm_adsp_fw_put),
261 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
262 wm_adsp_fw_get, wm_adsp_fw_put),
263 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
264 wm_adsp_fw_get, wm_adsp_fw_put),
265};
266EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls);
267
268#if IS_ENABLED(CONFIG_SND_SOC_ARIZONA)
269static const struct soc_enum wm_adsp2_rate_enum[] = {
270 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
271 ARIZONA_DSP1_RATE_SHIFT, 0xf,
272 ARIZONA_RATE_ENUM_SIZE,
273 arizona_rate_text, arizona_rate_val),
274 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
275 ARIZONA_DSP1_RATE_SHIFT, 0xf,
276 ARIZONA_RATE_ENUM_SIZE,
277 arizona_rate_text, arizona_rate_val),
278 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
279 ARIZONA_DSP1_RATE_SHIFT, 0xf,
280 ARIZONA_RATE_ENUM_SIZE,
281 arizona_rate_text, arizona_rate_val),
282 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
283 ARIZONA_DSP1_RATE_SHIFT, 0xf,
284 ARIZONA_RATE_ENUM_SIZE,
285 arizona_rate_text, arizona_rate_val),
286};
287
288const struct snd_kcontrol_new wm_adsp2_fw_controls[] = {
250 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], 289 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
251 wm_adsp_fw_get, wm_adsp_fw_put), 290 wm_adsp_fw_get, wm_adsp_fw_put),
291 SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]),
252 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], 292 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
253 wm_adsp_fw_get, wm_adsp_fw_put), 293 wm_adsp_fw_get, wm_adsp_fw_put),
294 SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]),
254 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], 295 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
255 wm_adsp_fw_get, wm_adsp_fw_put), 296 wm_adsp_fw_get, wm_adsp_fw_put),
297 SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]),
256 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], 298 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
257 wm_adsp_fw_get, wm_adsp_fw_put), 299 wm_adsp_fw_get, wm_adsp_fw_put),
300 SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]),
258}; 301};
259EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); 302EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls);
303#endif
260 304
261static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, 305static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
262 int type) 306 int type)
@@ -549,13 +593,30 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
549 buf_size = sizeof(adsp1_id); 593 buf_size = sizeof(adsp1_id);
550 594
551 algs = be32_to_cpu(adsp1_id.algs); 595 algs = be32_to_cpu(adsp1_id.algs);
596 dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
552 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 597 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
553 be32_to_cpu(adsp1_id.fw.id), 598 dsp->fw_id,
554 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, 599 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
555 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, 600 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
556 be32_to_cpu(adsp1_id.fw.ver) & 0xff, 601 be32_to_cpu(adsp1_id.fw.ver) & 0xff,
557 algs); 602 algs);
558 603
604 region = kzalloc(sizeof(*region), GFP_KERNEL);
605 if (!region)
606 return -ENOMEM;
607 region->type = WMFW_ADSP1_ZM;
608 region->alg = be32_to_cpu(adsp1_id.fw.id);
609 region->base = be32_to_cpu(adsp1_id.zm);
610 list_add_tail(&region->list, &dsp->alg_regions);
611
612 region = kzalloc(sizeof(*region), GFP_KERNEL);
613 if (!region)
614 return -ENOMEM;
615 region->type = WMFW_ADSP1_DM;
616 region->alg = be32_to_cpu(adsp1_id.fw.id);
617 region->base = be32_to_cpu(adsp1_id.dm);
618 list_add_tail(&region->list, &dsp->alg_regions);
619
559 pos = sizeof(adsp1_id) / 2; 620 pos = sizeof(adsp1_id) / 2;
560 term = pos + ((sizeof(*adsp1_alg) * algs) / 2); 621 term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
561 break; 622 break;
@@ -573,13 +634,38 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
573 buf_size = sizeof(adsp2_id); 634 buf_size = sizeof(adsp2_id);
574 635
575 algs = be32_to_cpu(adsp2_id.algs); 636 algs = be32_to_cpu(adsp2_id.algs);
637 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
576 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 638 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
577 be32_to_cpu(adsp2_id.fw.id), 639 dsp->fw_id,
578 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, 640 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
579 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, 641 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
580 be32_to_cpu(adsp2_id.fw.ver) & 0xff, 642 be32_to_cpu(adsp2_id.fw.ver) & 0xff,
581 algs); 643 algs);
582 644
645 region = kzalloc(sizeof(*region), GFP_KERNEL);
646 if (!region)
647 return -ENOMEM;
648 region->type = WMFW_ADSP2_XM;
649 region->alg = be32_to_cpu(adsp2_id.fw.id);
650 region->base = be32_to_cpu(adsp2_id.xm);
651 list_add_tail(&region->list, &dsp->alg_regions);
652
653 region = kzalloc(sizeof(*region), GFP_KERNEL);
654 if (!region)
655 return -ENOMEM;
656 region->type = WMFW_ADSP2_YM;
657 region->alg = be32_to_cpu(adsp2_id.fw.id);
658 region->base = be32_to_cpu(adsp2_id.ym);
659 list_add_tail(&region->list, &dsp->alg_regions);
660
661 region = kzalloc(sizeof(*region), GFP_KERNEL);
662 if (!region)
663 return -ENOMEM;
664 region->type = WMFW_ADSP2_ZM;
665 region->alg = be32_to_cpu(adsp2_id.fw.id);
666 region->base = be32_to_cpu(adsp2_id.zm);
667 list_add_tail(&region->list, &dsp->alg_regions);
668
583 pos = sizeof(adsp2_id) / 2; 669 pos = sizeof(adsp2_id) / 2;
584 term = pos + ((sizeof(*adsp2_alg) * algs) / 2); 670 term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
585 break; 671 break;
@@ -781,8 +867,24 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
781 case (WMFW_INFO_TEXT << 8): 867 case (WMFW_INFO_TEXT << 8):
782 break; 868 break;
783 case (WMFW_ABSOLUTE << 8): 869 case (WMFW_ABSOLUTE << 8):
784 region_name = "register"; 870 /*
785 reg = offset; 871 * Old files may use this for global
872 * coefficients.
873 */
874 if (le32_to_cpu(blk->id) == dsp->fw_id &&
875 offset == 0) {
876 region_name = "global coefficients";
877 mem = wm_adsp_find_region(dsp, type);
878 if (!mem) {
879 adsp_err(dsp, "No ZM\n");
880 break;
881 }
882 reg = wm_adsp_region_to_reg(mem, 0);
883
884 } else {
885 region_name = "register";
886 reg = offset;
887 }
786 break; 888 break;
787 889
788 case WMFW_ADSP1_DM: 890 case WMFW_ADSP1_DM: