forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/sound/soc/codecs/wm_adsp.c
....@@ -1,13 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * wm_adsp.c -- Wolfson ADSP support
34 *
45 * Copyright 2012 Wolfson Microelectronics plc
56 *
67 * 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.
118 */
129
1310 #include <linux/ctype.h>
....@@ -45,6 +42,13 @@
4542 dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
4643 #define adsp_dbg(_dsp, fmt, ...) \
4744 dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
45
+
46
+#define compr_err(_obj, fmt, ...) \
47
+ adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
48
+ ##__VA_ARGS__)
49
+#define compr_dbg(_obj, fmt, ...) \
50
+ adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
51
+ ##__VA_ARGS__)
4852
4953 #define ADSP1_CONTROL_1 0x00
5054 #define ADSP1_CONTROL_2 0x02
....@@ -195,7 +199,7 @@
195199 #define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR 0x7C
196200
197201 #define ADSP2_REGION_LOCK_ERR_MASK 0x8000
198
-#define ADSP2_SLAVE_ERR_MASK 0x4000
202
+#define ADSP2_ADDR_ERR_MASK 0x4000
199203 #define ADSP2_WDT_TIMEOUT_STS_MASK 0x2000
200204 #define ADSP2_CTRL_ERR_PAUSE_ENA 0x0002
201205 #define ADSP2_CTRL_ERR_EINT 0x0001
....@@ -219,6 +223,89 @@
219223 * Event control messages
220224 */
221225 #define WM_ADSP_FW_EVENT_SHUTDOWN 0x000001
226
+
227
+/*
228
+ * HALO system info
229
+ */
230
+#define HALO_AHBM_WINDOW_DEBUG_0 0x02040
231
+#define HALO_AHBM_WINDOW_DEBUG_1 0x02044
232
+
233
+/*
234
+ * HALO core
235
+ */
236
+#define HALO_SCRATCH1 0x005c0
237
+#define HALO_SCRATCH2 0x005c8
238
+#define HALO_SCRATCH3 0x005d0
239
+#define HALO_SCRATCH4 0x005d8
240
+#define HALO_CCM_CORE_CONTROL 0x41000
241
+#define HALO_CORE_SOFT_RESET 0x00010
242
+#define HALO_WDT_CONTROL 0x47000
243
+
244
+/*
245
+ * HALO MPU banks
246
+ */
247
+#define HALO_MPU_XMEM_ACCESS_0 0x43000
248
+#define HALO_MPU_YMEM_ACCESS_0 0x43004
249
+#define HALO_MPU_WINDOW_ACCESS_0 0x43008
250
+#define HALO_MPU_XREG_ACCESS_0 0x4300C
251
+#define HALO_MPU_YREG_ACCESS_0 0x43014
252
+#define HALO_MPU_XMEM_ACCESS_1 0x43018
253
+#define HALO_MPU_YMEM_ACCESS_1 0x4301C
254
+#define HALO_MPU_WINDOW_ACCESS_1 0x43020
255
+#define HALO_MPU_XREG_ACCESS_1 0x43024
256
+#define HALO_MPU_YREG_ACCESS_1 0x4302C
257
+#define HALO_MPU_XMEM_ACCESS_2 0x43030
258
+#define HALO_MPU_YMEM_ACCESS_2 0x43034
259
+#define HALO_MPU_WINDOW_ACCESS_2 0x43038
260
+#define HALO_MPU_XREG_ACCESS_2 0x4303C
261
+#define HALO_MPU_YREG_ACCESS_2 0x43044
262
+#define HALO_MPU_XMEM_ACCESS_3 0x43048
263
+#define HALO_MPU_YMEM_ACCESS_3 0x4304C
264
+#define HALO_MPU_WINDOW_ACCESS_3 0x43050
265
+#define HALO_MPU_XREG_ACCESS_3 0x43054
266
+#define HALO_MPU_YREG_ACCESS_3 0x4305C
267
+#define HALO_MPU_XM_VIO_ADDR 0x43100
268
+#define HALO_MPU_XM_VIO_STATUS 0x43104
269
+#define HALO_MPU_YM_VIO_ADDR 0x43108
270
+#define HALO_MPU_YM_VIO_STATUS 0x4310C
271
+#define HALO_MPU_PM_VIO_ADDR 0x43110
272
+#define HALO_MPU_PM_VIO_STATUS 0x43114
273
+#define HALO_MPU_LOCK_CONFIG 0x43140
274
+
275
+/*
276
+ * HALO_AHBM_WINDOW_DEBUG_1
277
+ */
278
+#define HALO_AHBM_CORE_ERR_ADDR_MASK 0x0fffff00
279
+#define HALO_AHBM_CORE_ERR_ADDR_SHIFT 8
280
+#define HALO_AHBM_FLAGS_ERR_MASK 0x000000ff
281
+
282
+/*
283
+ * HALO_CCM_CORE_CONTROL
284
+ */
285
+#define HALO_CORE_EN 0x00000001
286
+
287
+/*
288
+ * HALO_CORE_SOFT_RESET
289
+ */
290
+#define HALO_CORE_SOFT_RESET_MASK 0x00000001
291
+
292
+/*
293
+ * HALO_WDT_CONTROL
294
+ */
295
+#define HALO_WDT_EN_MASK 0x00000001
296
+
297
+/*
298
+ * HALO_MPU_?M_VIO_STATUS
299
+ */
300
+#define HALO_MPU_VIO_STS_MASK 0x007e0000
301
+#define HALO_MPU_VIO_STS_SHIFT 17
302
+#define HALO_MPU_VIO_ERR_WR_MASK 0x00008000
303
+#define HALO_MPU_VIO_ERR_SRC_MASK 0x00007fff
304
+#define HALO_MPU_VIO_ERR_SRC_SHIFT 0
305
+
306
+static struct wm_adsp_ops wm_adsp1_ops;
307
+static struct wm_adsp_ops wm_adsp2_ops[];
308
+static struct wm_adsp_ops wm_halo_ops;
222309
223310 struct wm_adsp_buf {
224311 struct list_head list;
....@@ -268,9 +355,11 @@
268355 #define WM_ADSP_FW_ASR 7
269356 #define WM_ADSP_FW_TRACE 8
270357 #define WM_ADSP_FW_SPK_PROT 9
271
-#define WM_ADSP_FW_MISC 10
358
+#define WM_ADSP_FW_SPK_CALI 10
359
+#define WM_ADSP_FW_SPK_DIAG 11
360
+#define WM_ADSP_FW_MISC 12
272361
273
-#define WM_ADSP_NUM_FW 11
362
+#define WM_ADSP_NUM_FW 13
274363
275364 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
276365 [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
....@@ -283,6 +372,8 @@
283372 [WM_ADSP_FW_ASR] = "ASR Assist",
284373 [WM_ADSP_FW_TRACE] = "Dbg Trace",
285374 [WM_ADSP_FW_SPK_PROT] = "Protection",
375
+ [WM_ADSP_FW_SPK_CALI] = "Calibration",
376
+ [WM_ADSP_FW_SPK_DIAG] = "Diagnostic",
286377 [WM_ADSP_FW_MISC] = "Misc",
287378 };
288379
....@@ -299,6 +390,12 @@
299390 __be32 build_job_number;
300391 };
301392
393
+struct wm_halo_system_config_xm_hdr {
394
+ __be32 halo_heartbeat;
395
+ __be32 build_job_name[3];
396
+ __be32 build_job_number;
397
+};
398
+
302399 struct wm_adsp_alg_xm_struct {
303400 __be32 magic;
304401 __be32 smoothing;
....@@ -310,13 +407,19 @@
310407 __be64 smoothed_power;
311408 };
312409
410
+struct wm_adsp_host_buf_coeff_v1 {
411
+ __be32 host_buf_ptr; /* Host buffer pointer */
412
+ __be32 versions; /* Version numbers */
413
+ __be32 name[4]; /* The buffer name */
414
+};
415
+
313416 struct wm_adsp_buffer {
314
- __be32 X_buf_base; /* XM base addr of first X area */
315
- __be32 X_buf_size; /* Size of 1st X area in words */
316
- __be32 X_buf_base2; /* XM base addr of 2nd X area */
317
- __be32 X_buf_brk; /* Total X size in words */
318
- __be32 Y_buf_base; /* YM base addr of Y area */
319
- __be32 wrap; /* Total size X and Y in words */
417
+ __be32 buf1_base; /* Base addr of first buffer area */
418
+ __be32 buf1_size; /* Size of buf1 area in DSP words */
419
+ __be32 buf2_base; /* Base addr of 2nd buffer area */
420
+ __be32 buf1_buf2_size; /* Size of buf1+buf2 in DSP words */
421
+ __be32 buf3_base; /* Base addr of buf3 area */
422
+ __be32 buf_total_size; /* Size of buf1+buf2+buf3 in DSP words */
320423 __be32 high_water_mark; /* Point at which IRQ is asserted */
321424 __be32 irq_count; /* bits 1-31 count IRQ assertions */
322425 __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */
....@@ -334,6 +437,7 @@
334437 struct wm_adsp_compr;
335438
336439 struct wm_adsp_compr_buf {
440
+ struct list_head list;
337441 struct wm_adsp *dsp;
338442 struct wm_adsp_compr *compr;
339443
....@@ -344,9 +448,13 @@
344448 u32 irq_count;
345449 int read_index;
346450 int avail;
451
+ int host_buf_mem_type;
452
+
453
+ char *name;
347454 };
348455
349456 struct wm_adsp_compr {
457
+ struct list_head list;
350458 struct wm_adsp *dsp;
351459 struct wm_adsp_compr_buf *buf;
352460
....@@ -357,6 +465,8 @@
357465 unsigned int copied_total;
358466
359467 unsigned int sample_rate;
468
+
469
+ const char *name;
360470 };
361471
362472 #define WM_ADSP_DATA_WORD_SIZE 3
....@@ -373,6 +483,11 @@
373483
374484 #define ALG_XM_FIELD(field) \
375485 (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
486
+
487
+#define HOST_BUF_COEFF_SUPPORTED_COMPAT_VER 1
488
+
489
+#define HOST_BUF_COEFF_COMPAT_VER_MASK 0xFF00
490
+#define HOST_BUF_COEFF_COMPAT_VER_SHIFT 8
376491
377492 static int wm_adsp_buffer_init(struct wm_adsp *dsp);
378493 static int wm_adsp_buffer_free(struct wm_adsp *dsp);
....@@ -393,18 +508,18 @@
393508 static const struct wm_adsp_buffer_region_def default_regions[] = {
394509 {
395510 .mem_type = WMFW_ADSP2_XM,
396
- .base_offset = HOST_BUFFER_FIELD(X_buf_base),
397
- .size_offset = HOST_BUFFER_FIELD(X_buf_size),
511
+ .base_offset = HOST_BUFFER_FIELD(buf1_base),
512
+ .size_offset = HOST_BUFFER_FIELD(buf1_size),
398513 },
399514 {
400515 .mem_type = WMFW_ADSP2_XM,
401
- .base_offset = HOST_BUFFER_FIELD(X_buf_base2),
402
- .size_offset = HOST_BUFFER_FIELD(X_buf_brk),
516
+ .base_offset = HOST_BUFFER_FIELD(buf2_base),
517
+ .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size),
403518 },
404519 {
405520 .mem_type = WMFW_ADSP2_YM,
406
- .base_offset = HOST_BUFFER_FIELD(Y_buf_base),
407
- .size_offset = HOST_BUFFER_FIELD(wrap),
521
+ .base_offset = HOST_BUFFER_FIELD(buf3_base),
522
+ .size_offset = HOST_BUFFER_FIELD(buf_total_size),
408523 },
409524 };
410525
....@@ -475,6 +590,8 @@
475590 .caps = trace_caps,
476591 },
477592 [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
593
+ [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" },
594
+ [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" },
478595 [WM_ADSP_FW_MISC] = { .file = "misc" },
479596 };
480597
....@@ -488,6 +605,9 @@
488605 struct wm_coeff_ctl {
489606 const char *name;
490607 const char *fw_name;
608
+ /* Subname is needed to match with firmware */
609
+ const char *subname;
610
+ unsigned int subname_len;
491611 struct wm_adsp_alg_region alg_region;
492612 struct wm_coeff_ctl_ops ops;
493613 struct wm_adsp *dsp;
....@@ -507,12 +627,18 @@
507627 switch (type) {
508628 case WMFW_ADSP1_PM:
509629 return "PM";
630
+ case WMFW_HALO_PM_PACKED:
631
+ return "PM_PACKED";
510632 case WMFW_ADSP1_DM:
511633 return "DM";
512634 case WMFW_ADSP2_XM:
513635 return "XM";
636
+ case WMFW_HALO_XM_PACKED:
637
+ return "XM_PACKED";
514638 case WMFW_ADSP2_YM:
515639 return "YM";
640
+ case WMFW_HALO_YM_PACKED:
641
+ return "YM_PACKED";
516642 case WMFW_ADSP1_ZM:
517643 return "ZM";
518644 default:
....@@ -611,41 +737,18 @@
611737 struct dentry *root = NULL;
612738 int i;
613739
614
- if (!component->debugfs_root) {
615
- adsp_err(dsp, "No codec debugfs root\n");
616
- goto err;
617
- }
618
-
619740 root = debugfs_create_dir(dsp->name, component->debugfs_root);
620741
621
- if (!root)
622
- goto err;
742
+ debugfs_create_bool("booted", 0444, root, &dsp->booted);
743
+ debugfs_create_bool("running", 0444, root, &dsp->running);
744
+ debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id);
745
+ debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version);
623746
624
- if (!debugfs_create_bool("booted", 0444, root, &dsp->booted))
625
- goto err;
626
-
627
- if (!debugfs_create_bool("running", 0444, root, &dsp->running))
628
- goto err;
629
-
630
- if (!debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id))
631
- goto err;
632
-
633
- if (!debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version))
634
- goto err;
635
-
636
- for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) {
637
- if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name,
638
- 0444, root, dsp,
639
- &wm_adsp_debugfs_fops[i].fops))
640
- goto err;
641
- }
747
+ for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i)
748
+ debugfs_create_file(wm_adsp_debugfs_fops[i].name, 0444, root,
749
+ dsp, &wm_adsp_debugfs_fops[i].fops);
642750
643751 dsp->debugfs_root = root;
644
- return;
645
-
646
-err:
647
- debugfs_remove_recursive(root);
648
- adsp_err(dsp, "Failed to create debugfs\n");
649752 }
650753
651754 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
....@@ -697,7 +800,7 @@
697800 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
698801 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
699802 struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
700
- int ret = 0;
803
+ int ret = 1;
701804
702805 if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
703806 return 0;
....@@ -707,7 +810,7 @@
707810
708811 mutex_lock(&dsp[e->shift_l].pwr_lock);
709812
710
- if (dsp[e->shift_l].booted || dsp[e->shift_l].compr)
813
+ if (dsp[e->shift_l].booted || !list_empty(&dsp[e->shift_l].compr_list))
711814 ret = -EBUSY;
712815 else
713816 dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
....@@ -744,17 +847,12 @@
744847 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
745848 unsigned int offset)
746849 {
747
- if (WARN_ON(!mem))
748
- return offset;
749850 switch (mem->type) {
750851 case WMFW_ADSP1_PM:
751852 return mem->base + (offset * 3);
752853 case WMFW_ADSP1_DM:
753
- return mem->base + (offset * 2);
754854 case WMFW_ADSP2_XM:
755
- return mem->base + (offset * 2);
756855 case WMFW_ADSP2_YM:
757
- return mem->base + (offset * 2);
758856 case WMFW_ADSP1_ZM:
759857 return mem->base + (offset * 2);
760858 default:
....@@ -763,49 +861,72 @@
763861 }
764862 }
765863
766
-static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
864
+static unsigned int wm_halo_region_to_reg(struct wm_adsp_region const *mem,
865
+ unsigned int offset)
767866 {
768
- unsigned int scratch[4];
769
- unsigned int addr = dsp->base + ADSP2_SCRATCH0;
867
+ switch (mem->type) {
868
+ case WMFW_ADSP2_XM:
869
+ case WMFW_ADSP2_YM:
870
+ return mem->base + (offset * 4);
871
+ case WMFW_HALO_XM_PACKED:
872
+ case WMFW_HALO_YM_PACKED:
873
+ return (mem->base + (offset * 3)) & ~0x3;
874
+ case WMFW_HALO_PM_PACKED:
875
+ return mem->base + (offset * 5);
876
+ default:
877
+ WARN(1, "Unknown memory region type");
878
+ return offset;
879
+ }
880
+}
881
+
882
+static void wm_adsp_read_fw_status(struct wm_adsp *dsp,
883
+ int noffs, unsigned int *offs)
884
+{
770885 unsigned int i;
771886 int ret;
772887
773
- for (i = 0; i < ARRAY_SIZE(scratch); ++i) {
774
- ret = regmap_read(dsp->regmap, addr + i, &scratch[i]);
888
+ for (i = 0; i < noffs; ++i) {
889
+ ret = regmap_read(dsp->regmap, dsp->base + offs[i], &offs[i]);
775890 if (ret) {
776891 adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret);
777892 return;
778893 }
779894 }
895
+}
896
+
897
+static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
898
+{
899
+ unsigned int offs[] = {
900
+ ADSP2_SCRATCH0, ADSP2_SCRATCH1, ADSP2_SCRATCH2, ADSP2_SCRATCH3,
901
+ };
902
+
903
+ wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
780904
781905 adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
782
- scratch[0], scratch[1], scratch[2], scratch[3]);
906
+ offs[0], offs[1], offs[2], offs[3]);
783907 }
784908
785909 static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp)
786910 {
787
- unsigned int scratch[2];
788
- int ret;
911
+ unsigned int offs[] = { ADSP2V2_SCRATCH0_1, ADSP2V2_SCRATCH2_3 };
789912
790
- ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1,
791
- &scratch[0]);
792
- if (ret) {
793
- adsp_err(dsp, "Failed to read SCRATCH0_1: %d\n", ret);
794
- return;
795
- }
796
-
797
- ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH2_3,
798
- &scratch[1]);
799
- if (ret) {
800
- adsp_err(dsp, "Failed to read SCRATCH2_3: %d\n", ret);
801
- return;
802
- }
913
+ wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
803914
804915 adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
805
- scratch[0] & 0xFFFF,
806
- scratch[0] >> 16,
807
- scratch[1] & 0xFFFF,
808
- scratch[1] >> 16);
916
+ offs[0] & 0xFFFF, offs[0] >> 16,
917
+ offs[1] & 0xFFFF, offs[1] >> 16);
918
+}
919
+
920
+static void wm_halo_show_fw_status(struct wm_adsp *dsp)
921
+{
922
+ unsigned int offs[] = {
923
+ HALO_SCRATCH1, HALO_SCRATCH2, HALO_SCRATCH3, HALO_SCRATCH4,
924
+ };
925
+
926
+ wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
927
+
928
+ adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
929
+ offs[0], offs[1], offs[2], offs[3]);
809930 }
810931
811932 static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
....@@ -826,7 +947,7 @@
826947 return -EINVAL;
827948 }
828949
829
- *reg = wm_adsp_region_to_reg(mem, ctl->alg_region.base + ctl->offset);
950
+ *reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset);
830951
831952 return 0;
832953 }
....@@ -915,8 +1036,8 @@
9151036 return -ETIMEDOUT;
9161037 }
9171038
918
-static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
919
- const void *buf, size_t len)
1039
+static int wm_coeff_write_ctrl_raw(struct wm_coeff_ctl *ctl,
1040
+ const void *buf, size_t len)
9201041 {
9211042 struct wm_adsp *dsp = ctl->dsp;
9221043 void *scratch;
....@@ -946,6 +1067,23 @@
9461067 return 0;
9471068 }
9481069
1070
+static int wm_coeff_write_ctrl(struct wm_coeff_ctl *ctl,
1071
+ const void *buf, size_t len)
1072
+{
1073
+ int ret = 0;
1074
+
1075
+ if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1076
+ ret = -EPERM;
1077
+ else if (buf != ctl->cache)
1078
+ memcpy(ctl->cache, buf, len);
1079
+
1080
+ ctl->set = 1;
1081
+ if (ctl->enabled && ctl->dsp->running)
1082
+ ret = wm_coeff_write_ctrl_raw(ctl, buf, len);
1083
+
1084
+ return ret;
1085
+}
1086
+
9491087 static int wm_coeff_put(struct snd_kcontrol *kctl,
9501088 struct snd_ctl_elem_value *ucontrol)
9511089 {
....@@ -956,16 +1094,7 @@
9561094 int ret = 0;
9571095
9581096 mutex_lock(&ctl->dsp->pwr_lock);
959
-
960
- if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
961
- ret = -EPERM;
962
- else
963
- memcpy(ctl->cache, p, ctl->len);
964
-
965
- ctl->set = 1;
966
- if (ctl->enabled && ctl->dsp->running)
967
- ret = wm_coeff_write_control(ctl, p, ctl->len);
968
-
1097
+ ret = wm_coeff_write_ctrl(ctl, p, ctl->len);
9691098 mutex_unlock(&ctl->dsp->pwr_lock);
9701099
9711100 return ret;
....@@ -981,15 +1110,10 @@
9811110
9821111 mutex_lock(&ctl->dsp->pwr_lock);
9831112
984
- if (copy_from_user(ctl->cache, bytes, size)) {
1113
+ if (copy_from_user(ctl->cache, bytes, size))
9851114 ret = -EFAULT;
986
- } else {
987
- ctl->set = 1;
988
- if (ctl->enabled && ctl->dsp->running)
989
- ret = wm_coeff_write_control(ctl, ctl->cache, size);
990
- else if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
991
- ret = -EPERM;
992
- }
1115
+ else
1116
+ ret = wm_coeff_write_ctrl(ctl, ctl->cache, size);
9931117
9941118 mutex_unlock(&ctl->dsp->pwr_lock);
9951119
....@@ -1020,8 +1144,8 @@
10201144 return ret;
10211145 }
10221146
1023
-static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
1024
- void *buf, size_t len)
1147
+static int wm_coeff_read_ctrl_raw(struct wm_coeff_ctl *ctl,
1148
+ void *buf, size_t len)
10251149 {
10261150 struct wm_adsp *dsp = ctl->dsp;
10271151 void *scratch;
....@@ -1051,6 +1175,26 @@
10511175 return 0;
10521176 }
10531177
1178
+static int wm_coeff_read_ctrl(struct wm_coeff_ctl *ctl, void *buf, size_t len)
1179
+{
1180
+ int ret = 0;
1181
+
1182
+ if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
1183
+ if (ctl->enabled && ctl->dsp->running)
1184
+ return wm_coeff_read_ctrl_raw(ctl, buf, len);
1185
+ else
1186
+ return -EPERM;
1187
+ } else {
1188
+ if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1189
+ ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
1190
+
1191
+ if (buf != ctl->cache)
1192
+ memcpy(buf, ctl->cache, len);
1193
+ }
1194
+
1195
+ return ret;
1196
+}
1197
+
10541198 static int wm_coeff_get(struct snd_kcontrol *kctl,
10551199 struct snd_ctl_elem_value *ucontrol)
10561200 {
....@@ -1058,22 +1202,10 @@
10581202 (struct soc_bytes_ext *)kctl->private_value;
10591203 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
10601204 char *p = ucontrol->value.bytes.data;
1061
- int ret = 0;
1205
+ int ret;
10621206
10631207 mutex_lock(&ctl->dsp->pwr_lock);
1064
-
1065
- if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
1066
- if (ctl->enabled && ctl->dsp->running)
1067
- ret = wm_coeff_read_control(ctl, p, ctl->len);
1068
- else
1069
- ret = -EPERM;
1070
- } else {
1071
- if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1072
- ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1073
-
1074
- memcpy(p, ctl->cache, ctl->len);
1075
- }
1076
-
1208
+ ret = wm_coeff_read_ctrl(ctl, p, ctl->len);
10771209 mutex_unlock(&ctl->dsp->pwr_lock);
10781210
10791211 return ret;
....@@ -1089,15 +1221,7 @@
10891221
10901222 mutex_lock(&ctl->dsp->pwr_lock);
10911223
1092
- if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
1093
- if (ctl->enabled && ctl->dsp->running)
1094
- ret = wm_coeff_read_control(ctl, ctl->cache, size);
1095
- else
1096
- ret = -EPERM;
1097
- } else {
1098
- if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1099
- ret = wm_coeff_read_control(ctl, ctl->cache, size);
1100
- }
1224
+ ret = wm_coeff_read_ctrl(ctl, ctl->cache, size);
11011225
11021226 if (!ret && copy_to_user(bytes, ctl->cache, size))
11031227 ret = -EFAULT;
....@@ -1225,7 +1349,7 @@
12251349 * created so we don't need to do anything.
12261350 */
12271351 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
1228
- ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1352
+ ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
12291353 if (ret < 0)
12301354 return ret;
12311355 }
....@@ -1243,7 +1367,8 @@
12431367 if (!ctl->enabled)
12441368 continue;
12451369 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
1246
- ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
1370
+ ret = wm_coeff_write_ctrl_raw(ctl, ctl->cache,
1371
+ ctl->len);
12471372 if (ret < 0)
12481373 return ret;
12491374 }
....@@ -1287,6 +1412,7 @@
12871412 {
12881413 kfree(ctl->cache);
12891414 kfree(ctl->name);
1415
+ kfree(ctl->subname);
12901416 kfree(ctl);
12911417 }
12921418
....@@ -1313,28 +1439,33 @@
13131439 case 1:
13141440 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x",
13151441 dsp->name, region_name, alg_region->alg);
1442
+ subname = NULL; /* don't append subname */
13161443 break;
1317
- default:
1318
- ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1444
+ case 2:
1445
+ ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
13191446 "%s%c %.12s %x", dsp->name, *region_name,
13201447 wm_adsp_fw_text[dsp->fw], alg_region->alg);
1448
+ break;
1449
+ default:
1450
+ ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1451
+ "%s %.12s %x", dsp->name,
1452
+ wm_adsp_fw_text[dsp->fw], alg_region->alg);
1453
+ break;
1454
+ }
1455
+
1456
+ if (subname) {
1457
+ int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
1458
+ int skip = 0;
1459
+
1460
+ if (dsp->component->name_prefix)
1461
+ avail -= strlen(dsp->component->name_prefix) + 1;
13211462
13221463 /* Truncate the subname from the start if it is too long */
1323
- if (subname) {
1324
- int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
1325
- int skip = 0;
1464
+ if (subname_len > avail)
1465
+ skip = subname_len - avail;
13261466
1327
- if (dsp->component->name_prefix)
1328
- avail -= strlen(dsp->component->name_prefix) + 1;
1329
-
1330
- if (subname_len > avail)
1331
- skip = subname_len - avail;
1332
-
1333
- snprintf(name + ret,
1334
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s",
1335
- subname_len - skip, subname + skip);
1336
- }
1337
- break;
1467
+ snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret,
1468
+ " %.*s", subname_len - skip, subname + skip);
13381469 }
13391470
13401471 list_for_each_entry(ctl, &dsp->ctl_list, list) {
....@@ -1355,6 +1486,15 @@
13551486 ret = -ENOMEM;
13561487 goto err_ctl;
13571488 }
1489
+ if (subname) {
1490
+ ctl->subname_len = subname_len;
1491
+ ctl->subname = kmemdup(subname,
1492
+ strlen(subname) + 1, GFP_KERNEL);
1493
+ if (!ctl->subname) {
1494
+ ret = -ENOMEM;
1495
+ goto err_ctl_name;
1496
+ }
1497
+ }
13581498 ctl->enabled = 1;
13591499 ctl->set = 0;
13601500 ctl->ops.xget = wm_coeff_get;
....@@ -1368,7 +1508,7 @@
13681508 ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
13691509 if (!ctl->cache) {
13701510 ret = -ENOMEM;
1371
- goto err_ctl_name;
1511
+ goto err_ctl_subname;
13721512 }
13731513
13741514 list_add(&ctl->list, &dsp->ctl_list);
....@@ -1392,6 +1532,8 @@
13921532 err_list_del:
13931533 list_del(&ctl->list);
13941534 kfree(ctl->cache);
1535
+err_ctl_subname:
1536
+ kfree(ctl->subname);
13951537 err_ctl_name:
13961538 kfree(ctl->name);
13971539 err_ctl:
....@@ -1622,6 +1764,62 @@
16221764 return 0;
16231765 }
16241766
1767
+static unsigned int wm_adsp1_parse_sizes(struct wm_adsp *dsp,
1768
+ const char * const file,
1769
+ unsigned int pos,
1770
+ const struct firmware *firmware)
1771
+{
1772
+ const struct wmfw_adsp1_sizes *adsp1_sizes;
1773
+
1774
+ adsp1_sizes = (void *)&firmware->data[pos];
1775
+
1776
+ adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
1777
+ le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
1778
+ le32_to_cpu(adsp1_sizes->zm));
1779
+
1780
+ return pos + sizeof(*adsp1_sizes);
1781
+}
1782
+
1783
+static unsigned int wm_adsp2_parse_sizes(struct wm_adsp *dsp,
1784
+ const char * const file,
1785
+ unsigned int pos,
1786
+ const struct firmware *firmware)
1787
+{
1788
+ const struct wmfw_adsp2_sizes *adsp2_sizes;
1789
+
1790
+ adsp2_sizes = (void *)&firmware->data[pos];
1791
+
1792
+ adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
1793
+ le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
1794
+ le32_to_cpu(adsp2_sizes->pm), le32_to_cpu(adsp2_sizes->zm));
1795
+
1796
+ return pos + sizeof(*adsp2_sizes);
1797
+}
1798
+
1799
+static bool wm_adsp_validate_version(struct wm_adsp *dsp, unsigned int version)
1800
+{
1801
+ switch (version) {
1802
+ case 0:
1803
+ adsp_warn(dsp, "Deprecated file format %d\n", version);
1804
+ return true;
1805
+ case 1:
1806
+ case 2:
1807
+ return true;
1808
+ default:
1809
+ return false;
1810
+ }
1811
+}
1812
+
1813
+static bool wm_halo_validate_version(struct wm_adsp *dsp, unsigned int version)
1814
+{
1815
+ switch (version) {
1816
+ case 3:
1817
+ return true;
1818
+ default:
1819
+ return false;
1820
+ }
1821
+}
1822
+
16251823 static int wm_adsp_load(struct wm_adsp *dsp)
16261824 {
16271825 LIST_HEAD(buf_list);
....@@ -1630,7 +1828,6 @@
16301828 unsigned int pos = 0;
16311829 const struct wmfw_header *header;
16321830 const struct wmfw_adsp1_sizes *adsp1_sizes;
1633
- const struct wmfw_adsp2_sizes *adsp2_sizes;
16341831 const struct wmfw_footer *footer;
16351832 const struct wmfw_region *region;
16361833 const struct wm_adsp_region *mem;
....@@ -1639,7 +1836,7 @@
16391836 struct wm_adsp_buf *buf;
16401837 unsigned int reg;
16411838 int regions = 0;
1642
- int ret, offset, type, sizes;
1839
+ int ret, offset, type;
16431840
16441841 file = kzalloc(PAGE_SIZE, GFP_KERNEL);
16451842 if (file == NULL)
....@@ -1670,15 +1867,7 @@
16701867 goto out_fw;
16711868 }
16721869
1673
- switch (header->ver) {
1674
- case 0:
1675
- adsp_warn(dsp, "%s: Depreciated file format %d\n",
1676
- file, header->ver);
1677
- break;
1678
- case 1:
1679
- case 2:
1680
- break;
1681
- default:
1870
+ if (!dsp->ops->validate_version(dsp, header->ver)) {
16821871 adsp_err(dsp, "%s: unknown file format %d\n",
16831872 file, header->ver);
16841873 goto out_fw;
....@@ -1693,39 +1882,13 @@
16931882 goto out_fw;
16941883 }
16951884
1696
- switch (dsp->type) {
1697
- case WMFW_ADSP1:
1698
- pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1699
- adsp1_sizes = (void *)&(header[1]);
1700
- footer = (void *)&(adsp1_sizes[1]);
1701
- sizes = sizeof(*adsp1_sizes);
1885
+ pos = sizeof(*header);
1886
+ pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
17021887
1703
- adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
1704
- file, le32_to_cpu(adsp1_sizes->dm),
1705
- le32_to_cpu(adsp1_sizes->pm),
1706
- le32_to_cpu(adsp1_sizes->zm));
1707
- break;
1888
+ footer = (void *)&firmware->data[pos];
1889
+ pos += sizeof(*footer);
17081890
1709
- case WMFW_ADSP2:
1710
- pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
1711
- adsp2_sizes = (void *)&(header[1]);
1712
- footer = (void *)&(adsp2_sizes[1]);
1713
- sizes = sizeof(*adsp2_sizes);
1714
-
1715
- adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
1716
- file, le32_to_cpu(adsp2_sizes->xm),
1717
- le32_to_cpu(adsp2_sizes->ym),
1718
- le32_to_cpu(adsp2_sizes->pm),
1719
- le32_to_cpu(adsp2_sizes->zm));
1720
- break;
1721
-
1722
- default:
1723
- WARN(1, "Unknown DSP type");
1724
- goto out_fw;
1725
- }
1726
-
1727
- if (le32_to_cpu(header->len) != sizeof(*header) +
1728
- sizes + sizeof(*footer)) {
1891
+ if (le32_to_cpu(header->len) != pos) {
17291892 adsp_err(dsp, "%s: unexpected header length %d\n",
17301893 file, le32_to_cpu(header->len));
17311894 goto out_fw;
....@@ -1742,7 +1905,6 @@
17421905 text = NULL;
17431906 offset = le32_to_cpu(region->offset) & 0xffffff;
17441907 type = be32_to_cpu(region->type) & 0xff;
1745
- mem = wm_adsp_find_region(dsp, type);
17461908
17471909 switch (type) {
17481910 case WMFW_NAME_TEXT:
....@@ -1770,8 +1932,18 @@
17701932 case WMFW_ADSP2_XM:
17711933 case WMFW_ADSP2_YM:
17721934 case WMFW_ADSP1_ZM:
1935
+ case WMFW_HALO_PM_PACKED:
1936
+ case WMFW_HALO_XM_PACKED:
1937
+ case WMFW_HALO_YM_PACKED:
1938
+ mem = wm_adsp_find_region(dsp, type);
1939
+ if (!mem) {
1940
+ adsp_err(dsp, "No region of type: %x\n", type);
1941
+ ret = -EINVAL;
1942
+ goto out_fw;
1943
+ }
1944
+
17731945 region_name = wm_adsp_mem_region_name(type);
1774
- reg = wm_adsp_region_to_reg(mem, offset);
1946
+ reg = dsp->ops->region_to_reg(mem, offset);
17751947 break;
17761948 default:
17771949 adsp_warn(dsp,
....@@ -1850,6 +2022,91 @@
18502022 return ret;
18512023 }
18522024
2025
+/*
2026
+ * Find wm_coeff_ctl with input name as its subname
2027
+ * If not found, return NULL
2028
+ */
2029
+static struct wm_coeff_ctl *wm_adsp_get_ctl(struct wm_adsp *dsp,
2030
+ const char *name, int type,
2031
+ unsigned int alg)
2032
+{
2033
+ struct wm_coeff_ctl *pos, *rslt = NULL;
2034
+ const char *fw_txt = wm_adsp_fw_text[dsp->fw];
2035
+
2036
+ list_for_each_entry(pos, &dsp->ctl_list, list) {
2037
+ if (!pos->subname)
2038
+ continue;
2039
+ if (strncmp(pos->subname, name, pos->subname_len) == 0 &&
2040
+ strncmp(pos->fw_name, fw_txt,
2041
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0 &&
2042
+ pos->alg_region.alg == alg &&
2043
+ pos->alg_region.type == type) {
2044
+ rslt = pos;
2045
+ break;
2046
+ }
2047
+ }
2048
+
2049
+ return rslt;
2050
+}
2051
+
2052
+int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
2053
+ unsigned int alg, void *buf, size_t len)
2054
+{
2055
+ struct wm_coeff_ctl *ctl;
2056
+ struct snd_kcontrol *kcontrol;
2057
+ char ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2058
+ int ret;
2059
+
2060
+ ctl = wm_adsp_get_ctl(dsp, name, type, alg);
2061
+ if (!ctl)
2062
+ return -EINVAL;
2063
+
2064
+ if (len > ctl->len)
2065
+ return -EINVAL;
2066
+
2067
+ ret = wm_coeff_write_ctrl(ctl, buf, len);
2068
+ if (ret)
2069
+ return ret;
2070
+
2071
+ if (ctl->flags & WMFW_CTL_FLAG_SYS)
2072
+ return 0;
2073
+
2074
+ if (dsp->component->name_prefix)
2075
+ snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s",
2076
+ dsp->component->name_prefix, ctl->name);
2077
+ else
2078
+ snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s",
2079
+ ctl->name);
2080
+
2081
+ kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl_name);
2082
+ if (!kcontrol) {
2083
+ adsp_err(dsp, "Can't find kcontrol %s\n", ctl_name);
2084
+ return -EINVAL;
2085
+ }
2086
+
2087
+ snd_ctl_notify(dsp->component->card->snd_card,
2088
+ SNDRV_CTL_EVENT_MASK_VALUE, &kcontrol->id);
2089
+
2090
+ return ret;
2091
+}
2092
+EXPORT_SYMBOL_GPL(wm_adsp_write_ctl);
2093
+
2094
+int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
2095
+ unsigned int alg, void *buf, size_t len)
2096
+{
2097
+ struct wm_coeff_ctl *ctl;
2098
+
2099
+ ctl = wm_adsp_get_ctl(dsp, name, type, alg);
2100
+ if (!ctl)
2101
+ return -EINVAL;
2102
+
2103
+ if (len > ctl->len)
2104
+ return -EINVAL;
2105
+
2106
+ return wm_coeff_read_ctrl(ctl, buf, len);
2107
+}
2108
+EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
2109
+
18532110 static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp,
18542111 const struct wm_adsp_alg_region *alg_region)
18552112 {
....@@ -1884,7 +2141,7 @@
18842141 }
18852142
18862143 /* Read the terminator first to validate the length */
1887
- reg = wm_adsp_region_to_reg(mem, pos + len);
2144
+ reg = dsp->ops->region_to_reg(mem, pos + len);
18882145
18892146 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
18902147 if (ret != 0) {
....@@ -1904,7 +2161,7 @@
19042161 if (!alg)
19052162 return ERR_PTR(-ENOMEM);
19062163
1907
- reg = wm_adsp_region_to_reg(mem, pos);
2164
+ reg = dsp->ops->region_to_reg(mem, pos);
19082165
19092166 ret = regmap_raw_read(dsp->regmap, reg, alg, len);
19102167 if (ret != 0) {
....@@ -1964,6 +2221,47 @@
19642221 }
19652222 }
19662223
2224
+static void wmfw_parse_id_header(struct wm_adsp *dsp,
2225
+ struct wmfw_id_hdr *fw, int nalgs)
2226
+{
2227
+ dsp->fw_id = be32_to_cpu(fw->id);
2228
+ dsp->fw_id_version = be32_to_cpu(fw->ver);
2229
+
2230
+ adsp_info(dsp, "Firmware: %x v%d.%d.%d, %d algorithms\n",
2231
+ dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16,
2232
+ (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
2233
+ nalgs);
2234
+}
2235
+
2236
+static void wmfw_v3_parse_id_header(struct wm_adsp *dsp,
2237
+ struct wmfw_v3_id_hdr *fw, int nalgs)
2238
+{
2239
+ dsp->fw_id = be32_to_cpu(fw->id);
2240
+ dsp->fw_id_version = be32_to_cpu(fw->ver);
2241
+ dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id);
2242
+
2243
+ adsp_info(dsp, "Firmware: %x vendor: 0x%x v%d.%d.%d, %d algorithms\n",
2244
+ dsp->fw_id, dsp->fw_vendor_id,
2245
+ (dsp->fw_id_version & 0xff0000) >> 16,
2246
+ (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
2247
+ nalgs);
2248
+}
2249
+
2250
+static int wm_adsp_create_regions(struct wm_adsp *dsp, __be32 id, int nregions,
2251
+ int *type, __be32 *base)
2252
+{
2253
+ struct wm_adsp_alg_region *alg_region;
2254
+ int i;
2255
+
2256
+ for (i = 0; i < nregions; i++) {
2257
+ alg_region = wm_adsp_create_region(dsp, type[i], id, base[i]);
2258
+ if (IS_ERR(alg_region))
2259
+ return PTR_ERR(alg_region);
2260
+ }
2261
+
2262
+ return 0;
2263
+}
2264
+
19672265 static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
19682266 {
19692267 struct wmfw_adsp1_id_hdr adsp1_id;
....@@ -1987,13 +2285,8 @@
19872285 }
19882286
19892287 n_algs = be32_to_cpu(adsp1_id.n_algs);
1990
- dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
1991
- adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
1992
- dsp->fw_id,
1993
- (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
1994
- (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
1995
- be32_to_cpu(adsp1_id.fw.ver) & 0xff,
1996
- n_algs);
2288
+
2289
+ wmfw_parse_id_header(dsp, &adsp1_id.fw, n_algs);
19972290
19982291 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
19992292 adsp1_id.fw.id, adsp1_id.zm);
....@@ -2093,14 +2386,8 @@
20932386 }
20942387
20952388 n_algs = be32_to_cpu(adsp2_id.n_algs);
2096
- dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
2097
- dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver);
2098
- adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
2099
- dsp->fw_id,
2100
- (dsp->fw_id_version & 0xff0000) >> 16,
2101
- (dsp->fw_id_version & 0xff00) >> 8,
2102
- dsp->fw_id_version & 0xff,
2103
- n_algs);
2389
+
2390
+ wmfw_parse_id_header(dsp, &adsp2_id.fw, n_algs);
21042391
21052392 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
21062393 adsp2_id.fw.id, adsp2_id.xm);
....@@ -2205,6 +2492,78 @@
22052492 return ret;
22062493 }
22072494
2495
+static int wm_halo_create_regions(struct wm_adsp *dsp, __be32 id,
2496
+ __be32 xm_base, __be32 ym_base)
2497
+{
2498
+ int types[] = {
2499
+ WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED,
2500
+ WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED
2501
+ };
2502
+ __be32 bases[] = { xm_base, xm_base, ym_base, ym_base };
2503
+
2504
+ return wm_adsp_create_regions(dsp, id, ARRAY_SIZE(types), types, bases);
2505
+}
2506
+
2507
+static int wm_halo_setup_algs(struct wm_adsp *dsp)
2508
+{
2509
+ struct wmfw_halo_id_hdr halo_id;
2510
+ struct wmfw_halo_alg_hdr *halo_alg;
2511
+ const struct wm_adsp_region *mem;
2512
+ unsigned int pos, len;
2513
+ size_t n_algs;
2514
+ int i, ret;
2515
+
2516
+ mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
2517
+ if (WARN_ON(!mem))
2518
+ return -EINVAL;
2519
+
2520
+ ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id,
2521
+ sizeof(halo_id));
2522
+ if (ret != 0) {
2523
+ adsp_err(dsp, "Failed to read algorithm info: %d\n",
2524
+ ret);
2525
+ return ret;
2526
+ }
2527
+
2528
+ n_algs = be32_to_cpu(halo_id.n_algs);
2529
+
2530
+ wmfw_v3_parse_id_header(dsp, &halo_id.fw, n_algs);
2531
+
2532
+ ret = wm_halo_create_regions(dsp, halo_id.fw.id,
2533
+ halo_id.xm_base, halo_id.ym_base);
2534
+ if (ret)
2535
+ return ret;
2536
+
2537
+ /* Calculate offset and length in DSP words */
2538
+ pos = sizeof(halo_id) / sizeof(u32);
2539
+ len = (sizeof(*halo_alg) * n_algs) / sizeof(u32);
2540
+
2541
+ halo_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
2542
+ if (IS_ERR(halo_alg))
2543
+ return PTR_ERR(halo_alg);
2544
+
2545
+ for (i = 0; i < n_algs; i++) {
2546
+ adsp_info(dsp,
2547
+ "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
2548
+ i, be32_to_cpu(halo_alg[i].alg.id),
2549
+ (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
2550
+ (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
2551
+ be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
2552
+ be32_to_cpu(halo_alg[i].xm_base),
2553
+ be32_to_cpu(halo_alg[i].ym_base));
2554
+
2555
+ ret = wm_halo_create_regions(dsp, halo_alg[i].alg.id,
2556
+ halo_alg[i].xm_base,
2557
+ halo_alg[i].ym_base);
2558
+ if (ret)
2559
+ goto out;
2560
+ }
2561
+
2562
+out:
2563
+ kfree(halo_alg);
2564
+ return ret;
2565
+}
2566
+
22082567 static int wm_adsp_load_coeff(struct wm_adsp *dsp)
22092568 {
22102569 LIST_HEAD(buf_list);
....@@ -2285,6 +2644,7 @@
22852644 switch (type) {
22862645 case (WMFW_NAME_TEXT << 8):
22872646 case (WMFW_INFO_TEXT << 8):
2647
+ case (WMFW_METADATA << 8):
22882648 break;
22892649 case (WMFW_ABSOLUTE << 8):
22902650 /*
....@@ -2299,7 +2659,7 @@
22992659 adsp_err(dsp, "No ZM\n");
23002660 break;
23012661 }
2302
- reg = wm_adsp_region_to_reg(mem, 0);
2662
+ reg = dsp->ops->region_to_reg(mem, 0);
23032663
23042664 } else {
23052665 region_name = "register";
....@@ -2311,6 +2671,9 @@
23112671 case WMFW_ADSP1_ZM:
23122672 case WMFW_ADSP2_XM:
23132673 case WMFW_ADSP2_YM:
2674
+ case WMFW_HALO_XM_PACKED:
2675
+ case WMFW_HALO_YM_PACKED:
2676
+ case WMFW_HALO_PM_PACKED:
23142677 adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
23152678 file, blocks, le32_to_cpu(blk->len),
23162679 type, le32_to_cpu(blk->id));
....@@ -2325,7 +2688,7 @@
23252688 le32_to_cpu(blk->id));
23262689 if (alg_region) {
23272690 reg = alg_region->base;
2328
- reg = wm_adsp_region_to_reg(mem, reg);
2691
+ reg = dsp->ops->region_to_reg(mem, reg);
23292692 reg += offset;
23302693 } else {
23312694 adsp_err(dsp, "No %x for algorithm %x\n",
....@@ -2419,7 +2782,7 @@
24192782 return 0;
24202783 }
24212784
2422
-int wm_adsp1_init(struct wm_adsp *dsp)
2785
+static int wm_adsp_common_init(struct wm_adsp *dsp)
24232786 {
24242787 int ret;
24252788
....@@ -2428,10 +2791,20 @@
24282791 return ret;
24292792
24302793 INIT_LIST_HEAD(&dsp->alg_regions);
2794
+ INIT_LIST_HEAD(&dsp->ctl_list);
2795
+ INIT_LIST_HEAD(&dsp->compr_list);
2796
+ INIT_LIST_HEAD(&dsp->buffer_list);
24312797
24322798 mutex_init(&dsp->pwr_lock);
24332799
24342800 return 0;
2801
+}
2802
+
2803
+int wm_adsp1_init(struct wm_adsp *dsp)
2804
+{
2805
+ dsp->ops = &wm_adsp1_ops;
2806
+
2807
+ return wm_adsp_common_init(dsp);
24352808 }
24362809 EXPORT_SYMBOL_GPL(wm_adsp1_init);
24372810
....@@ -2550,22 +2923,10 @@
25502923 }
25512924 EXPORT_SYMBOL_GPL(wm_adsp1_event);
25522925
2553
-static int wm_adsp2_ena(struct wm_adsp *dsp)
2926
+static int wm_adsp2v2_enable_core(struct wm_adsp *dsp)
25542927 {
25552928 unsigned int val;
25562929 int ret, count;
2557
-
2558
- switch (dsp->rev) {
2559
- case 0:
2560
- ret = regmap_update_bits_async(dsp->regmap,
2561
- dsp->base + ADSP2_CONTROL,
2562
- ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2563
- if (ret != 0)
2564
- return ret;
2565
- break;
2566
- default:
2567
- break;
2568
- }
25692930
25702931 /* Wait for the RAM to start, should be near instantaneous */
25712932 for (count = 0; count < 10; ++count) {
....@@ -2589,7 +2950,78 @@
25892950 return 0;
25902951 }
25912952
2592
-static void wm_adsp2_boot_work(struct work_struct *work)
2953
+static int wm_adsp2_enable_core(struct wm_adsp *dsp)
2954
+{
2955
+ int ret;
2956
+
2957
+ ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
2958
+ ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2959
+ if (ret != 0)
2960
+ return ret;
2961
+
2962
+ return wm_adsp2v2_enable_core(dsp);
2963
+}
2964
+
2965
+static int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions)
2966
+{
2967
+ struct regmap *regmap = dsp->regmap;
2968
+ unsigned int code0, code1, lock_reg;
2969
+
2970
+ if (!(lock_regions & WM_ADSP2_REGION_ALL))
2971
+ return 0;
2972
+
2973
+ lock_regions &= WM_ADSP2_REGION_ALL;
2974
+ lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0;
2975
+
2976
+ while (lock_regions) {
2977
+ code0 = code1 = 0;
2978
+ if (lock_regions & BIT(0)) {
2979
+ code0 = ADSP2_LOCK_CODE_0;
2980
+ code1 = ADSP2_LOCK_CODE_1;
2981
+ }
2982
+ if (lock_regions & BIT(1)) {
2983
+ code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT;
2984
+ code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT;
2985
+ }
2986
+ regmap_write(regmap, lock_reg, code0);
2987
+ regmap_write(regmap, lock_reg, code1);
2988
+ lock_regions >>= 2;
2989
+ lock_reg += 2;
2990
+ }
2991
+
2992
+ return 0;
2993
+}
2994
+
2995
+static int wm_adsp2_enable_memory(struct wm_adsp *dsp)
2996
+{
2997
+ return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2998
+ ADSP2_MEM_ENA, ADSP2_MEM_ENA);
2999
+}
3000
+
3001
+static void wm_adsp2_disable_memory(struct wm_adsp *dsp)
3002
+{
3003
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3004
+ ADSP2_MEM_ENA, 0);
3005
+}
3006
+
3007
+static void wm_adsp2_disable_core(struct wm_adsp *dsp)
3008
+{
3009
+ regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
3010
+ regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
3011
+ regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
3012
+
3013
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3014
+ ADSP2_SYS_ENA, 0);
3015
+}
3016
+
3017
+static void wm_adsp2v2_disable_core(struct wm_adsp *dsp)
3018
+{
3019
+ regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
3020
+ regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
3021
+ regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0);
3022
+}
3023
+
3024
+static void wm_adsp_boot_work(struct work_struct *work)
25933025 {
25943026 struct wm_adsp *dsp = container_of(work,
25953027 struct wm_adsp,
....@@ -2598,20 +3030,23 @@
25983030
25993031 mutex_lock(&dsp->pwr_lock);
26003032
2601
- ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2602
- ADSP2_MEM_ENA, ADSP2_MEM_ENA);
2603
- if (ret != 0)
2604
- goto err_mutex;
3033
+ if (dsp->ops->enable_memory) {
3034
+ ret = dsp->ops->enable_memory(dsp);
3035
+ if (ret != 0)
3036
+ goto err_mutex;
3037
+ }
26053038
2606
- ret = wm_adsp2_ena(dsp);
2607
- if (ret != 0)
2608
- goto err_mem;
3039
+ if (dsp->ops->enable_core) {
3040
+ ret = dsp->ops->enable_core(dsp);
3041
+ if (ret != 0)
3042
+ goto err_mem;
3043
+ }
26093044
26103045 ret = wm_adsp_load(dsp);
26113046 if (ret != 0)
26123047 goto err_ena;
26133048
2614
- ret = wm_adsp2_setup_algs(dsp);
3049
+ ret = dsp->ops->setup_algs(dsp);
26153050 if (ret != 0)
26163051 goto err_ena;
26173052
....@@ -2624,17 +3059,8 @@
26243059 if (ret != 0)
26253060 goto err_ena;
26263061
2627
- switch (dsp->rev) {
2628
- case 0:
2629
- /* Turn DSP back off until we are ready to run */
2630
- ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2631
- ADSP2_SYS_ENA, 0);
2632
- if (ret != 0)
2633
- goto err_ena;
2634
- break;
2635
- default:
2636
- break;
2637
- }
3062
+ if (dsp->ops->disable_core)
3063
+ dsp->ops->disable_core(dsp);
26383064
26393065 dsp->booted = true;
26403066
....@@ -2643,35 +3069,62 @@
26433069 return;
26443070
26453071 err_ena:
2646
- regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2647
- ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
3072
+ if (dsp->ops->disable_core)
3073
+ dsp->ops->disable_core(dsp);
26483074 err_mem:
2649
- regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2650
- ADSP2_MEM_ENA, 0);
3075
+ if (dsp->ops->disable_memory)
3076
+ dsp->ops->disable_memory(dsp);
26513077 err_mutex:
26523078 mutex_unlock(&dsp->pwr_lock);
26533079 }
26543080
2655
-static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
3081
+static int wm_halo_configure_mpu(struct wm_adsp *dsp, unsigned int lock_regions)
26563082 {
3083
+ struct reg_sequence config[] = {
3084
+ { dsp->base + HALO_MPU_LOCK_CONFIG, 0x5555 },
3085
+ { dsp->base + HALO_MPU_LOCK_CONFIG, 0xAAAA },
3086
+ { dsp->base + HALO_MPU_XMEM_ACCESS_0, 0xFFFFFFFF },
3087
+ { dsp->base + HALO_MPU_YMEM_ACCESS_0, 0xFFFFFFFF },
3088
+ { dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions },
3089
+ { dsp->base + HALO_MPU_XREG_ACCESS_0, lock_regions },
3090
+ { dsp->base + HALO_MPU_YREG_ACCESS_0, lock_regions },
3091
+ { dsp->base + HALO_MPU_XMEM_ACCESS_1, 0xFFFFFFFF },
3092
+ { dsp->base + HALO_MPU_YMEM_ACCESS_1, 0xFFFFFFFF },
3093
+ { dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions },
3094
+ { dsp->base + HALO_MPU_XREG_ACCESS_1, lock_regions },
3095
+ { dsp->base + HALO_MPU_YREG_ACCESS_1, lock_regions },
3096
+ { dsp->base + HALO_MPU_XMEM_ACCESS_2, 0xFFFFFFFF },
3097
+ { dsp->base + HALO_MPU_YMEM_ACCESS_2, 0xFFFFFFFF },
3098
+ { dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions },
3099
+ { dsp->base + HALO_MPU_XREG_ACCESS_2, lock_regions },
3100
+ { dsp->base + HALO_MPU_YREG_ACCESS_2, lock_regions },
3101
+ { dsp->base + HALO_MPU_XMEM_ACCESS_3, 0xFFFFFFFF },
3102
+ { dsp->base + HALO_MPU_YMEM_ACCESS_3, 0xFFFFFFFF },
3103
+ { dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions },
3104
+ { dsp->base + HALO_MPU_XREG_ACCESS_3, lock_regions },
3105
+ { dsp->base + HALO_MPU_YREG_ACCESS_3, lock_regions },
3106
+ { dsp->base + HALO_MPU_LOCK_CONFIG, 0 },
3107
+ };
3108
+
3109
+ return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config));
3110
+}
3111
+
3112
+int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq)
3113
+{
3114
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3115
+ struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3116
+ struct wm_adsp *dsp = &dsps[w->shift];
26573117 int ret;
26583118
2659
- switch (dsp->rev) {
2660
- case 0:
2661
- ret = regmap_update_bits_async(dsp->regmap,
2662
- dsp->base + ADSP2_CLOCKING,
2663
- ADSP2_CLK_SEL_MASK,
2664
- freq << ADSP2_CLK_SEL_SHIFT);
2665
- if (ret) {
2666
- adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2667
- return;
2668
- }
2669
- break;
2670
- default:
2671
- /* clock is handled by parent codec driver */
2672
- break;
2673
- }
3119
+ ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING,
3120
+ ADSP2_CLK_SEL_MASK,
3121
+ freq << ADSP2_CLK_SEL_SHIFT);
3122
+ if (ret)
3123
+ adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
3124
+
3125
+ return ret;
26743126 }
3127
+EXPORT_SYMBOL_GPL(wm_adsp2_set_dspclk);
26753128
26763129 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
26773130 struct snd_ctl_elem_value *ucontrol)
....@@ -2718,19 +3171,18 @@
27183171
27193172 static void wm_adsp_stop_watchdog(struct wm_adsp *dsp)
27203173 {
2721
- switch (dsp->rev) {
2722
- case 0:
2723
- case 1:
2724
- return;
2725
- default:
2726
- regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG,
2727
- ADSP2_WDT_ENA_MASK, 0);
2728
- }
3174
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG,
3175
+ ADSP2_WDT_ENA_MASK, 0);
27293176 }
27303177
2731
-int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
2732
- struct snd_kcontrol *kcontrol, int event,
2733
- unsigned int freq)
3178
+static void wm_halo_stop_watchdog(struct wm_adsp *dsp)
3179
+{
3180
+ regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL,
3181
+ HALO_WDT_EN_MASK, 0);
3182
+}
3183
+
3184
+int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
3185
+ struct snd_kcontrol *kcontrol, int event)
27343186 {
27353187 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
27363188 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
....@@ -2739,7 +3191,6 @@
27393191
27403192 switch (event) {
27413193 case SND_SOC_DAPM_PRE_PMU:
2742
- wm_adsp2_set_dspclk(dsp, freq);
27433194 queue_work(system_unbound_wq, &dsp->boot_work);
27443195 break;
27453196 case SND_SOC_DAPM_PRE_PMD:
....@@ -2752,8 +3203,8 @@
27523203
27533204 dsp->booted = false;
27543205
2755
- regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2756
- ADSP2_MEM_ENA, 0);
3206
+ if (dsp->ops->disable_memory)
3207
+ dsp->ops->disable_memory(dsp);
27573208
27583209 list_for_each_entry(ctl, &dsp->ctl_list, list)
27593210 ctl->enabled = 0;
....@@ -2770,10 +3221,23 @@
27703221
27713222 return 0;
27723223 }
2773
-EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
3224
+EXPORT_SYMBOL_GPL(wm_adsp_early_event);
27743225
2775
-int wm_adsp2_event(struct snd_soc_dapm_widget *w,
2776
- struct snd_kcontrol *kcontrol, int event)
3226
+static int wm_adsp2_start_core(struct wm_adsp *dsp)
3227
+{
3228
+ return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3229
+ ADSP2_CORE_ENA | ADSP2_START,
3230
+ ADSP2_CORE_ENA | ADSP2_START);
3231
+}
3232
+
3233
+static void wm_adsp2_stop_core(struct wm_adsp *dsp)
3234
+{
3235
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3236
+ ADSP2_CORE_ENA | ADSP2_START, 0);
3237
+}
3238
+
3239
+int wm_adsp_event(struct snd_soc_dapm_widget *w,
3240
+ struct snd_kcontrol *kcontrol, int event)
27773241 {
27783242 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
27793243 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
....@@ -2791,23 +3255,31 @@
27913255 goto err;
27923256 }
27933257
2794
- ret = wm_adsp2_ena(dsp);
2795
- if (ret != 0)
2796
- goto err;
3258
+ if (dsp->ops->enable_core) {
3259
+ ret = dsp->ops->enable_core(dsp);
3260
+ if (ret != 0)
3261
+ goto err;
3262
+ }
27973263
27983264 /* Sync set controls */
27993265 ret = wm_coeff_sync_controls(dsp);
28003266 if (ret != 0)
28013267 goto err;
28023268
2803
- wm_adsp2_lock(dsp, dsp->lock_regions);
3269
+ if (dsp->ops->lock_memory) {
3270
+ ret = dsp->ops->lock_memory(dsp, dsp->lock_regions);
3271
+ if (ret != 0) {
3272
+ adsp_err(dsp, "Error configuring MPU: %d\n",
3273
+ ret);
3274
+ goto err;
3275
+ }
3276
+ }
28043277
2805
- ret = regmap_update_bits(dsp->regmap,
2806
- dsp->base + ADSP2_CONTROL,
2807
- ADSP2_CORE_ENA | ADSP2_START,
2808
- ADSP2_CORE_ENA | ADSP2_START);
2809
- if (ret != 0)
2810
- goto err;
3278
+ if (dsp->ops->start_core) {
3279
+ ret = dsp->ops->start_core(dsp);
3280
+ if (ret != 0)
3281
+ goto err;
3282
+ }
28113283
28123284 if (wm_adsp_fw[dsp->fw].num_caps != 0) {
28133285 ret = wm_adsp_buffer_init(dsp);
....@@ -2818,59 +3290,32 @@
28183290 dsp->running = true;
28193291
28203292 mutex_unlock(&dsp->pwr_lock);
2821
-
28223293 break;
28233294
28243295 case SND_SOC_DAPM_PRE_PMD:
28253296 /* Tell the firmware to cleanup */
28263297 wm_adsp_signal_event_controls(dsp, WM_ADSP_FW_EVENT_SHUTDOWN);
28273298
2828
- wm_adsp_stop_watchdog(dsp);
3299
+ if (dsp->ops->stop_watchdog)
3300
+ dsp->ops->stop_watchdog(dsp);
28293301
28303302 /* Log firmware state, it can be useful for analysis */
2831
- switch (dsp->rev) {
2832
- case 0:
2833
- wm_adsp2_show_fw_status(dsp);
2834
- break;
2835
- default:
2836
- wm_adsp2v2_show_fw_status(dsp);
2837
- break;
2838
- }
3303
+ if (dsp->ops->show_fw_status)
3304
+ dsp->ops->show_fw_status(dsp);
28393305
28403306 mutex_lock(&dsp->pwr_lock);
28413307
28423308 dsp->running = false;
28433309
2844
- regmap_update_bits(dsp->regmap,
2845
- dsp->base + ADSP2_CONTROL,
2846
- ADSP2_CORE_ENA | ADSP2_START, 0);
2847
-
2848
- /* Make sure DMAs are quiesced */
2849
- switch (dsp->rev) {
2850
- case 0:
2851
- regmap_write(dsp->regmap,
2852
- dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2853
- regmap_write(dsp->regmap,
2854
- dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2855
- regmap_write(dsp->regmap,
2856
- dsp->base + ADSP2_WDMA_CONFIG_2, 0);
2857
-
2858
- regmap_update_bits(dsp->regmap,
2859
- dsp->base + ADSP2_CONTROL,
2860
- ADSP2_SYS_ENA, 0);
2861
- break;
2862
- default:
2863
- regmap_write(dsp->regmap,
2864
- dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2865
- regmap_write(dsp->regmap,
2866
- dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2867
- regmap_write(dsp->regmap,
2868
- dsp->base + ADSP2V2_WDMA_CONFIG_2, 0);
2869
- break;
2870
- }
3310
+ if (dsp->ops->stop_core)
3311
+ dsp->ops->stop_core(dsp);
3312
+ if (dsp->ops->disable_core)
3313
+ dsp->ops->disable_core(dsp);
28713314
28723315 if (wm_adsp_fw[dsp->fw].num_caps != 0)
28733316 wm_adsp_buffer_free(dsp);
3317
+
3318
+ dsp->fatal_error = false;
28743319
28753320 mutex_unlock(&dsp->pwr_lock);
28763321
....@@ -2883,12 +3328,31 @@
28833328
28843329 return 0;
28853330 err:
2886
- regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2887
- ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
3331
+ if (dsp->ops->stop_core)
3332
+ dsp->ops->stop_core(dsp);
3333
+ if (dsp->ops->disable_core)
3334
+ dsp->ops->disable_core(dsp);
28883335 mutex_unlock(&dsp->pwr_lock);
28893336 return ret;
28903337 }
2891
-EXPORT_SYMBOL_GPL(wm_adsp2_event);
3338
+EXPORT_SYMBOL_GPL(wm_adsp_event);
3339
+
3340
+static int wm_halo_start_core(struct wm_adsp *dsp)
3341
+{
3342
+ return regmap_update_bits(dsp->regmap,
3343
+ dsp->base + HALO_CCM_CORE_CONTROL,
3344
+ HALO_CORE_EN, HALO_CORE_EN);
3345
+}
3346
+
3347
+static void wm_halo_stop_core(struct wm_adsp *dsp)
3348
+{
3349
+ regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
3350
+ HALO_CORE_EN, 0);
3351
+
3352
+ /* reset halo core with CORE_SOFT_RESET */
3353
+ regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET,
3354
+ HALO_CORE_SOFT_RESET_MASK, 1);
3355
+}
28923356
28933357 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component)
28943358 {
....@@ -2917,7 +3381,7 @@
29173381 {
29183382 int ret;
29193383
2920
- ret = wm_adsp_create_name(dsp);
3384
+ ret = wm_adsp_common_init(dsp);
29213385 if (ret)
29223386 return ret;
29233387
....@@ -2934,20 +3398,38 @@
29343398 "Failed to clear memory retention: %d\n", ret);
29353399 return ret;
29363400 }
3401
+
3402
+ dsp->ops = &wm_adsp2_ops[0];
3403
+ break;
3404
+ case 1:
3405
+ dsp->ops = &wm_adsp2_ops[1];
29373406 break;
29383407 default:
3408
+ dsp->ops = &wm_adsp2_ops[2];
29393409 break;
29403410 }
29413411
2942
- INIT_LIST_HEAD(&dsp->alg_regions);
2943
- INIT_LIST_HEAD(&dsp->ctl_list);
2944
- INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work);
2945
-
2946
- mutex_init(&dsp->pwr_lock);
3412
+ INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
29473413
29483414 return 0;
29493415 }
29503416 EXPORT_SYMBOL_GPL(wm_adsp2_init);
3417
+
3418
+int wm_halo_init(struct wm_adsp *dsp)
3419
+{
3420
+ int ret;
3421
+
3422
+ ret = wm_adsp_common_init(dsp);
3423
+ if (ret)
3424
+ return ret;
3425
+
3426
+ dsp->ops = &wm_halo_ops;
3427
+
3428
+ INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
3429
+
3430
+ return 0;
3431
+}
3432
+EXPORT_SYMBOL_GPL(wm_halo_init);
29513433
29523434 void wm_adsp2_remove(struct wm_adsp *dsp)
29533435 {
....@@ -2969,15 +3451,23 @@
29693451
29703452 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
29713453 {
2972
- /*
2973
- * Note this will be more complex once each DSP can support multiple
2974
- * streams
2975
- */
2976
- if (!compr->dsp->buffer)
3454
+ struct wm_adsp_compr_buf *buf = NULL, *tmp;
3455
+
3456
+ if (compr->dsp->fatal_error)
29773457 return -EINVAL;
29783458
2979
- compr->buf = compr->dsp->buffer;
2980
- compr->buf->compr = compr;
3459
+ list_for_each_entry(tmp, &compr->dsp->buffer_list, list) {
3460
+ if (!tmp->name || !strcmp(compr->name, tmp->name)) {
3461
+ buf = tmp;
3462
+ break;
3463
+ }
3464
+ }
3465
+
3466
+ if (!buf)
3467
+ return -EINVAL;
3468
+
3469
+ compr->buf = buf;
3470
+ buf->compr = compr;
29813471
29823472 return 0;
29833473 }
....@@ -2999,28 +3489,33 @@
29993489
30003490 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
30013491 {
3002
- struct wm_adsp_compr *compr;
3492
+ struct wm_adsp_compr *compr, *tmp;
3493
+ struct snd_soc_pcm_runtime *rtd = stream->private_data;
30033494 int ret = 0;
30043495
30053496 mutex_lock(&dsp->pwr_lock);
30063497
30073498 if (wm_adsp_fw[dsp->fw].num_caps == 0) {
3008
- adsp_err(dsp, "Firmware does not support compressed API\n");
3499
+ adsp_err(dsp, "%s: Firmware does not support compressed API\n",
3500
+ asoc_rtd_to_codec(rtd, 0)->name);
30093501 ret = -ENXIO;
30103502 goto out;
30113503 }
30123504
30133505 if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
3014
- adsp_err(dsp, "Firmware does not support stream direction\n");
3506
+ adsp_err(dsp, "%s: Firmware does not support stream direction\n",
3507
+ asoc_rtd_to_codec(rtd, 0)->name);
30153508 ret = -EINVAL;
30163509 goto out;
30173510 }
30183511
3019
- if (dsp->compr) {
3020
- /* It is expect this limitation will be removed in future */
3021
- adsp_err(dsp, "Only a single stream supported per DSP\n");
3022
- ret = -EBUSY;
3023
- goto out;
3512
+ list_for_each_entry(tmp, &dsp->compr_list, list) {
3513
+ if (!strcmp(tmp->name, asoc_rtd_to_codec(rtd, 0)->name)) {
3514
+ adsp_err(dsp, "%s: Only a single stream supported per dai\n",
3515
+ asoc_rtd_to_codec(rtd, 0)->name);
3516
+ ret = -EBUSY;
3517
+ goto out;
3518
+ }
30243519 }
30253520
30263521 compr = kzalloc(sizeof(*compr), GFP_KERNEL);
....@@ -3031,8 +3526,9 @@
30313526
30323527 compr->dsp = dsp;
30333528 compr->stream = stream;
3529
+ compr->name = asoc_rtd_to_codec(rtd, 0)->name;
30343530
3035
- dsp->compr = compr;
3531
+ list_add_tail(&compr->list, &dsp->compr_list);
30363532
30373533 stream->runtime->private_data = compr;
30383534
....@@ -3043,7 +3539,8 @@
30433539 }
30443540 EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
30453541
3046
-int wm_adsp_compr_free(struct snd_compr_stream *stream)
3542
+int wm_adsp_compr_free(struct snd_soc_component *component,
3543
+ struct snd_compr_stream *stream)
30473544 {
30483545 struct wm_adsp_compr *compr = stream->runtime->private_data;
30493546 struct wm_adsp *dsp = compr->dsp;
....@@ -3051,7 +3548,7 @@
30513548 mutex_lock(&dsp->pwr_lock);
30523549
30533550 wm_adsp_compr_detach(compr);
3054
- dsp->compr = NULL;
3551
+ list_del(&compr->list);
30553552
30563553 kfree(compr->raw_buf);
30573554 kfree(compr);
....@@ -3076,9 +3573,9 @@
30763573 params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
30773574 params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
30783575 params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) {
3079
- adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n",
3080
- params->buffer.fragment_size,
3081
- params->buffer.fragments);
3576
+ compr_err(compr, "Invalid buffer fragsize=%d fragments=%d\n",
3577
+ params->buffer.fragment_size,
3578
+ params->buffer.fragments);
30823579
30833580 return -EINVAL;
30843581 }
....@@ -3106,9 +3603,9 @@
31063603 return 0;
31073604 }
31083605
3109
- adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
3110
- params->codec.id, params->codec.ch_in, params->codec.ch_out,
3111
- params->codec.sample_rate, params->codec.format);
3606
+ compr_err(compr, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
3607
+ params->codec.id, params->codec.ch_in, params->codec.ch_out,
3608
+ params->codec.sample_rate, params->codec.format);
31123609 return -EINVAL;
31133610 }
31143611
....@@ -3117,7 +3614,8 @@
31173614 return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE;
31183615 }
31193616
3120
-int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
3617
+int wm_adsp_compr_set_params(struct snd_soc_component *component,
3618
+ struct snd_compr_stream *stream,
31213619 struct snd_compr_params *params)
31223620 {
31233621 struct wm_adsp_compr *compr = stream->runtime->private_data;
....@@ -3130,8 +3628,8 @@
31303628
31313629 compr->size = params->buffer;
31323630
3133
- adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n",
3134
- compr->size.fragment_size, compr->size.fragments);
3631
+ compr_dbg(compr, "fragment_size=%d fragments=%d\n",
3632
+ compr->size.fragment_size, compr->size.fragments);
31353633
31363634 size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
31373635 compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
....@@ -3144,7 +3642,8 @@
31443642 }
31453643 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
31463644
3147
-int wm_adsp_compr_get_caps(struct snd_compr_stream *stream,
3645
+int wm_adsp_compr_get_caps(struct snd_soc_component *component,
3646
+ struct snd_compr_stream *stream,
31483647 struct snd_compr_caps *caps)
31493648 {
31503649 struct wm_adsp_compr *compr = stream->runtime->private_data;
....@@ -3179,7 +3678,7 @@
31793678 if (!mem)
31803679 return -EINVAL;
31813680
3182
- reg = wm_adsp_region_to_reg(mem, mem_addr);
3681
+ reg = dsp->ops->region_to_reg(mem, mem_addr);
31833682
31843683 ret = regmap_raw_read(dsp->regmap, reg, data,
31853684 sizeof(*data) * num_words);
....@@ -3207,7 +3706,7 @@
32073706 if (!mem)
32083707 return -EINVAL;
32093708
3210
- reg = wm_adsp_region_to_reg(mem, mem_addr);
3709
+ reg = dsp->ops->region_to_reg(mem, mem_addr);
32113710
32123711 data = cpu_to_be32(data & 0x00ffffffu);
32133712
....@@ -3217,109 +3716,30 @@
32173716 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
32183717 unsigned int field_offset, u32 *data)
32193718 {
3220
- return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM,
3719
+ return wm_adsp_read_data_word(buf->dsp, buf->host_buf_mem_type,
32213720 buf->host_buf_ptr + field_offset, data);
32223721 }
32233722
32243723 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
32253724 unsigned int field_offset, u32 data)
32263725 {
3227
- return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM,
3726
+ return wm_adsp_write_data_word(buf->dsp, buf->host_buf_mem_type,
32283727 buf->host_buf_ptr + field_offset, data);
32293728 }
32303729
3231
-static int wm_adsp_legacy_host_buf_addr(struct wm_adsp_compr_buf *buf)
3730
+static void wm_adsp_remove_padding(u32 *buf, int nwords, int data_word_size)
32323731 {
3233
- struct wm_adsp_alg_region *alg_region;
3234
- struct wm_adsp *dsp = buf->dsp;
3235
- u32 xmalg, addr, magic;
3236
- int i, ret;
3732
+ u8 *pack_in = (u8 *)buf;
3733
+ u8 *pack_out = (u8 *)buf;
3734
+ int i, j;
32373735
3238
- alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
3239
- xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32);
3736
+ /* Remove the padding bytes from the data read from the DSP */
3737
+ for (i = 0; i < nwords; i++) {
3738
+ for (j = 0; j < data_word_size; j++)
3739
+ *pack_out++ = *pack_in++;
32403740
3241
- addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
3242
- ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic);
3243
- if (ret < 0)
3244
- return ret;
3245
-
3246
- if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
3247
- return -EINVAL;
3248
-
3249
- addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
3250
- for (i = 0; i < 5; ++i) {
3251
- ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr,
3252
- &buf->host_buf_ptr);
3253
- if (ret < 0)
3254
- return ret;
3255
-
3256
- if (buf->host_buf_ptr)
3257
- break;
3258
-
3259
- usleep_range(1000, 2000);
3741
+ pack_in += sizeof(*buf) - data_word_size;
32603742 }
3261
-
3262
- if (!buf->host_buf_ptr)
3263
- return -EIO;
3264
-
3265
- adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr);
3266
-
3267
- return 0;
3268
-}
3269
-
3270
-static struct wm_coeff_ctl *
3271
-wm_adsp_find_host_buffer_ctrl(struct wm_adsp_compr_buf *buf)
3272
-{
3273
- struct wm_adsp *dsp = buf->dsp;
3274
- struct wm_coeff_ctl *ctl;
3275
-
3276
- list_for_each_entry(ctl, &dsp->ctl_list, list) {
3277
- if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
3278
- continue;
3279
-
3280
- if (!ctl->enabled)
3281
- continue;
3282
-
3283
- return ctl;
3284
- }
3285
-
3286
- return NULL;
3287
-}
3288
-
3289
-static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
3290
-{
3291
- struct wm_adsp *dsp = buf->dsp;
3292
- struct wm_coeff_ctl *ctl;
3293
- unsigned int reg;
3294
- u32 val;
3295
- int i, ret;
3296
-
3297
- ctl = wm_adsp_find_host_buffer_ctrl(buf);
3298
- if (!ctl)
3299
- return wm_adsp_legacy_host_buf_addr(buf);
3300
-
3301
- ret = wm_coeff_base_reg(ctl, &reg);
3302
- if (ret)
3303
- return ret;
3304
-
3305
- for (i = 0; i < 5; ++i) {
3306
- ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
3307
- if (ret < 0)
3308
- return ret;
3309
-
3310
- if (val)
3311
- break;
3312
-
3313
- usleep_range(1000, 2000);
3314
- }
3315
-
3316
- if (!val)
3317
- return -EIO;
3318
-
3319
- buf->host_buf_ptr = be32_to_cpu(val);
3320
- adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr);
3321
-
3322
- return 0;
33233743 }
33243744
33253745 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
....@@ -3328,6 +3748,11 @@
33283748 struct wm_adsp_buffer_region *region;
33293749 u32 offset = 0;
33303750 int i, ret;
3751
+
3752
+ buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions),
3753
+ GFP_KERNEL);
3754
+ if (!buf->regions)
3755
+ return -ENOMEM;
33313756
33323757 for (i = 0; i < caps->num_regions; ++i) {
33333758 region = &buf->regions[i];
....@@ -3347,10 +3772,10 @@
33473772
33483773 region->cumulative_size = offset;
33493774
3350
- adsp_dbg(buf->dsp,
3351
- "region=%d type=%d base=%04x off=%04x size=%04x\n",
3352
- i, region->mem_type, region->base_addr,
3353
- region->offset, region->cumulative_size);
3775
+ compr_dbg(buf,
3776
+ "region=%d type=%d base=%08x off=%08x size=%08x\n",
3777
+ i, region->mem_type, region->base_addr,
3778
+ region->offset, region->cumulative_size);
33543779 }
33553780
33563781 return 0;
....@@ -3363,70 +3788,235 @@
33633788 buf->avail = 0;
33643789 }
33653790
3366
-static int wm_adsp_buffer_init(struct wm_adsp *dsp)
3791
+static struct wm_adsp_compr_buf *wm_adsp_buffer_alloc(struct wm_adsp *dsp)
33673792 {
33683793 struct wm_adsp_compr_buf *buf;
3369
- int ret;
33703794
33713795 buf = kzalloc(sizeof(*buf), GFP_KERNEL);
33723796 if (!buf)
3373
- return -ENOMEM;
3797
+ return NULL;
33743798
33753799 buf->dsp = dsp;
33763800
33773801 wm_adsp_buffer_clear(buf);
33783802
3379
- ret = wm_adsp_buffer_locate(buf);
3380
- if (ret < 0) {
3381
- adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret);
3382
- goto err_buffer;
3803
+ list_add_tail(&buf->list, &dsp->buffer_list);
3804
+
3805
+ return buf;
3806
+}
3807
+
3808
+static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
3809
+{
3810
+ struct wm_adsp_alg_region *alg_region;
3811
+ struct wm_adsp_compr_buf *buf;
3812
+ u32 xmalg, addr, magic;
3813
+ int i, ret;
3814
+
3815
+ alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
3816
+ if (!alg_region) {
3817
+ adsp_err(dsp, "No algorithm region found\n");
3818
+ return -EINVAL;
33833819 }
33843820
3385
- buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions,
3386
- sizeof(*buf->regions), GFP_KERNEL);
3387
- if (!buf->regions) {
3388
- ret = -ENOMEM;
3389
- goto err_buffer;
3821
+ buf = wm_adsp_buffer_alloc(dsp);
3822
+ if (!buf)
3823
+ return -ENOMEM;
3824
+
3825
+ xmalg = dsp->ops->sys_config_size / sizeof(__be32);
3826
+
3827
+ addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
3828
+ ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic);
3829
+ if (ret < 0)
3830
+ return ret;
3831
+
3832
+ if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
3833
+ return -ENODEV;
3834
+
3835
+ addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
3836
+ for (i = 0; i < 5; ++i) {
3837
+ ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr,
3838
+ &buf->host_buf_ptr);
3839
+ if (ret < 0)
3840
+ return ret;
3841
+
3842
+ if (buf->host_buf_ptr)
3843
+ break;
3844
+
3845
+ usleep_range(1000, 2000);
33903846 }
3847
+
3848
+ if (!buf->host_buf_ptr)
3849
+ return -EIO;
3850
+
3851
+ buf->host_buf_mem_type = WMFW_ADSP2_XM;
33913852
33923853 ret = wm_adsp_buffer_populate(buf);
3393
- if (ret < 0) {
3394
- adsp_err(dsp, "Failed to populate host buffer: %d\n", ret);
3395
- goto err_regions;
3854
+ if (ret < 0)
3855
+ return ret;
3856
+
3857
+ compr_dbg(buf, "legacy host_buf_ptr=%x\n", buf->host_buf_ptr);
3858
+
3859
+ return 0;
3860
+}
3861
+
3862
+static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
3863
+{
3864
+ struct wm_adsp_host_buf_coeff_v1 coeff_v1;
3865
+ struct wm_adsp_compr_buf *buf;
3866
+ unsigned int val, reg;
3867
+ int ret, i;
3868
+
3869
+ ret = wm_coeff_base_reg(ctl, &reg);
3870
+ if (ret)
3871
+ return ret;
3872
+
3873
+ for (i = 0; i < 5; ++i) {
3874
+ ret = regmap_raw_read(ctl->dsp->regmap, reg, &val, sizeof(val));
3875
+ if (ret < 0)
3876
+ return ret;
3877
+
3878
+ if (val)
3879
+ break;
3880
+
3881
+ usleep_range(1000, 2000);
33963882 }
33973883
3398
- dsp->buffer = buf;
3884
+ if (!val) {
3885
+ adsp_err(ctl->dsp, "Failed to acquire host buffer\n");
3886
+ return -EIO;
3887
+ }
3888
+
3889
+ buf = wm_adsp_buffer_alloc(ctl->dsp);
3890
+ if (!buf)
3891
+ return -ENOMEM;
3892
+
3893
+ buf->host_buf_mem_type = ctl->alg_region.type;
3894
+ buf->host_buf_ptr = be32_to_cpu(val);
3895
+
3896
+ ret = wm_adsp_buffer_populate(buf);
3897
+ if (ret < 0)
3898
+ return ret;
3899
+
3900
+ /*
3901
+ * v0 host_buffer coefficients didn't have versioning, so if the
3902
+ * control is one word, assume version 0.
3903
+ */
3904
+ if (ctl->len == 4) {
3905
+ compr_dbg(buf, "host_buf_ptr=%x\n", buf->host_buf_ptr);
3906
+ return 0;
3907
+ }
3908
+
3909
+ ret = regmap_raw_read(ctl->dsp->regmap, reg, &coeff_v1,
3910
+ sizeof(coeff_v1));
3911
+ if (ret < 0)
3912
+ return ret;
3913
+
3914
+ coeff_v1.versions = be32_to_cpu(coeff_v1.versions);
3915
+ val = coeff_v1.versions & HOST_BUF_COEFF_COMPAT_VER_MASK;
3916
+ val >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
3917
+
3918
+ if (val > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
3919
+ adsp_err(ctl->dsp,
3920
+ "Host buffer coeff ver %u > supported version %u\n",
3921
+ val, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
3922
+ return -EINVAL;
3923
+ }
3924
+
3925
+ for (i = 0; i < ARRAY_SIZE(coeff_v1.name); i++)
3926
+ coeff_v1.name[i] = be32_to_cpu(coeff_v1.name[i]);
3927
+
3928
+ wm_adsp_remove_padding((u32 *)&coeff_v1.name,
3929
+ ARRAY_SIZE(coeff_v1.name),
3930
+ WM_ADSP_DATA_WORD_SIZE);
3931
+
3932
+ buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part,
3933
+ (char *)&coeff_v1.name);
3934
+
3935
+ compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
3936
+ buf->host_buf_ptr, val);
3937
+
3938
+ return val;
3939
+}
3940
+
3941
+static int wm_adsp_buffer_init(struct wm_adsp *dsp)
3942
+{
3943
+ struct wm_coeff_ctl *ctl;
3944
+ int ret;
3945
+
3946
+ list_for_each_entry(ctl, &dsp->ctl_list, list) {
3947
+ if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
3948
+ continue;
3949
+
3950
+ if (!ctl->enabled)
3951
+ continue;
3952
+
3953
+ ret = wm_adsp_buffer_parse_coeff(ctl);
3954
+ if (ret < 0) {
3955
+ adsp_err(dsp, "Failed to parse coeff: %d\n", ret);
3956
+ goto error;
3957
+ } else if (ret == 0) {
3958
+ /* Only one buffer supported for version 0 */
3959
+ return 0;
3960
+ }
3961
+ }
3962
+
3963
+ if (list_empty(&dsp->buffer_list)) {
3964
+ /* Fall back to legacy support */
3965
+ ret = wm_adsp_buffer_parse_legacy(dsp);
3966
+ if (ret) {
3967
+ adsp_err(dsp, "Failed to parse legacy: %d\n", ret);
3968
+ goto error;
3969
+ }
3970
+ }
33993971
34003972 return 0;
34013973
3402
-err_regions:
3403
- kfree(buf->regions);
3404
-err_buffer:
3405
- kfree(buf);
3974
+error:
3975
+ wm_adsp_buffer_free(dsp);
34063976 return ret;
34073977 }
34083978
34093979 static int wm_adsp_buffer_free(struct wm_adsp *dsp)
34103980 {
3411
- if (dsp->buffer) {
3412
- wm_adsp_compr_detach(dsp->buffer->compr);
3981
+ struct wm_adsp_compr_buf *buf, *tmp;
34133982
3414
- kfree(dsp->buffer->regions);
3415
- kfree(dsp->buffer);
3983
+ list_for_each_entry_safe(buf, tmp, &dsp->buffer_list, list) {
3984
+ wm_adsp_compr_detach(buf->compr);
34163985
3417
- dsp->buffer = NULL;
3986
+ kfree(buf->name);
3987
+ kfree(buf->regions);
3988
+ list_del(&buf->list);
3989
+ kfree(buf);
34183990 }
34193991
34203992 return 0;
34213993 }
34223994
3423
-int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
3995
+static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
3996
+{
3997
+ int ret;
3998
+
3999
+ ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
4000
+ if (ret < 0) {
4001
+ compr_err(buf, "Failed to check buffer error: %d\n", ret);
4002
+ return ret;
4003
+ }
4004
+ if (buf->error != 0) {
4005
+ compr_err(buf, "Buffer error occurred: %d\n", buf->error);
4006
+ return -EIO;
4007
+ }
4008
+
4009
+ return 0;
4010
+}
4011
+
4012
+int wm_adsp_compr_trigger(struct snd_soc_component *component,
4013
+ struct snd_compr_stream *stream, int cmd)
34244014 {
34254015 struct wm_adsp_compr *compr = stream->runtime->private_data;
34264016 struct wm_adsp *dsp = compr->dsp;
34274017 int ret = 0;
34284018
3429
- adsp_dbg(dsp, "Trigger: %d\n", cmd);
4019
+ compr_dbg(compr, "Trigger: %d\n", cmd);
34304020
34314021 mutex_lock(&dsp->pwr_lock);
34324022
....@@ -3435,19 +4025,23 @@
34354025 if (!wm_adsp_compr_attached(compr)) {
34364026 ret = wm_adsp_compr_attach(compr);
34374027 if (ret < 0) {
3438
- adsp_err(dsp, "Failed to link buffer and stream: %d\n",
3439
- ret);
4028
+ compr_err(compr, "Failed to link buffer and stream: %d\n",
4029
+ ret);
34404030 break;
34414031 }
34424032 }
4033
+
4034
+ ret = wm_adsp_buffer_get_error(compr->buf);
4035
+ if (ret < 0)
4036
+ break;
34434037
34444038 /* Trigger the IRQ at one fragment of data */
34454039 ret = wm_adsp_buffer_write(compr->buf,
34464040 HOST_BUFFER_FIELD(high_water_mark),
34474041 wm_adsp_compr_frag_words(compr));
34484042 if (ret < 0) {
3449
- adsp_err(dsp, "Failed to set high water mark: %d\n",
3450
- ret);
4043
+ compr_err(compr, "Failed to set high water mark: %d\n",
4044
+ ret);
34514045 break;
34524046 }
34534047 break;
....@@ -3490,7 +4084,7 @@
34904084 read_index = sign_extend32(next_read_index, 23);
34914085
34924086 if (read_index < 0) {
3493
- adsp_dbg(buf->dsp, "Avail check on unstarted stream\n");
4087
+ compr_dbg(buf, "Avail check on unstarted stream\n");
34944088 return 0;
34954089 }
34964090
....@@ -3508,27 +4102,10 @@
35084102 if (avail < 0)
35094103 avail += wm_adsp_buffer_size(buf);
35104104
3511
- adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
3512
- buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE);
4105
+ compr_dbg(buf, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
4106
+ buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE);
35134107
35144108 buf->avail = avail;
3515
-
3516
- return 0;
3517
-}
3518
-
3519
-static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
3520
-{
3521
- int ret;
3522
-
3523
- ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
3524
- if (ret < 0) {
3525
- adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret);
3526
- return ret;
3527
- }
3528
- if (buf->error != 0) {
3529
- adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error);
3530
- return -EIO;
3531
- }
35324109
35334110 return 0;
35344111 }
....@@ -3541,39 +4118,40 @@
35414118
35424119 mutex_lock(&dsp->pwr_lock);
35434120
3544
- buf = dsp->buffer;
3545
- compr = dsp->compr;
3546
-
3547
- if (!buf) {
4121
+ if (list_empty(&dsp->buffer_list)) {
35484122 ret = -ENODEV;
35494123 goto out;
35504124 }
35514125
35524126 adsp_dbg(dsp, "Handling buffer IRQ\n");
35534127
3554
- ret = wm_adsp_buffer_get_error(buf);
3555
- if (ret < 0)
3556
- goto out_notify; /* Wake poll to report error */
4128
+ list_for_each_entry(buf, &dsp->buffer_list, list) {
4129
+ compr = buf->compr;
35574130
3558
- ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
3559
- &buf->irq_count);
3560
- if (ret < 0) {
3561
- adsp_err(dsp, "Failed to get irq_count: %d\n", ret);
3562
- goto out;
3563
- }
4131
+ ret = wm_adsp_buffer_get_error(buf);
4132
+ if (ret < 0)
4133
+ goto out_notify; /* Wake poll to report error */
35644134
3565
- ret = wm_adsp_buffer_update_avail(buf);
3566
- if (ret < 0) {
3567
- adsp_err(dsp, "Error reading avail: %d\n", ret);
3568
- goto out;
3569
- }
4135
+ ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
4136
+ &buf->irq_count);
4137
+ if (ret < 0) {
4138
+ compr_err(buf, "Failed to get irq_count: %d\n", ret);
4139
+ goto out;
4140
+ }
35704141
3571
- if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
3572
- ret = WM_ADSP_COMPR_VOICE_TRIGGER;
4142
+ ret = wm_adsp_buffer_update_avail(buf);
4143
+ if (ret < 0) {
4144
+ compr_err(buf, "Error reading avail: %d\n", ret);
4145
+ goto out;
4146
+ }
4147
+
4148
+ if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
4149
+ ret = WM_ADSP_COMPR_VOICE_TRIGGER;
35734150
35744151 out_notify:
3575
- if (compr && compr->stream)
3576
- snd_compr_fragment_elapsed(compr->stream);
4152
+ if (compr && compr->stream)
4153
+ snd_compr_fragment_elapsed(compr->stream);
4154
+ }
35774155
35784156 out:
35794157 mutex_unlock(&dsp->pwr_lock);
....@@ -3587,8 +4165,7 @@
35874165 if (buf->irq_count & 0x01)
35884166 return 0;
35894167
3590
- adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n",
3591
- buf->irq_count);
4168
+ compr_dbg(buf, "Enable IRQ(0x%x) for next fragment\n", buf->irq_count);
35924169
35934170 buf->irq_count |= 0x01;
35944171
....@@ -3596,7 +4173,8 @@
35964173 buf->irq_count);
35974174 }
35984175
3599
-int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
4176
+int wm_adsp_compr_pointer(struct snd_soc_component *component,
4177
+ struct snd_compr_stream *stream,
36004178 struct snd_compr_tstamp *tstamp)
36014179 {
36024180 struct wm_adsp_compr *compr = stream->runtime->private_data;
....@@ -3604,13 +4182,13 @@
36044182 struct wm_adsp_compr_buf *buf;
36054183 int ret = 0;
36064184
3607
- adsp_dbg(dsp, "Pointer request\n");
4185
+ compr_dbg(compr, "Pointer request\n");
36084186
36094187 mutex_lock(&dsp->pwr_lock);
36104188
36114189 buf = compr->buf;
36124190
3613
- if (!compr->buf || compr->buf->error) {
4191
+ if (dsp->fatal_error || !buf || buf->error) {
36144192 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
36154193 ret = -EIO;
36164194 goto out;
....@@ -3619,7 +4197,7 @@
36194197 if (buf->avail < wm_adsp_compr_frag_words(compr)) {
36204198 ret = wm_adsp_buffer_update_avail(buf);
36214199 if (ret < 0) {
3622
- adsp_err(dsp, "Error reading avail: %d\n", ret);
4200
+ compr_err(compr, "Error reading avail: %d\n", ret);
36234201 goto out;
36244202 }
36254203
....@@ -3630,7 +4208,7 @@
36304208 if (buf->avail < wm_adsp_compr_frag_words(compr)) {
36314209 ret = wm_adsp_buffer_get_error(buf);
36324210 if (ret < 0) {
3633
- if (compr->buf->error)
4211
+ if (buf->error)
36344212 snd_compr_stop_error(stream,
36354213 SNDRV_PCM_STATE_XRUN);
36364214 goto out;
....@@ -3638,9 +4216,8 @@
36384216
36394217 ret = wm_adsp_buffer_reenable_irq(buf);
36404218 if (ret < 0) {
3641
- adsp_err(dsp,
3642
- "Failed to re-enable buffer IRQ: %d\n",
3643
- ret);
4219
+ compr_err(compr, "Failed to re-enable buffer IRQ: %d\n",
4220
+ ret);
36444221 goto out;
36454222 }
36464223 }
....@@ -3660,11 +4237,9 @@
36604237 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
36614238 {
36624239 struct wm_adsp_compr_buf *buf = compr->buf;
3663
- u8 *pack_in = (u8 *)compr->raw_buf;
3664
- u8 *pack_out = (u8 *)compr->raw_buf;
36654240 unsigned int adsp_addr;
36664241 int mem_type, nwords, max_read;
3667
- int i, j, ret;
4242
+ int i, ret;
36684243
36694244 /* Calculate read parameters */
36704245 for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
....@@ -3696,13 +4271,7 @@
36964271 if (ret < 0)
36974272 return ret;
36984273
3699
- /* Remove the padding bytes from the data read from the DSP */
3700
- for (i = 0; i < nwords; i++) {
3701
- for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++)
3702
- *pack_out++ = *pack_in++;
3703
-
3704
- pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE;
3705
- }
4274
+ wm_adsp_remove_padding(compr->raw_buf, nwords, WM_ADSP_DATA_WORD_SIZE);
37064275
37074276 /* update read index to account for words read */
37084277 buf->read_index += nwords;
....@@ -3727,9 +4296,9 @@
37274296 int ntotal = 0;
37284297 int nwords, nbytes;
37294298
3730
- adsp_dbg(dsp, "Requested read of %zu bytes\n", count);
4299
+ compr_dbg(compr, "Requested read of %zu bytes\n", count);
37314300
3732
- if (!compr->buf || compr->buf->error) {
4301
+ if (dsp->fatal_error || !compr->buf || compr->buf->error) {
37334302 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
37344303 return -EIO;
37354304 }
....@@ -3739,17 +4308,18 @@
37394308 do {
37404309 nwords = wm_adsp_buffer_capture_block(compr, count);
37414310 if (nwords < 0) {
3742
- adsp_err(dsp, "Failed to capture block: %d\n", nwords);
4311
+ compr_err(compr, "Failed to capture block: %d\n",
4312
+ nwords);
37434313 return nwords;
37444314 }
37454315
37464316 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE;
37474317
3748
- adsp_dbg(dsp, "Read %d bytes\n", nbytes);
4318
+ compr_dbg(compr, "Read %d bytes\n", nbytes);
37494319
37504320 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
3751
- adsp_err(dsp, "Failed to copy data to user: %d, %d\n",
3752
- ntotal, nbytes);
4321
+ compr_err(compr, "Failed to copy data to user: %d, %d\n",
4322
+ ntotal, nbytes);
37534323 return -EFAULT;
37544324 }
37554325
....@@ -3762,7 +4332,8 @@
37624332 return ntotal;
37634333 }
37644334
3765
-int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf,
4335
+int wm_adsp_compr_copy(struct snd_soc_component *component,
4336
+ struct snd_compr_stream *stream, char __user *buf,
37664337 size_t count)
37674338 {
37684339 struct wm_adsp_compr *compr = stream->runtime->private_data;
....@@ -3782,39 +4353,21 @@
37824353 }
37834354 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
37844355
3785
-int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions)
4356
+static void wm_adsp_fatal_error(struct wm_adsp *dsp)
37864357 {
3787
- struct regmap *regmap = dsp->regmap;
3788
- unsigned int code0, code1, lock_reg;
4358
+ struct wm_adsp_compr *compr;
37894359
3790
- if (!(lock_regions & WM_ADSP2_REGION_ALL))
3791
- return 0;
4360
+ dsp->fatal_error = true;
37924361
3793
- lock_regions &= WM_ADSP2_REGION_ALL;
3794
- lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0;
3795
-
3796
- while (lock_regions) {
3797
- code0 = code1 = 0;
3798
- if (lock_regions & BIT(0)) {
3799
- code0 = ADSP2_LOCK_CODE_0;
3800
- code1 = ADSP2_LOCK_CODE_1;
3801
- }
3802
- if (lock_regions & BIT(1)) {
3803
- code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT;
3804
- code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT;
3805
- }
3806
- regmap_write(regmap, lock_reg, code0);
3807
- regmap_write(regmap, lock_reg, code1);
3808
- lock_regions >>= 2;
3809
- lock_reg += 2;
4362
+ list_for_each_entry(compr, &dsp->compr_list, list) {
4363
+ if (compr->stream)
4364
+ snd_compr_fragment_elapsed(compr->stream);
38104365 }
3811
-
3812
- return 0;
38134366 }
3814
-EXPORT_SYMBOL_GPL(wm_adsp2_lock);
38154367
3816
-irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp)
4368
+irqreturn_t wm_adsp2_bus_error(int irq, void *data)
38174369 {
4370
+ struct wm_adsp *dsp = (struct wm_adsp *)data;
38184371 unsigned int val;
38194372 struct regmap *regmap = dsp->regmap;
38204373 int ret = 0;
....@@ -3830,12 +4383,13 @@
38304383
38314384 if (val & ADSP2_WDT_TIMEOUT_STS_MASK) {
38324385 adsp_err(dsp, "watchdog timeout error\n");
3833
- wm_adsp_stop_watchdog(dsp);
4386
+ dsp->ops->stop_watchdog(dsp);
4387
+ wm_adsp_fatal_error(dsp);
38344388 }
38354389
3836
- if (val & (ADSP2_SLAVE_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) {
3837
- if (val & ADSP2_SLAVE_ERR_MASK)
3838
- adsp_err(dsp, "bus error: slave error\n");
4390
+ if (val & (ADSP2_ADDR_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) {
4391
+ if (val & ADSP2_ADDR_ERR_MASK)
4392
+ adsp_err(dsp, "bus error: address error\n");
38394393 else
38404394 adsp_err(dsp, "bus error: region lock error\n");
38414395
....@@ -3877,4 +4431,160 @@
38774431 }
38784432 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error);
38794433
4434
+irqreturn_t wm_halo_bus_error(int irq, void *data)
4435
+{
4436
+ struct wm_adsp *dsp = (struct wm_adsp *)data;
4437
+ struct regmap *regmap = dsp->regmap;
4438
+ unsigned int fault[6];
4439
+ struct reg_sequence clear[] = {
4440
+ { dsp->base + HALO_MPU_XM_VIO_STATUS, 0x0 },
4441
+ { dsp->base + HALO_MPU_YM_VIO_STATUS, 0x0 },
4442
+ { dsp->base + HALO_MPU_PM_VIO_STATUS, 0x0 },
4443
+ };
4444
+ int ret;
4445
+
4446
+ mutex_lock(&dsp->pwr_lock);
4447
+
4448
+ ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1,
4449
+ fault);
4450
+ if (ret) {
4451
+ adsp_warn(dsp, "Failed to read AHB DEBUG_1: %d\n", ret);
4452
+ goto exit_unlock;
4453
+ }
4454
+
4455
+ adsp_warn(dsp, "AHB: STATUS: 0x%x ADDR: 0x%x\n",
4456
+ *fault & HALO_AHBM_FLAGS_ERR_MASK,
4457
+ (*fault & HALO_AHBM_CORE_ERR_ADDR_MASK) >>
4458
+ HALO_AHBM_CORE_ERR_ADDR_SHIFT);
4459
+
4460
+ ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0,
4461
+ fault);
4462
+ if (ret) {
4463
+ adsp_warn(dsp, "Failed to read AHB DEBUG_0: %d\n", ret);
4464
+ goto exit_unlock;
4465
+ }
4466
+
4467
+ adsp_warn(dsp, "AHB: SYS_ADDR: 0x%x\n", *fault);
4468
+
4469
+ ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR,
4470
+ fault, ARRAY_SIZE(fault));
4471
+ if (ret) {
4472
+ adsp_warn(dsp, "Failed to read MPU fault info: %d\n", ret);
4473
+ goto exit_unlock;
4474
+ }
4475
+
4476
+ adsp_warn(dsp, "XM: STATUS:0x%x ADDR:0x%x\n", fault[1], fault[0]);
4477
+ adsp_warn(dsp, "YM: STATUS:0x%x ADDR:0x%x\n", fault[3], fault[2]);
4478
+ adsp_warn(dsp, "PM: STATUS:0x%x ADDR:0x%x\n", fault[5], fault[4]);
4479
+
4480
+ ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear));
4481
+ if (ret)
4482
+ adsp_warn(dsp, "Failed to clear MPU status: %d\n", ret);
4483
+
4484
+exit_unlock:
4485
+ mutex_unlock(&dsp->pwr_lock);
4486
+
4487
+ return IRQ_HANDLED;
4488
+}
4489
+EXPORT_SYMBOL_GPL(wm_halo_bus_error);
4490
+
4491
+irqreturn_t wm_halo_wdt_expire(int irq, void *data)
4492
+{
4493
+ struct wm_adsp *dsp = data;
4494
+
4495
+ mutex_lock(&dsp->pwr_lock);
4496
+
4497
+ adsp_warn(dsp, "WDT Expiry Fault\n");
4498
+ dsp->ops->stop_watchdog(dsp);
4499
+ wm_adsp_fatal_error(dsp);
4500
+
4501
+ mutex_unlock(&dsp->pwr_lock);
4502
+
4503
+ return IRQ_HANDLED;
4504
+}
4505
+EXPORT_SYMBOL_GPL(wm_halo_wdt_expire);
4506
+
4507
+static struct wm_adsp_ops wm_adsp1_ops = {
4508
+ .validate_version = wm_adsp_validate_version,
4509
+ .parse_sizes = wm_adsp1_parse_sizes,
4510
+ .region_to_reg = wm_adsp_region_to_reg,
4511
+};
4512
+
4513
+static struct wm_adsp_ops wm_adsp2_ops[] = {
4514
+ {
4515
+ .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4516
+ .parse_sizes = wm_adsp2_parse_sizes,
4517
+ .validate_version = wm_adsp_validate_version,
4518
+ .setup_algs = wm_adsp2_setup_algs,
4519
+ .region_to_reg = wm_adsp_region_to_reg,
4520
+
4521
+ .show_fw_status = wm_adsp2_show_fw_status,
4522
+
4523
+ .enable_memory = wm_adsp2_enable_memory,
4524
+ .disable_memory = wm_adsp2_disable_memory,
4525
+
4526
+ .enable_core = wm_adsp2_enable_core,
4527
+ .disable_core = wm_adsp2_disable_core,
4528
+
4529
+ .start_core = wm_adsp2_start_core,
4530
+ .stop_core = wm_adsp2_stop_core,
4531
+
4532
+ },
4533
+ {
4534
+ .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4535
+ .parse_sizes = wm_adsp2_parse_sizes,
4536
+ .validate_version = wm_adsp_validate_version,
4537
+ .setup_algs = wm_adsp2_setup_algs,
4538
+ .region_to_reg = wm_adsp_region_to_reg,
4539
+
4540
+ .show_fw_status = wm_adsp2v2_show_fw_status,
4541
+
4542
+ .enable_memory = wm_adsp2_enable_memory,
4543
+ .disable_memory = wm_adsp2_disable_memory,
4544
+ .lock_memory = wm_adsp2_lock,
4545
+
4546
+ .enable_core = wm_adsp2v2_enable_core,
4547
+ .disable_core = wm_adsp2v2_disable_core,
4548
+
4549
+ .start_core = wm_adsp2_start_core,
4550
+ .stop_core = wm_adsp2_stop_core,
4551
+ },
4552
+ {
4553
+ .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4554
+ .parse_sizes = wm_adsp2_parse_sizes,
4555
+ .validate_version = wm_adsp_validate_version,
4556
+ .setup_algs = wm_adsp2_setup_algs,
4557
+ .region_to_reg = wm_adsp_region_to_reg,
4558
+
4559
+ .show_fw_status = wm_adsp2v2_show_fw_status,
4560
+ .stop_watchdog = wm_adsp_stop_watchdog,
4561
+
4562
+ .enable_memory = wm_adsp2_enable_memory,
4563
+ .disable_memory = wm_adsp2_disable_memory,
4564
+ .lock_memory = wm_adsp2_lock,
4565
+
4566
+ .enable_core = wm_adsp2v2_enable_core,
4567
+ .disable_core = wm_adsp2v2_disable_core,
4568
+
4569
+ .start_core = wm_adsp2_start_core,
4570
+ .stop_core = wm_adsp2_stop_core,
4571
+ },
4572
+};
4573
+
4574
+static struct wm_adsp_ops wm_halo_ops = {
4575
+ .sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr),
4576
+ .parse_sizes = wm_adsp2_parse_sizes,
4577
+ .validate_version = wm_halo_validate_version,
4578
+ .setup_algs = wm_halo_setup_algs,
4579
+ .region_to_reg = wm_halo_region_to_reg,
4580
+
4581
+ .show_fw_status = wm_halo_show_fw_status,
4582
+ .stop_watchdog = wm_halo_stop_watchdog,
4583
+
4584
+ .lock_memory = wm_halo_configure_mpu,
4585
+
4586
+ .start_core = wm_halo_start_core,
4587
+ .stop_core = wm_halo_stop_core,
4588
+};
4589
+
38804590 MODULE_LICENSE("GPL v2");