.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * wm_adsp.c -- Wolfson ADSP support |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2012 Wolfson Microelectronics plc |
---|
5 | 6 | * |
---|
6 | 7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | 8 | */ |
---|
12 | 9 | |
---|
13 | 10 | #include <linux/ctype.h> |
---|
.. | .. |
---|
45 | 42 | dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) |
---|
46 | 43 | #define adsp_dbg(_dsp, fmt, ...) \ |
---|
47 | 44 | 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__) |
---|
48 | 52 | |
---|
49 | 53 | #define ADSP1_CONTROL_1 0x00 |
---|
50 | 54 | #define ADSP1_CONTROL_2 0x02 |
---|
.. | .. |
---|
195 | 199 | #define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR 0x7C |
---|
196 | 200 | |
---|
197 | 201 | #define ADSP2_REGION_LOCK_ERR_MASK 0x8000 |
---|
198 | | -#define ADSP2_SLAVE_ERR_MASK 0x4000 |
---|
| 202 | +#define ADSP2_ADDR_ERR_MASK 0x4000 |
---|
199 | 203 | #define ADSP2_WDT_TIMEOUT_STS_MASK 0x2000 |
---|
200 | 204 | #define ADSP2_CTRL_ERR_PAUSE_ENA 0x0002 |
---|
201 | 205 | #define ADSP2_CTRL_ERR_EINT 0x0001 |
---|
.. | .. |
---|
219 | 223 | * Event control messages |
---|
220 | 224 | */ |
---|
221 | 225 | #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; |
---|
222 | 309 | |
---|
223 | 310 | struct wm_adsp_buf { |
---|
224 | 311 | struct list_head list; |
---|
.. | .. |
---|
268 | 355 | #define WM_ADSP_FW_ASR 7 |
---|
269 | 356 | #define WM_ADSP_FW_TRACE 8 |
---|
270 | 357 | #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 |
---|
272 | 361 | |
---|
273 | | -#define WM_ADSP_NUM_FW 11 |
---|
| 362 | +#define WM_ADSP_NUM_FW 13 |
---|
274 | 363 | |
---|
275 | 364 | static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { |
---|
276 | 365 | [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", |
---|
.. | .. |
---|
283 | 372 | [WM_ADSP_FW_ASR] = "ASR Assist", |
---|
284 | 373 | [WM_ADSP_FW_TRACE] = "Dbg Trace", |
---|
285 | 374 | [WM_ADSP_FW_SPK_PROT] = "Protection", |
---|
| 375 | + [WM_ADSP_FW_SPK_CALI] = "Calibration", |
---|
| 376 | + [WM_ADSP_FW_SPK_DIAG] = "Diagnostic", |
---|
286 | 377 | [WM_ADSP_FW_MISC] = "Misc", |
---|
287 | 378 | }; |
---|
288 | 379 | |
---|
.. | .. |
---|
299 | 390 | __be32 build_job_number; |
---|
300 | 391 | }; |
---|
301 | 392 | |
---|
| 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 | + |
---|
302 | 399 | struct wm_adsp_alg_xm_struct { |
---|
303 | 400 | __be32 magic; |
---|
304 | 401 | __be32 smoothing; |
---|
.. | .. |
---|
310 | 407 | __be64 smoothed_power; |
---|
311 | 408 | }; |
---|
312 | 409 | |
---|
| 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 | + |
---|
313 | 416 | 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 */ |
---|
320 | 423 | __be32 high_water_mark; /* Point at which IRQ is asserted */ |
---|
321 | 424 | __be32 irq_count; /* bits 1-31 count IRQ assertions */ |
---|
322 | 425 | __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */ |
---|
.. | .. |
---|
334 | 437 | struct wm_adsp_compr; |
---|
335 | 438 | |
---|
336 | 439 | struct wm_adsp_compr_buf { |
---|
| 440 | + struct list_head list; |
---|
337 | 441 | struct wm_adsp *dsp; |
---|
338 | 442 | struct wm_adsp_compr *compr; |
---|
339 | 443 | |
---|
.. | .. |
---|
344 | 448 | u32 irq_count; |
---|
345 | 449 | int read_index; |
---|
346 | 450 | int avail; |
---|
| 451 | + int host_buf_mem_type; |
---|
| 452 | + |
---|
| 453 | + char *name; |
---|
347 | 454 | }; |
---|
348 | 455 | |
---|
349 | 456 | struct wm_adsp_compr { |
---|
| 457 | + struct list_head list; |
---|
350 | 458 | struct wm_adsp *dsp; |
---|
351 | 459 | struct wm_adsp_compr_buf *buf; |
---|
352 | 460 | |
---|
.. | .. |
---|
357 | 465 | unsigned int copied_total; |
---|
358 | 466 | |
---|
359 | 467 | unsigned int sample_rate; |
---|
| 468 | + |
---|
| 469 | + const char *name; |
---|
360 | 470 | }; |
---|
361 | 471 | |
---|
362 | 472 | #define WM_ADSP_DATA_WORD_SIZE 3 |
---|
.. | .. |
---|
373 | 483 | |
---|
374 | 484 | #define ALG_XM_FIELD(field) \ |
---|
375 | 485 | (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 |
---|
376 | 491 | |
---|
377 | 492 | static int wm_adsp_buffer_init(struct wm_adsp *dsp); |
---|
378 | 493 | static int wm_adsp_buffer_free(struct wm_adsp *dsp); |
---|
.. | .. |
---|
393 | 508 | static const struct wm_adsp_buffer_region_def default_regions[] = { |
---|
394 | 509 | { |
---|
395 | 510 | .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), |
---|
398 | 513 | }, |
---|
399 | 514 | { |
---|
400 | 515 | .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), |
---|
403 | 518 | }, |
---|
404 | 519 | { |
---|
405 | 520 | .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), |
---|
408 | 523 | }, |
---|
409 | 524 | }; |
---|
410 | 525 | |
---|
.. | .. |
---|
475 | 590 | .caps = trace_caps, |
---|
476 | 591 | }, |
---|
477 | 592 | [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" }, |
---|
478 | 595 | [WM_ADSP_FW_MISC] = { .file = "misc" }, |
---|
479 | 596 | }; |
---|
480 | 597 | |
---|
.. | .. |
---|
488 | 605 | struct wm_coeff_ctl { |
---|
489 | 606 | const char *name; |
---|
490 | 607 | const char *fw_name; |
---|
| 608 | + /* Subname is needed to match with firmware */ |
---|
| 609 | + const char *subname; |
---|
| 610 | + unsigned int subname_len; |
---|
491 | 611 | struct wm_adsp_alg_region alg_region; |
---|
492 | 612 | struct wm_coeff_ctl_ops ops; |
---|
493 | 613 | struct wm_adsp *dsp; |
---|
.. | .. |
---|
507 | 627 | switch (type) { |
---|
508 | 628 | case WMFW_ADSP1_PM: |
---|
509 | 629 | return "PM"; |
---|
| 630 | + case WMFW_HALO_PM_PACKED: |
---|
| 631 | + return "PM_PACKED"; |
---|
510 | 632 | case WMFW_ADSP1_DM: |
---|
511 | 633 | return "DM"; |
---|
512 | 634 | case WMFW_ADSP2_XM: |
---|
513 | 635 | return "XM"; |
---|
| 636 | + case WMFW_HALO_XM_PACKED: |
---|
| 637 | + return "XM_PACKED"; |
---|
514 | 638 | case WMFW_ADSP2_YM: |
---|
515 | 639 | return "YM"; |
---|
| 640 | + case WMFW_HALO_YM_PACKED: |
---|
| 641 | + return "YM_PACKED"; |
---|
516 | 642 | case WMFW_ADSP1_ZM: |
---|
517 | 643 | return "ZM"; |
---|
518 | 644 | default: |
---|
.. | .. |
---|
611 | 737 | struct dentry *root = NULL; |
---|
612 | 738 | int i; |
---|
613 | 739 | |
---|
614 | | - if (!component->debugfs_root) { |
---|
615 | | - adsp_err(dsp, "No codec debugfs root\n"); |
---|
616 | | - goto err; |
---|
617 | | - } |
---|
618 | | - |
---|
619 | 740 | root = debugfs_create_dir(dsp->name, component->debugfs_root); |
---|
620 | 741 | |
---|
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); |
---|
623 | 746 | |
---|
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); |
---|
642 | 750 | |
---|
643 | 751 | dsp->debugfs_root = root; |
---|
644 | | - return; |
---|
645 | | - |
---|
646 | | -err: |
---|
647 | | - debugfs_remove_recursive(root); |
---|
648 | | - adsp_err(dsp, "Failed to create debugfs\n"); |
---|
649 | 752 | } |
---|
650 | 753 | |
---|
651 | 754 | static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) |
---|
.. | .. |
---|
697 | 800 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
---|
698 | 801 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
---|
699 | 802 | struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); |
---|
700 | | - int ret = 0; |
---|
| 803 | + int ret = 1; |
---|
701 | 804 | |
---|
702 | 805 | if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw) |
---|
703 | 806 | return 0; |
---|
.. | .. |
---|
707 | 810 | |
---|
708 | 811 | mutex_lock(&dsp[e->shift_l].pwr_lock); |
---|
709 | 812 | |
---|
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)) |
---|
711 | 814 | ret = -EBUSY; |
---|
712 | 815 | else |
---|
713 | 816 | dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0]; |
---|
.. | .. |
---|
744 | 847 | static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem, |
---|
745 | 848 | unsigned int offset) |
---|
746 | 849 | { |
---|
747 | | - if (WARN_ON(!mem)) |
---|
748 | | - return offset; |
---|
749 | 850 | switch (mem->type) { |
---|
750 | 851 | case WMFW_ADSP1_PM: |
---|
751 | 852 | return mem->base + (offset * 3); |
---|
752 | 853 | case WMFW_ADSP1_DM: |
---|
753 | | - return mem->base + (offset * 2); |
---|
754 | 854 | case WMFW_ADSP2_XM: |
---|
755 | | - return mem->base + (offset * 2); |
---|
756 | 855 | case WMFW_ADSP2_YM: |
---|
757 | | - return mem->base + (offset * 2); |
---|
758 | 856 | case WMFW_ADSP1_ZM: |
---|
759 | 857 | return mem->base + (offset * 2); |
---|
760 | 858 | default: |
---|
.. | .. |
---|
763 | 861 | } |
---|
764 | 862 | } |
---|
765 | 863 | |
---|
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) |
---|
767 | 866 | { |
---|
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 | +{ |
---|
770 | 885 | unsigned int i; |
---|
771 | 886 | int ret; |
---|
772 | 887 | |
---|
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]); |
---|
775 | 890 | if (ret) { |
---|
776 | 891 | adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret); |
---|
777 | 892 | return; |
---|
778 | 893 | } |
---|
779 | 894 | } |
---|
| 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); |
---|
780 | 904 | |
---|
781 | 905 | 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]); |
---|
783 | 907 | } |
---|
784 | 908 | |
---|
785 | 909 | static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp) |
---|
786 | 910 | { |
---|
787 | | - unsigned int scratch[2]; |
---|
788 | | - int ret; |
---|
| 911 | + unsigned int offs[] = { ADSP2V2_SCRATCH0_1, ADSP2V2_SCRATCH2_3 }; |
---|
789 | 912 | |
---|
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); |
---|
803 | 914 | |
---|
804 | 915 | 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]); |
---|
809 | 930 | } |
---|
810 | 931 | |
---|
811 | 932 | static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext) |
---|
.. | .. |
---|
826 | 947 | return -EINVAL; |
---|
827 | 948 | } |
---|
828 | 949 | |
---|
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); |
---|
830 | 951 | |
---|
831 | 952 | return 0; |
---|
832 | 953 | } |
---|
.. | .. |
---|
915 | 1036 | return -ETIMEDOUT; |
---|
916 | 1037 | } |
---|
917 | 1038 | |
---|
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) |
---|
920 | 1041 | { |
---|
921 | 1042 | struct wm_adsp *dsp = ctl->dsp; |
---|
922 | 1043 | void *scratch; |
---|
.. | .. |
---|
946 | 1067 | return 0; |
---|
947 | 1068 | } |
---|
948 | 1069 | |
---|
| 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 | + |
---|
949 | 1087 | static int wm_coeff_put(struct snd_kcontrol *kctl, |
---|
950 | 1088 | struct snd_ctl_elem_value *ucontrol) |
---|
951 | 1089 | { |
---|
.. | .. |
---|
956 | 1094 | int ret = 0; |
---|
957 | 1095 | |
---|
958 | 1096 | 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); |
---|
969 | 1098 | mutex_unlock(&ctl->dsp->pwr_lock); |
---|
970 | 1099 | |
---|
971 | 1100 | return ret; |
---|
.. | .. |
---|
981 | 1110 | |
---|
982 | 1111 | mutex_lock(&ctl->dsp->pwr_lock); |
---|
983 | 1112 | |
---|
984 | | - if (copy_from_user(ctl->cache, bytes, size)) { |
---|
| 1113 | + if (copy_from_user(ctl->cache, bytes, size)) |
---|
985 | 1114 | 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); |
---|
993 | 1117 | |
---|
994 | 1118 | mutex_unlock(&ctl->dsp->pwr_lock); |
---|
995 | 1119 | |
---|
.. | .. |
---|
1020 | 1144 | return ret; |
---|
1021 | 1145 | } |
---|
1022 | 1146 | |
---|
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) |
---|
1025 | 1149 | { |
---|
1026 | 1150 | struct wm_adsp *dsp = ctl->dsp; |
---|
1027 | 1151 | void *scratch; |
---|
.. | .. |
---|
1051 | 1175 | return 0; |
---|
1052 | 1176 | } |
---|
1053 | 1177 | |
---|
| 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 | + |
---|
1054 | 1198 | static int wm_coeff_get(struct snd_kcontrol *kctl, |
---|
1055 | 1199 | struct snd_ctl_elem_value *ucontrol) |
---|
1056 | 1200 | { |
---|
.. | .. |
---|
1058 | 1202 | (struct soc_bytes_ext *)kctl->private_value; |
---|
1059 | 1203 | struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); |
---|
1060 | 1204 | char *p = ucontrol->value.bytes.data; |
---|
1061 | | - int ret = 0; |
---|
| 1205 | + int ret; |
---|
1062 | 1206 | |
---|
1063 | 1207 | 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); |
---|
1077 | 1209 | mutex_unlock(&ctl->dsp->pwr_lock); |
---|
1078 | 1210 | |
---|
1079 | 1211 | return ret; |
---|
.. | .. |
---|
1089 | 1221 | |
---|
1090 | 1222 | mutex_lock(&ctl->dsp->pwr_lock); |
---|
1091 | 1223 | |
---|
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); |
---|
1101 | 1225 | |
---|
1102 | 1226 | if (!ret && copy_to_user(bytes, ctl->cache, size)) |
---|
1103 | 1227 | ret = -EFAULT; |
---|
.. | .. |
---|
1225 | 1349 | * created so we don't need to do anything. |
---|
1226 | 1350 | */ |
---|
1227 | 1351 | 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); |
---|
1229 | 1353 | if (ret < 0) |
---|
1230 | 1354 | return ret; |
---|
1231 | 1355 | } |
---|
.. | .. |
---|
1243 | 1367 | if (!ctl->enabled) |
---|
1244 | 1368 | continue; |
---|
1245 | 1369 | 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); |
---|
1247 | 1372 | if (ret < 0) |
---|
1248 | 1373 | return ret; |
---|
1249 | 1374 | } |
---|
.. | .. |
---|
1287 | 1412 | { |
---|
1288 | 1413 | kfree(ctl->cache); |
---|
1289 | 1414 | kfree(ctl->name); |
---|
| 1415 | + kfree(ctl->subname); |
---|
1290 | 1416 | kfree(ctl); |
---|
1291 | 1417 | } |
---|
1292 | 1418 | |
---|
.. | .. |
---|
1313 | 1439 | case 1: |
---|
1314 | 1440 | snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x", |
---|
1315 | 1441 | dsp->name, region_name, alg_region->alg); |
---|
| 1442 | + subname = NULL; /* don't append subname */ |
---|
1316 | 1443 | 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, |
---|
1319 | 1446 | "%s%c %.12s %x", dsp->name, *region_name, |
---|
1320 | 1447 | 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; |
---|
1321 | 1462 | |
---|
1322 | 1463 | /* 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; |
---|
1326 | 1466 | |
---|
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); |
---|
1338 | 1469 | } |
---|
1339 | 1470 | |
---|
1340 | 1471 | list_for_each_entry(ctl, &dsp->ctl_list, list) { |
---|
.. | .. |
---|
1355 | 1486 | ret = -ENOMEM; |
---|
1356 | 1487 | goto err_ctl; |
---|
1357 | 1488 | } |
---|
| 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 | + } |
---|
1358 | 1498 | ctl->enabled = 1; |
---|
1359 | 1499 | ctl->set = 0; |
---|
1360 | 1500 | ctl->ops.xget = wm_coeff_get; |
---|
.. | .. |
---|
1368 | 1508 | ctl->cache = kzalloc(ctl->len, GFP_KERNEL); |
---|
1369 | 1509 | if (!ctl->cache) { |
---|
1370 | 1510 | ret = -ENOMEM; |
---|
1371 | | - goto err_ctl_name; |
---|
| 1511 | + goto err_ctl_subname; |
---|
1372 | 1512 | } |
---|
1373 | 1513 | |
---|
1374 | 1514 | list_add(&ctl->list, &dsp->ctl_list); |
---|
.. | .. |
---|
1392 | 1532 | err_list_del: |
---|
1393 | 1533 | list_del(&ctl->list); |
---|
1394 | 1534 | kfree(ctl->cache); |
---|
| 1535 | +err_ctl_subname: |
---|
| 1536 | + kfree(ctl->subname); |
---|
1395 | 1537 | err_ctl_name: |
---|
1396 | 1538 | kfree(ctl->name); |
---|
1397 | 1539 | err_ctl: |
---|
.. | .. |
---|
1622 | 1764 | return 0; |
---|
1623 | 1765 | } |
---|
1624 | 1766 | |
---|
| 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 | + |
---|
1625 | 1823 | static int wm_adsp_load(struct wm_adsp *dsp) |
---|
1626 | 1824 | { |
---|
1627 | 1825 | LIST_HEAD(buf_list); |
---|
.. | .. |
---|
1630 | 1828 | unsigned int pos = 0; |
---|
1631 | 1829 | const struct wmfw_header *header; |
---|
1632 | 1830 | const struct wmfw_adsp1_sizes *adsp1_sizes; |
---|
1633 | | - const struct wmfw_adsp2_sizes *adsp2_sizes; |
---|
1634 | 1831 | const struct wmfw_footer *footer; |
---|
1635 | 1832 | const struct wmfw_region *region; |
---|
1636 | 1833 | const struct wm_adsp_region *mem; |
---|
.. | .. |
---|
1639 | 1836 | struct wm_adsp_buf *buf; |
---|
1640 | 1837 | unsigned int reg; |
---|
1641 | 1838 | int regions = 0; |
---|
1642 | | - int ret, offset, type, sizes; |
---|
| 1839 | + int ret, offset, type; |
---|
1643 | 1840 | |
---|
1644 | 1841 | file = kzalloc(PAGE_SIZE, GFP_KERNEL); |
---|
1645 | 1842 | if (file == NULL) |
---|
.. | .. |
---|
1670 | 1867 | goto out_fw; |
---|
1671 | 1868 | } |
---|
1672 | 1869 | |
---|
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)) { |
---|
1682 | 1871 | adsp_err(dsp, "%s: unknown file format %d\n", |
---|
1683 | 1872 | file, header->ver); |
---|
1684 | 1873 | goto out_fw; |
---|
.. | .. |
---|
1693 | 1882 | goto out_fw; |
---|
1694 | 1883 | } |
---|
1695 | 1884 | |
---|
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); |
---|
1702 | 1887 | |
---|
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); |
---|
1708 | 1890 | |
---|
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) { |
---|
1729 | 1892 | adsp_err(dsp, "%s: unexpected header length %d\n", |
---|
1730 | 1893 | file, le32_to_cpu(header->len)); |
---|
1731 | 1894 | goto out_fw; |
---|
.. | .. |
---|
1742 | 1905 | text = NULL; |
---|
1743 | 1906 | offset = le32_to_cpu(region->offset) & 0xffffff; |
---|
1744 | 1907 | type = be32_to_cpu(region->type) & 0xff; |
---|
1745 | | - mem = wm_adsp_find_region(dsp, type); |
---|
1746 | 1908 | |
---|
1747 | 1909 | switch (type) { |
---|
1748 | 1910 | case WMFW_NAME_TEXT: |
---|
.. | .. |
---|
1770 | 1932 | case WMFW_ADSP2_XM: |
---|
1771 | 1933 | case WMFW_ADSP2_YM: |
---|
1772 | 1934 | 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 | + |
---|
1773 | 1945 | 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); |
---|
1775 | 1947 | break; |
---|
1776 | 1948 | default: |
---|
1777 | 1949 | adsp_warn(dsp, |
---|
.. | .. |
---|
1850 | 2022 | return ret; |
---|
1851 | 2023 | } |
---|
1852 | 2024 | |
---|
| 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 | + |
---|
1853 | 2110 | static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp, |
---|
1854 | 2111 | const struct wm_adsp_alg_region *alg_region) |
---|
1855 | 2112 | { |
---|
.. | .. |
---|
1884 | 2141 | } |
---|
1885 | 2142 | |
---|
1886 | 2143 | /* 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); |
---|
1888 | 2145 | |
---|
1889 | 2146 | ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); |
---|
1890 | 2147 | if (ret != 0) { |
---|
.. | .. |
---|
1904 | 2161 | if (!alg) |
---|
1905 | 2162 | return ERR_PTR(-ENOMEM); |
---|
1906 | 2163 | |
---|
1907 | | - reg = wm_adsp_region_to_reg(mem, pos); |
---|
| 2164 | + reg = dsp->ops->region_to_reg(mem, pos); |
---|
1908 | 2165 | |
---|
1909 | 2166 | ret = regmap_raw_read(dsp->regmap, reg, alg, len); |
---|
1910 | 2167 | if (ret != 0) { |
---|
.. | .. |
---|
1964 | 2221 | } |
---|
1965 | 2222 | } |
---|
1966 | 2223 | |
---|
| 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 | + |
---|
1967 | 2265 | static int wm_adsp1_setup_algs(struct wm_adsp *dsp) |
---|
1968 | 2266 | { |
---|
1969 | 2267 | struct wmfw_adsp1_id_hdr adsp1_id; |
---|
.. | .. |
---|
1987 | 2285 | } |
---|
1988 | 2286 | |
---|
1989 | 2287 | 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); |
---|
1997 | 2290 | |
---|
1998 | 2291 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, |
---|
1999 | 2292 | adsp1_id.fw.id, adsp1_id.zm); |
---|
.. | .. |
---|
2093 | 2386 | } |
---|
2094 | 2387 | |
---|
2095 | 2388 | 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); |
---|
2104 | 2391 | |
---|
2105 | 2392 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, |
---|
2106 | 2393 | adsp2_id.fw.id, adsp2_id.xm); |
---|
.. | .. |
---|
2205 | 2492 | return ret; |
---|
2206 | 2493 | } |
---|
2207 | 2494 | |
---|
| 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 | + |
---|
2208 | 2567 | static int wm_adsp_load_coeff(struct wm_adsp *dsp) |
---|
2209 | 2568 | { |
---|
2210 | 2569 | LIST_HEAD(buf_list); |
---|
.. | .. |
---|
2285 | 2644 | switch (type) { |
---|
2286 | 2645 | case (WMFW_NAME_TEXT << 8): |
---|
2287 | 2646 | case (WMFW_INFO_TEXT << 8): |
---|
| 2647 | + case (WMFW_METADATA << 8): |
---|
2288 | 2648 | break; |
---|
2289 | 2649 | case (WMFW_ABSOLUTE << 8): |
---|
2290 | 2650 | /* |
---|
.. | .. |
---|
2299 | 2659 | adsp_err(dsp, "No ZM\n"); |
---|
2300 | 2660 | break; |
---|
2301 | 2661 | } |
---|
2302 | | - reg = wm_adsp_region_to_reg(mem, 0); |
---|
| 2662 | + reg = dsp->ops->region_to_reg(mem, 0); |
---|
2303 | 2663 | |
---|
2304 | 2664 | } else { |
---|
2305 | 2665 | region_name = "register"; |
---|
.. | .. |
---|
2311 | 2671 | case WMFW_ADSP1_ZM: |
---|
2312 | 2672 | case WMFW_ADSP2_XM: |
---|
2313 | 2673 | case WMFW_ADSP2_YM: |
---|
| 2674 | + case WMFW_HALO_XM_PACKED: |
---|
| 2675 | + case WMFW_HALO_YM_PACKED: |
---|
| 2676 | + case WMFW_HALO_PM_PACKED: |
---|
2314 | 2677 | adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", |
---|
2315 | 2678 | file, blocks, le32_to_cpu(blk->len), |
---|
2316 | 2679 | type, le32_to_cpu(blk->id)); |
---|
.. | .. |
---|
2325 | 2688 | le32_to_cpu(blk->id)); |
---|
2326 | 2689 | if (alg_region) { |
---|
2327 | 2690 | reg = alg_region->base; |
---|
2328 | | - reg = wm_adsp_region_to_reg(mem, reg); |
---|
| 2691 | + reg = dsp->ops->region_to_reg(mem, reg); |
---|
2329 | 2692 | reg += offset; |
---|
2330 | 2693 | } else { |
---|
2331 | 2694 | adsp_err(dsp, "No %x for algorithm %x\n", |
---|
.. | .. |
---|
2419 | 2782 | return 0; |
---|
2420 | 2783 | } |
---|
2421 | 2784 | |
---|
2422 | | -int wm_adsp1_init(struct wm_adsp *dsp) |
---|
| 2785 | +static int wm_adsp_common_init(struct wm_adsp *dsp) |
---|
2423 | 2786 | { |
---|
2424 | 2787 | int ret; |
---|
2425 | 2788 | |
---|
.. | .. |
---|
2428 | 2791 | return ret; |
---|
2429 | 2792 | |
---|
2430 | 2793 | 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); |
---|
2431 | 2797 | |
---|
2432 | 2798 | mutex_init(&dsp->pwr_lock); |
---|
2433 | 2799 | |
---|
2434 | 2800 | 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); |
---|
2435 | 2808 | } |
---|
2436 | 2809 | EXPORT_SYMBOL_GPL(wm_adsp1_init); |
---|
2437 | 2810 | |
---|
.. | .. |
---|
2550 | 2923 | } |
---|
2551 | 2924 | EXPORT_SYMBOL_GPL(wm_adsp1_event); |
---|
2552 | 2925 | |
---|
2553 | | -static int wm_adsp2_ena(struct wm_adsp *dsp) |
---|
| 2926 | +static int wm_adsp2v2_enable_core(struct wm_adsp *dsp) |
---|
2554 | 2927 | { |
---|
2555 | 2928 | unsigned int val; |
---|
2556 | 2929 | 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 | | - } |
---|
2569 | 2930 | |
---|
2570 | 2931 | /* Wait for the RAM to start, should be near instantaneous */ |
---|
2571 | 2932 | for (count = 0; count < 10; ++count) { |
---|
.. | .. |
---|
2589 | 2950 | return 0; |
---|
2590 | 2951 | } |
---|
2591 | 2952 | |
---|
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) |
---|
2593 | 3025 | { |
---|
2594 | 3026 | struct wm_adsp *dsp = container_of(work, |
---|
2595 | 3027 | struct wm_adsp, |
---|
.. | .. |
---|
2598 | 3030 | |
---|
2599 | 3031 | mutex_lock(&dsp->pwr_lock); |
---|
2600 | 3032 | |
---|
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 | + } |
---|
2605 | 3038 | |
---|
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 | + } |
---|
2609 | 3044 | |
---|
2610 | 3045 | ret = wm_adsp_load(dsp); |
---|
2611 | 3046 | if (ret != 0) |
---|
2612 | 3047 | goto err_ena; |
---|
2613 | 3048 | |
---|
2614 | | - ret = wm_adsp2_setup_algs(dsp); |
---|
| 3049 | + ret = dsp->ops->setup_algs(dsp); |
---|
2615 | 3050 | if (ret != 0) |
---|
2616 | 3051 | goto err_ena; |
---|
2617 | 3052 | |
---|
.. | .. |
---|
2624 | 3059 | if (ret != 0) |
---|
2625 | 3060 | goto err_ena; |
---|
2626 | 3061 | |
---|
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); |
---|
2638 | 3064 | |
---|
2639 | 3065 | dsp->booted = true; |
---|
2640 | 3066 | |
---|
.. | .. |
---|
2643 | 3069 | return; |
---|
2644 | 3070 | |
---|
2645 | 3071 | 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); |
---|
2648 | 3074 | 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); |
---|
2651 | 3077 | err_mutex: |
---|
2652 | 3078 | mutex_unlock(&dsp->pwr_lock); |
---|
2653 | 3079 | } |
---|
2654 | 3080 | |
---|
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) |
---|
2656 | 3082 | { |
---|
| 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]; |
---|
2657 | 3117 | int ret; |
---|
2658 | 3118 | |
---|
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; |
---|
2674 | 3126 | } |
---|
| 3127 | +EXPORT_SYMBOL_GPL(wm_adsp2_set_dspclk); |
---|
2675 | 3128 | |
---|
2676 | 3129 | int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, |
---|
2677 | 3130 | struct snd_ctl_elem_value *ucontrol) |
---|
.. | .. |
---|
2718 | 3171 | |
---|
2719 | 3172 | static void wm_adsp_stop_watchdog(struct wm_adsp *dsp) |
---|
2720 | 3173 | { |
---|
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); |
---|
2729 | 3176 | } |
---|
2730 | 3177 | |
---|
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) |
---|
2734 | 3186 | { |
---|
2735 | 3187 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
---|
2736 | 3188 | struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); |
---|
.. | .. |
---|
2739 | 3191 | |
---|
2740 | 3192 | switch (event) { |
---|
2741 | 3193 | case SND_SOC_DAPM_PRE_PMU: |
---|
2742 | | - wm_adsp2_set_dspclk(dsp, freq); |
---|
2743 | 3194 | queue_work(system_unbound_wq, &dsp->boot_work); |
---|
2744 | 3195 | break; |
---|
2745 | 3196 | case SND_SOC_DAPM_PRE_PMD: |
---|
.. | .. |
---|
2752 | 3203 | |
---|
2753 | 3204 | dsp->booted = false; |
---|
2754 | 3205 | |
---|
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); |
---|
2757 | 3208 | |
---|
2758 | 3209 | list_for_each_entry(ctl, &dsp->ctl_list, list) |
---|
2759 | 3210 | ctl->enabled = 0; |
---|
.. | .. |
---|
2770 | 3221 | |
---|
2771 | 3222 | return 0; |
---|
2772 | 3223 | } |
---|
2773 | | -EXPORT_SYMBOL_GPL(wm_adsp2_early_event); |
---|
| 3224 | +EXPORT_SYMBOL_GPL(wm_adsp_early_event); |
---|
2774 | 3225 | |
---|
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) |
---|
2777 | 3241 | { |
---|
2778 | 3242 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
---|
2779 | 3243 | struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); |
---|
.. | .. |
---|
2791 | 3255 | goto err; |
---|
2792 | 3256 | } |
---|
2793 | 3257 | |
---|
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 | + } |
---|
2797 | 3263 | |
---|
2798 | 3264 | /* Sync set controls */ |
---|
2799 | 3265 | ret = wm_coeff_sync_controls(dsp); |
---|
2800 | 3266 | if (ret != 0) |
---|
2801 | 3267 | goto err; |
---|
2802 | 3268 | |
---|
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 | + } |
---|
2804 | 3277 | |
---|
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 | + } |
---|
2811 | 3283 | |
---|
2812 | 3284 | if (wm_adsp_fw[dsp->fw].num_caps != 0) { |
---|
2813 | 3285 | ret = wm_adsp_buffer_init(dsp); |
---|
.. | .. |
---|
2818 | 3290 | dsp->running = true; |
---|
2819 | 3291 | |
---|
2820 | 3292 | mutex_unlock(&dsp->pwr_lock); |
---|
2821 | | - |
---|
2822 | 3293 | break; |
---|
2823 | 3294 | |
---|
2824 | 3295 | case SND_SOC_DAPM_PRE_PMD: |
---|
2825 | 3296 | /* Tell the firmware to cleanup */ |
---|
2826 | 3297 | wm_adsp_signal_event_controls(dsp, WM_ADSP_FW_EVENT_SHUTDOWN); |
---|
2827 | 3298 | |
---|
2828 | | - wm_adsp_stop_watchdog(dsp); |
---|
| 3299 | + if (dsp->ops->stop_watchdog) |
---|
| 3300 | + dsp->ops->stop_watchdog(dsp); |
---|
2829 | 3301 | |
---|
2830 | 3302 | /* 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); |
---|
2839 | 3305 | |
---|
2840 | 3306 | mutex_lock(&dsp->pwr_lock); |
---|
2841 | 3307 | |
---|
2842 | 3308 | dsp->running = false; |
---|
2843 | 3309 | |
---|
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); |
---|
2871 | 3314 | |
---|
2872 | 3315 | if (wm_adsp_fw[dsp->fw].num_caps != 0) |
---|
2873 | 3316 | wm_adsp_buffer_free(dsp); |
---|
| 3317 | + |
---|
| 3318 | + dsp->fatal_error = false; |
---|
2874 | 3319 | |
---|
2875 | 3320 | mutex_unlock(&dsp->pwr_lock); |
---|
2876 | 3321 | |
---|
.. | .. |
---|
2883 | 3328 | |
---|
2884 | 3329 | return 0; |
---|
2885 | 3330 | 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); |
---|
2888 | 3335 | mutex_unlock(&dsp->pwr_lock); |
---|
2889 | 3336 | return ret; |
---|
2890 | 3337 | } |
---|
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 | +} |
---|
2892 | 3356 | |
---|
2893 | 3357 | int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component) |
---|
2894 | 3358 | { |
---|
.. | .. |
---|
2917 | 3381 | { |
---|
2918 | 3382 | int ret; |
---|
2919 | 3383 | |
---|
2920 | | - ret = wm_adsp_create_name(dsp); |
---|
| 3384 | + ret = wm_adsp_common_init(dsp); |
---|
2921 | 3385 | if (ret) |
---|
2922 | 3386 | return ret; |
---|
2923 | 3387 | |
---|
.. | .. |
---|
2934 | 3398 | "Failed to clear memory retention: %d\n", ret); |
---|
2935 | 3399 | return ret; |
---|
2936 | 3400 | } |
---|
| 3401 | + |
---|
| 3402 | + dsp->ops = &wm_adsp2_ops[0]; |
---|
| 3403 | + break; |
---|
| 3404 | + case 1: |
---|
| 3405 | + dsp->ops = &wm_adsp2_ops[1]; |
---|
2937 | 3406 | break; |
---|
2938 | 3407 | default: |
---|
| 3408 | + dsp->ops = &wm_adsp2_ops[2]; |
---|
2939 | 3409 | break; |
---|
2940 | 3410 | } |
---|
2941 | 3411 | |
---|
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); |
---|
2947 | 3413 | |
---|
2948 | 3414 | return 0; |
---|
2949 | 3415 | } |
---|
2950 | 3416 | 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); |
---|
2951 | 3433 | |
---|
2952 | 3434 | void wm_adsp2_remove(struct wm_adsp *dsp) |
---|
2953 | 3435 | { |
---|
.. | .. |
---|
2969 | 3451 | |
---|
2970 | 3452 | static int wm_adsp_compr_attach(struct wm_adsp_compr *compr) |
---|
2971 | 3453 | { |
---|
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) |
---|
2977 | 3457 | return -EINVAL; |
---|
2978 | 3458 | |
---|
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; |
---|
2981 | 3471 | |
---|
2982 | 3472 | return 0; |
---|
2983 | 3473 | } |
---|
.. | .. |
---|
2999 | 3489 | |
---|
3000 | 3490 | int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream) |
---|
3001 | 3491 | { |
---|
3002 | | - struct wm_adsp_compr *compr; |
---|
| 3492 | + struct wm_adsp_compr *compr, *tmp; |
---|
| 3493 | + struct snd_soc_pcm_runtime *rtd = stream->private_data; |
---|
3003 | 3494 | int ret = 0; |
---|
3004 | 3495 | |
---|
3005 | 3496 | mutex_lock(&dsp->pwr_lock); |
---|
3006 | 3497 | |
---|
3007 | 3498 | 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); |
---|
3009 | 3501 | ret = -ENXIO; |
---|
3010 | 3502 | goto out; |
---|
3011 | 3503 | } |
---|
3012 | 3504 | |
---|
3013 | 3505 | 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); |
---|
3015 | 3508 | ret = -EINVAL; |
---|
3016 | 3509 | goto out; |
---|
3017 | 3510 | } |
---|
3018 | 3511 | |
---|
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 | + } |
---|
3024 | 3519 | } |
---|
3025 | 3520 | |
---|
3026 | 3521 | compr = kzalloc(sizeof(*compr), GFP_KERNEL); |
---|
.. | .. |
---|
3031 | 3526 | |
---|
3032 | 3527 | compr->dsp = dsp; |
---|
3033 | 3528 | compr->stream = stream; |
---|
| 3529 | + compr->name = asoc_rtd_to_codec(rtd, 0)->name; |
---|
3034 | 3530 | |
---|
3035 | | - dsp->compr = compr; |
---|
| 3531 | + list_add_tail(&compr->list, &dsp->compr_list); |
---|
3036 | 3532 | |
---|
3037 | 3533 | stream->runtime->private_data = compr; |
---|
3038 | 3534 | |
---|
.. | .. |
---|
3043 | 3539 | } |
---|
3044 | 3540 | EXPORT_SYMBOL_GPL(wm_adsp_compr_open); |
---|
3045 | 3541 | |
---|
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) |
---|
3047 | 3544 | { |
---|
3048 | 3545 | struct wm_adsp_compr *compr = stream->runtime->private_data; |
---|
3049 | 3546 | struct wm_adsp *dsp = compr->dsp; |
---|
.. | .. |
---|
3051 | 3548 | mutex_lock(&dsp->pwr_lock); |
---|
3052 | 3549 | |
---|
3053 | 3550 | wm_adsp_compr_detach(compr); |
---|
3054 | | - dsp->compr = NULL; |
---|
| 3551 | + list_del(&compr->list); |
---|
3055 | 3552 | |
---|
3056 | 3553 | kfree(compr->raw_buf); |
---|
3057 | 3554 | kfree(compr); |
---|
.. | .. |
---|
3076 | 3573 | params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS || |
---|
3077 | 3574 | params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS || |
---|
3078 | 3575 | 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); |
---|
3082 | 3579 | |
---|
3083 | 3580 | return -EINVAL; |
---|
3084 | 3581 | } |
---|
.. | .. |
---|
3106 | 3603 | return 0; |
---|
3107 | 3604 | } |
---|
3108 | 3605 | |
---|
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); |
---|
3112 | 3609 | return -EINVAL; |
---|
3113 | 3610 | } |
---|
3114 | 3611 | |
---|
.. | .. |
---|
3117 | 3614 | return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE; |
---|
3118 | 3615 | } |
---|
3119 | 3616 | |
---|
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, |
---|
3121 | 3619 | struct snd_compr_params *params) |
---|
3122 | 3620 | { |
---|
3123 | 3621 | struct wm_adsp_compr *compr = stream->runtime->private_data; |
---|
.. | .. |
---|
3130 | 3628 | |
---|
3131 | 3629 | compr->size = params->buffer; |
---|
3132 | 3630 | |
---|
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); |
---|
3135 | 3633 | |
---|
3136 | 3634 | size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf); |
---|
3137 | 3635 | compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); |
---|
.. | .. |
---|
3144 | 3642 | } |
---|
3145 | 3643 | EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); |
---|
3146 | 3644 | |
---|
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, |
---|
3148 | 3647 | struct snd_compr_caps *caps) |
---|
3149 | 3648 | { |
---|
3150 | 3649 | struct wm_adsp_compr *compr = stream->runtime->private_data; |
---|
.. | .. |
---|
3179 | 3678 | if (!mem) |
---|
3180 | 3679 | return -EINVAL; |
---|
3181 | 3680 | |
---|
3182 | | - reg = wm_adsp_region_to_reg(mem, mem_addr); |
---|
| 3681 | + reg = dsp->ops->region_to_reg(mem, mem_addr); |
---|
3183 | 3682 | |
---|
3184 | 3683 | ret = regmap_raw_read(dsp->regmap, reg, data, |
---|
3185 | 3684 | sizeof(*data) * num_words); |
---|
.. | .. |
---|
3207 | 3706 | if (!mem) |
---|
3208 | 3707 | return -EINVAL; |
---|
3209 | 3708 | |
---|
3210 | | - reg = wm_adsp_region_to_reg(mem, mem_addr); |
---|
| 3709 | + reg = dsp->ops->region_to_reg(mem, mem_addr); |
---|
3211 | 3710 | |
---|
3212 | 3711 | data = cpu_to_be32(data & 0x00ffffffu); |
---|
3213 | 3712 | |
---|
.. | .. |
---|
3217 | 3716 | static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, |
---|
3218 | 3717 | unsigned int field_offset, u32 *data) |
---|
3219 | 3718 | { |
---|
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, |
---|
3221 | 3720 | buf->host_buf_ptr + field_offset, data); |
---|
3222 | 3721 | } |
---|
3223 | 3722 | |
---|
3224 | 3723 | static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, |
---|
3225 | 3724 | unsigned int field_offset, u32 data) |
---|
3226 | 3725 | { |
---|
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, |
---|
3228 | 3727 | buf->host_buf_ptr + field_offset, data); |
---|
3229 | 3728 | } |
---|
3230 | 3729 | |
---|
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) |
---|
3232 | 3731 | { |
---|
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; |
---|
3237 | 3735 | |
---|
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++; |
---|
3240 | 3740 | |
---|
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; |
---|
3260 | 3742 | } |
---|
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, ®); |
---|
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; |
---|
3323 | 3743 | } |
---|
3324 | 3744 | |
---|
3325 | 3745 | static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) |
---|
.. | .. |
---|
3328 | 3748 | struct wm_adsp_buffer_region *region; |
---|
3329 | 3749 | u32 offset = 0; |
---|
3330 | 3750 | int i, ret; |
---|
| 3751 | + |
---|
| 3752 | + buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions), |
---|
| 3753 | + GFP_KERNEL); |
---|
| 3754 | + if (!buf->regions) |
---|
| 3755 | + return -ENOMEM; |
---|
3331 | 3756 | |
---|
3332 | 3757 | for (i = 0; i < caps->num_regions; ++i) { |
---|
3333 | 3758 | region = &buf->regions[i]; |
---|
.. | .. |
---|
3347 | 3772 | |
---|
3348 | 3773 | region->cumulative_size = offset; |
---|
3349 | 3774 | |
---|
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); |
---|
3354 | 3779 | } |
---|
3355 | 3780 | |
---|
3356 | 3781 | return 0; |
---|
.. | .. |
---|
3363 | 3788 | buf->avail = 0; |
---|
3364 | 3789 | } |
---|
3365 | 3790 | |
---|
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) |
---|
3367 | 3792 | { |
---|
3368 | 3793 | struct wm_adsp_compr_buf *buf; |
---|
3369 | | - int ret; |
---|
3370 | 3794 | |
---|
3371 | 3795 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
---|
3372 | 3796 | if (!buf) |
---|
3373 | | - return -ENOMEM; |
---|
| 3797 | + return NULL; |
---|
3374 | 3798 | |
---|
3375 | 3799 | buf->dsp = dsp; |
---|
3376 | 3800 | |
---|
3377 | 3801 | wm_adsp_buffer_clear(buf); |
---|
3378 | 3802 | |
---|
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; |
---|
3383 | 3819 | } |
---|
3384 | 3820 | |
---|
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); |
---|
3390 | 3846 | } |
---|
| 3847 | + |
---|
| 3848 | + if (!buf->host_buf_ptr) |
---|
| 3849 | + return -EIO; |
---|
| 3850 | + |
---|
| 3851 | + buf->host_buf_mem_type = WMFW_ADSP2_XM; |
---|
3391 | 3852 | |
---|
3392 | 3853 | 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, ®); |
---|
| 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); |
---|
3396 | 3882 | } |
---|
3397 | 3883 | |
---|
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 | + } |
---|
3399 | 3971 | |
---|
3400 | 3972 | return 0; |
---|
3401 | 3973 | |
---|
3402 | | -err_regions: |
---|
3403 | | - kfree(buf->regions); |
---|
3404 | | -err_buffer: |
---|
3405 | | - kfree(buf); |
---|
| 3974 | +error: |
---|
| 3975 | + wm_adsp_buffer_free(dsp); |
---|
3406 | 3976 | return ret; |
---|
3407 | 3977 | } |
---|
3408 | 3978 | |
---|
3409 | 3979 | static int wm_adsp_buffer_free(struct wm_adsp *dsp) |
---|
3410 | 3980 | { |
---|
3411 | | - if (dsp->buffer) { |
---|
3412 | | - wm_adsp_compr_detach(dsp->buffer->compr); |
---|
| 3981 | + struct wm_adsp_compr_buf *buf, *tmp; |
---|
3413 | 3982 | |
---|
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); |
---|
3416 | 3985 | |
---|
3417 | | - dsp->buffer = NULL; |
---|
| 3986 | + kfree(buf->name); |
---|
| 3987 | + kfree(buf->regions); |
---|
| 3988 | + list_del(&buf->list); |
---|
| 3989 | + kfree(buf); |
---|
3418 | 3990 | } |
---|
3419 | 3991 | |
---|
3420 | 3992 | return 0; |
---|
3421 | 3993 | } |
---|
3422 | 3994 | |
---|
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) |
---|
3424 | 4014 | { |
---|
3425 | 4015 | struct wm_adsp_compr *compr = stream->runtime->private_data; |
---|
3426 | 4016 | struct wm_adsp *dsp = compr->dsp; |
---|
3427 | 4017 | int ret = 0; |
---|
3428 | 4018 | |
---|
3429 | | - adsp_dbg(dsp, "Trigger: %d\n", cmd); |
---|
| 4019 | + compr_dbg(compr, "Trigger: %d\n", cmd); |
---|
3430 | 4020 | |
---|
3431 | 4021 | mutex_lock(&dsp->pwr_lock); |
---|
3432 | 4022 | |
---|
.. | .. |
---|
3435 | 4025 | if (!wm_adsp_compr_attached(compr)) { |
---|
3436 | 4026 | ret = wm_adsp_compr_attach(compr); |
---|
3437 | 4027 | 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); |
---|
3440 | 4030 | break; |
---|
3441 | 4031 | } |
---|
3442 | 4032 | } |
---|
| 4033 | + |
---|
| 4034 | + ret = wm_adsp_buffer_get_error(compr->buf); |
---|
| 4035 | + if (ret < 0) |
---|
| 4036 | + break; |
---|
3443 | 4037 | |
---|
3444 | 4038 | /* Trigger the IRQ at one fragment of data */ |
---|
3445 | 4039 | ret = wm_adsp_buffer_write(compr->buf, |
---|
3446 | 4040 | HOST_BUFFER_FIELD(high_water_mark), |
---|
3447 | 4041 | wm_adsp_compr_frag_words(compr)); |
---|
3448 | 4042 | 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); |
---|
3451 | 4045 | break; |
---|
3452 | 4046 | } |
---|
3453 | 4047 | break; |
---|
.. | .. |
---|
3490 | 4084 | read_index = sign_extend32(next_read_index, 23); |
---|
3491 | 4085 | |
---|
3492 | 4086 | 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"); |
---|
3494 | 4088 | return 0; |
---|
3495 | 4089 | } |
---|
3496 | 4090 | |
---|
.. | .. |
---|
3508 | 4102 | if (avail < 0) |
---|
3509 | 4103 | avail += wm_adsp_buffer_size(buf); |
---|
3510 | 4104 | |
---|
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); |
---|
3513 | 4107 | |
---|
3514 | 4108 | 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 | | - } |
---|
3532 | 4109 | |
---|
3533 | 4110 | return 0; |
---|
3534 | 4111 | } |
---|
.. | .. |
---|
3541 | 4118 | |
---|
3542 | 4119 | mutex_lock(&dsp->pwr_lock); |
---|
3543 | 4120 | |
---|
3544 | | - buf = dsp->buffer; |
---|
3545 | | - compr = dsp->compr; |
---|
3546 | | - |
---|
3547 | | - if (!buf) { |
---|
| 4121 | + if (list_empty(&dsp->buffer_list)) { |
---|
3548 | 4122 | ret = -ENODEV; |
---|
3549 | 4123 | goto out; |
---|
3550 | 4124 | } |
---|
3551 | 4125 | |
---|
3552 | 4126 | adsp_dbg(dsp, "Handling buffer IRQ\n"); |
---|
3553 | 4127 | |
---|
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; |
---|
3557 | 4130 | |
---|
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 */ |
---|
3564 | 4134 | |
---|
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 | + } |
---|
3570 | 4141 | |
---|
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; |
---|
3573 | 4150 | |
---|
3574 | 4151 | 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 | + } |
---|
3577 | 4155 | |
---|
3578 | 4156 | out: |
---|
3579 | 4157 | mutex_unlock(&dsp->pwr_lock); |
---|
.. | .. |
---|
3587 | 4165 | if (buf->irq_count & 0x01) |
---|
3588 | 4166 | return 0; |
---|
3589 | 4167 | |
---|
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); |
---|
3592 | 4169 | |
---|
3593 | 4170 | buf->irq_count |= 0x01; |
---|
3594 | 4171 | |
---|
.. | .. |
---|
3596 | 4173 | buf->irq_count); |
---|
3597 | 4174 | } |
---|
3598 | 4175 | |
---|
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, |
---|
3600 | 4178 | struct snd_compr_tstamp *tstamp) |
---|
3601 | 4179 | { |
---|
3602 | 4180 | struct wm_adsp_compr *compr = stream->runtime->private_data; |
---|
.. | .. |
---|
3604 | 4182 | struct wm_adsp_compr_buf *buf; |
---|
3605 | 4183 | int ret = 0; |
---|
3606 | 4184 | |
---|
3607 | | - adsp_dbg(dsp, "Pointer request\n"); |
---|
| 4185 | + compr_dbg(compr, "Pointer request\n"); |
---|
3608 | 4186 | |
---|
3609 | 4187 | mutex_lock(&dsp->pwr_lock); |
---|
3610 | 4188 | |
---|
3611 | 4189 | buf = compr->buf; |
---|
3612 | 4190 | |
---|
3613 | | - if (!compr->buf || compr->buf->error) { |
---|
| 4191 | + if (dsp->fatal_error || !buf || buf->error) { |
---|
3614 | 4192 | snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN); |
---|
3615 | 4193 | ret = -EIO; |
---|
3616 | 4194 | goto out; |
---|
.. | .. |
---|
3619 | 4197 | if (buf->avail < wm_adsp_compr_frag_words(compr)) { |
---|
3620 | 4198 | ret = wm_adsp_buffer_update_avail(buf); |
---|
3621 | 4199 | if (ret < 0) { |
---|
3622 | | - adsp_err(dsp, "Error reading avail: %d\n", ret); |
---|
| 4200 | + compr_err(compr, "Error reading avail: %d\n", ret); |
---|
3623 | 4201 | goto out; |
---|
3624 | 4202 | } |
---|
3625 | 4203 | |
---|
.. | .. |
---|
3630 | 4208 | if (buf->avail < wm_adsp_compr_frag_words(compr)) { |
---|
3631 | 4209 | ret = wm_adsp_buffer_get_error(buf); |
---|
3632 | 4210 | if (ret < 0) { |
---|
3633 | | - if (compr->buf->error) |
---|
| 4211 | + if (buf->error) |
---|
3634 | 4212 | snd_compr_stop_error(stream, |
---|
3635 | 4213 | SNDRV_PCM_STATE_XRUN); |
---|
3636 | 4214 | goto out; |
---|
.. | .. |
---|
3638 | 4216 | |
---|
3639 | 4217 | ret = wm_adsp_buffer_reenable_irq(buf); |
---|
3640 | 4218 | 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); |
---|
3644 | 4221 | goto out; |
---|
3645 | 4222 | } |
---|
3646 | 4223 | } |
---|
.. | .. |
---|
3660 | 4237 | static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) |
---|
3661 | 4238 | { |
---|
3662 | 4239 | struct wm_adsp_compr_buf *buf = compr->buf; |
---|
3663 | | - u8 *pack_in = (u8 *)compr->raw_buf; |
---|
3664 | | - u8 *pack_out = (u8 *)compr->raw_buf; |
---|
3665 | 4240 | unsigned int adsp_addr; |
---|
3666 | 4241 | int mem_type, nwords, max_read; |
---|
3667 | | - int i, j, ret; |
---|
| 4242 | + int i, ret; |
---|
3668 | 4243 | |
---|
3669 | 4244 | /* Calculate read parameters */ |
---|
3670 | 4245 | for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i) |
---|
.. | .. |
---|
3696 | 4271 | if (ret < 0) |
---|
3697 | 4272 | return ret; |
---|
3698 | 4273 | |
---|
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); |
---|
3706 | 4275 | |
---|
3707 | 4276 | /* update read index to account for words read */ |
---|
3708 | 4277 | buf->read_index += nwords; |
---|
.. | .. |
---|
3727 | 4296 | int ntotal = 0; |
---|
3728 | 4297 | int nwords, nbytes; |
---|
3729 | 4298 | |
---|
3730 | | - adsp_dbg(dsp, "Requested read of %zu bytes\n", count); |
---|
| 4299 | + compr_dbg(compr, "Requested read of %zu bytes\n", count); |
---|
3731 | 4300 | |
---|
3732 | | - if (!compr->buf || compr->buf->error) { |
---|
| 4301 | + if (dsp->fatal_error || !compr->buf || compr->buf->error) { |
---|
3733 | 4302 | snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN); |
---|
3734 | 4303 | return -EIO; |
---|
3735 | 4304 | } |
---|
.. | .. |
---|
3739 | 4308 | do { |
---|
3740 | 4309 | nwords = wm_adsp_buffer_capture_block(compr, count); |
---|
3741 | 4310 | 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); |
---|
3743 | 4313 | return nwords; |
---|
3744 | 4314 | } |
---|
3745 | 4315 | |
---|
3746 | 4316 | nbytes = nwords * WM_ADSP_DATA_WORD_SIZE; |
---|
3747 | 4317 | |
---|
3748 | | - adsp_dbg(dsp, "Read %d bytes\n", nbytes); |
---|
| 4318 | + compr_dbg(compr, "Read %d bytes\n", nbytes); |
---|
3749 | 4319 | |
---|
3750 | 4320 | 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); |
---|
3753 | 4323 | return -EFAULT; |
---|
3754 | 4324 | } |
---|
3755 | 4325 | |
---|
.. | .. |
---|
3762 | 4332 | return ntotal; |
---|
3763 | 4333 | } |
---|
3764 | 4334 | |
---|
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, |
---|
3766 | 4337 | size_t count) |
---|
3767 | 4338 | { |
---|
3768 | 4339 | struct wm_adsp_compr *compr = stream->runtime->private_data; |
---|
.. | .. |
---|
3782 | 4353 | } |
---|
3783 | 4354 | EXPORT_SYMBOL_GPL(wm_adsp_compr_copy); |
---|
3784 | 4355 | |
---|
3785 | | -int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions) |
---|
| 4356 | +static void wm_adsp_fatal_error(struct wm_adsp *dsp) |
---|
3786 | 4357 | { |
---|
3787 | | - struct regmap *regmap = dsp->regmap; |
---|
3788 | | - unsigned int code0, code1, lock_reg; |
---|
| 4358 | + struct wm_adsp_compr *compr; |
---|
3789 | 4359 | |
---|
3790 | | - if (!(lock_regions & WM_ADSP2_REGION_ALL)) |
---|
3791 | | - return 0; |
---|
| 4360 | + dsp->fatal_error = true; |
---|
3792 | 4361 | |
---|
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); |
---|
3810 | 4365 | } |
---|
3811 | | - |
---|
3812 | | - return 0; |
---|
3813 | 4366 | } |
---|
3814 | | -EXPORT_SYMBOL_GPL(wm_adsp2_lock); |
---|
3815 | 4367 | |
---|
3816 | | -irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) |
---|
| 4368 | +irqreturn_t wm_adsp2_bus_error(int irq, void *data) |
---|
3817 | 4369 | { |
---|
| 4370 | + struct wm_adsp *dsp = (struct wm_adsp *)data; |
---|
3818 | 4371 | unsigned int val; |
---|
3819 | 4372 | struct regmap *regmap = dsp->regmap; |
---|
3820 | 4373 | int ret = 0; |
---|
.. | .. |
---|
3830 | 4383 | |
---|
3831 | 4384 | if (val & ADSP2_WDT_TIMEOUT_STS_MASK) { |
---|
3832 | 4385 | 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); |
---|
3834 | 4388 | } |
---|
3835 | 4389 | |
---|
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"); |
---|
3839 | 4393 | else |
---|
3840 | 4394 | adsp_err(dsp, "bus error: region lock error\n"); |
---|
3841 | 4395 | |
---|
.. | .. |
---|
3877 | 4431 | } |
---|
3878 | 4432 | EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); |
---|
3879 | 4433 | |
---|
| 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 | + |
---|
3880 | 4590 | MODULE_LICENSE("GPL v2"); |
---|