wm_adsp.c (2dd044641ec3672433b9fe3ec47b236621757aa8) | wm_adsp.c (f6bc909e7673c30abcbdb329e7d0aa2e83c103d7) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * wm_adsp.c -- Wolfson ADSP support 4 * 5 * Copyright 2012 Wolfson Microelectronics plc 6 * 7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8 */ --- 5 unchanged lines hidden (view full) --- 14#include <linux/delay.h> 15#include <linux/firmware.h> 16#include <linux/list.h> 17#include <linux/pm.h> 18#include <linux/pm_runtime.h> 19#include <linux/regmap.h> 20#include <linux/regulator/consumer.h> 21#include <linux/slab.h> | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * wm_adsp.c -- Wolfson ADSP support 4 * 5 * Copyright 2012 Wolfson Microelectronics plc 6 * 7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8 */ --- 5 unchanged lines hidden (view full) --- 14#include <linux/delay.h> 15#include <linux/firmware.h> 16#include <linux/list.h> 17#include <linux/pm.h> 18#include <linux/pm_runtime.h> 19#include <linux/regmap.h> 20#include <linux/regulator/consumer.h> 21#include <linux/slab.h> |
22#include <linux/vmalloc.h> | |
23#include <linux/workqueue.h> 24#include <linux/debugfs.h> 25#include <sound/core.h> 26#include <sound/pcm.h> 27#include <sound/pcm_params.h> 28#include <sound/soc.h> 29#include <sound/jack.h> 30#include <sound/initval.h> --- 8 unchanged lines hidden (view full) --- 39 dev_err(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 40#define adsp_warn(_dsp, fmt, ...) \ 41 dev_warn(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 42#define adsp_info(_dsp, fmt, ...) \ 43 dev_info(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 44#define adsp_dbg(_dsp, fmt, ...) \ 45 dev_dbg(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 46 | 22#include <linux/workqueue.h> 23#include <linux/debugfs.h> 24#include <sound/core.h> 25#include <sound/pcm.h> 26#include <sound/pcm_params.h> 27#include <sound/soc.h> 28#include <sound/jack.h> 29#include <sound/initval.h> --- 8 unchanged lines hidden (view full) --- 38 dev_err(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 39#define adsp_warn(_dsp, fmt, ...) \ 40 dev_warn(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 41#define adsp_info(_dsp, fmt, ...) \ 42 dev_info(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 43#define adsp_dbg(_dsp, fmt, ...) \ 44 dev_dbg(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__) 45 |
47#define cs_dsp_err(_dsp, fmt, ...) \ 48 dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 49#define cs_dsp_warn(_dsp, fmt, ...) \ 50 dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 51#define cs_dsp_info(_dsp, fmt, ...) \ 52 dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 53#define cs_dsp_dbg(_dsp, fmt, ...) \ 54 dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 55 | |
56#define compr_err(_obj, fmt, ...) \ 57 adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \ 58 ##__VA_ARGS__) 59#define compr_dbg(_obj, fmt, ...) \ 60 adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \ 61 ##__VA_ARGS__) 62 | 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__) 52 |
63#define ADSP1_CONTROL_1 0x00 64#define ADSP1_CONTROL_2 0x02 65#define ADSP1_CONTROL_3 0x03 66#define ADSP1_CONTROL_4 0x04 67#define ADSP1_CONTROL_5 0x06 68#define ADSP1_CONTROL_6 0x07 69#define ADSP1_CONTROL_7 0x08 70#define ADSP1_CONTROL_8 0x09 71#define ADSP1_CONTROL_9 0x0A 72#define ADSP1_CONTROL_10 0x0B 73#define ADSP1_CONTROL_11 0x0C 74#define ADSP1_CONTROL_12 0x0D 75#define ADSP1_CONTROL_13 0x0F 76#define ADSP1_CONTROL_14 0x10 77#define ADSP1_CONTROL_15 0x11 78#define ADSP1_CONTROL_16 0x12 79#define ADSP1_CONTROL_17 0x13 80#define ADSP1_CONTROL_18 0x14 81#define ADSP1_CONTROL_19 0x16 82#define ADSP1_CONTROL_20 0x17 83#define ADSP1_CONTROL_21 0x18 84#define ADSP1_CONTROL_22 0x1A 85#define ADSP1_CONTROL_23 0x1B 86#define ADSP1_CONTROL_24 0x1C 87#define ADSP1_CONTROL_25 0x1E 88#define ADSP1_CONTROL_26 0x20 89#define ADSP1_CONTROL_27 0x21 90#define ADSP1_CONTROL_28 0x22 91#define ADSP1_CONTROL_29 0x23 92#define ADSP1_CONTROL_30 0x24 93#define ADSP1_CONTROL_31 0x26 94 95/* 96 * ADSP1 Control 19 97 */ 98#define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 99#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 100#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 101 102 103/* 104 * ADSP1 Control 30 105 */ 106#define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */ 107#define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */ 108#define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */ 109#define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */ 110#define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 111#define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 112#define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 113#define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 114#define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 115#define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 116#define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 117#define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 118#define ADSP1_START 0x0001 /* DSP1_START */ 119#define ADSP1_START_MASK 0x0001 /* DSP1_START */ 120#define ADSP1_START_SHIFT 0 /* DSP1_START */ 121#define ADSP1_START_WIDTH 1 /* DSP1_START */ 122 123/* 124 * ADSP1 Control 31 125 */ 126#define ADSP1_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 127#define ADSP1_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 128#define ADSP1_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 129 130#define ADSP2_CONTROL 0x0 131#define ADSP2_CLOCKING 0x1 132#define ADSP2V2_CLOCKING 0x2 133#define ADSP2_STATUS1 0x4 134#define ADSP2_WDMA_CONFIG_1 0x30 135#define ADSP2_WDMA_CONFIG_2 0x31 136#define ADSP2V2_WDMA_CONFIG_2 0x32 137#define ADSP2_RDMA_CONFIG_1 0x34 138 139#define ADSP2_SCRATCH0 0x40 140#define ADSP2_SCRATCH1 0x41 141#define ADSP2_SCRATCH2 0x42 142#define ADSP2_SCRATCH3 0x43 143 144#define ADSP2V2_SCRATCH0_1 0x40 145#define ADSP2V2_SCRATCH2_3 0x42 146 147/* 148 * ADSP2 Control 149 */ 150 151#define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */ 152#define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */ 153#define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */ 154#define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */ 155#define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 156#define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 157#define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 158#define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 159#define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 160#define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 161#define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 162#define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 163#define ADSP2_START 0x0001 /* DSP1_START */ 164#define ADSP2_START_MASK 0x0001 /* DSP1_START */ 165#define ADSP2_START_SHIFT 0 /* DSP1_START */ 166#define ADSP2_START_WIDTH 1 /* DSP1_START */ 167 168/* 169 * ADSP2 clocking 170 */ 171#define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 172#define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 173#define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 174 175/* 176 * ADSP2V2 clocking 177 */ 178#define ADSP2V2_CLK_SEL_MASK 0x70000 /* CLK_SEL_ENA */ 179#define ADSP2V2_CLK_SEL_SHIFT 16 /* CLK_SEL_ENA */ 180#define ADSP2V2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 181 182#define ADSP2V2_RATE_MASK 0x7800 /* DSP_RATE */ 183#define ADSP2V2_RATE_SHIFT 11 /* DSP_RATE */ 184#define ADSP2V2_RATE_WIDTH 4 /* DSP_RATE */ 185 186/* 187 * ADSP2 Status 1 188 */ 189#define ADSP2_RAM_RDY 0x0001 190#define ADSP2_RAM_RDY_MASK 0x0001 191#define ADSP2_RAM_RDY_SHIFT 0 192#define ADSP2_RAM_RDY_WIDTH 1 193 194/* 195 * ADSP2 Lock support 196 */ 197#define ADSP2_LOCK_CODE_0 0x5555 198#define ADSP2_LOCK_CODE_1 0xAAAA 199 200#define ADSP2_WATCHDOG 0x0A 201#define ADSP2_BUS_ERR_ADDR 0x52 202#define ADSP2_REGION_LOCK_STATUS 0x64 203#define ADSP2_LOCK_REGION_1_LOCK_REGION_0 0x66 204#define ADSP2_LOCK_REGION_3_LOCK_REGION_2 0x68 205#define ADSP2_LOCK_REGION_5_LOCK_REGION_4 0x6A 206#define ADSP2_LOCK_REGION_7_LOCK_REGION_6 0x6C 207#define ADSP2_LOCK_REGION_9_LOCK_REGION_8 0x6E 208#define ADSP2_LOCK_REGION_CTRL 0x7A 209#define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR 0x7C 210 211#define ADSP2_REGION_LOCK_ERR_MASK 0x8000 212#define ADSP2_ADDR_ERR_MASK 0x4000 213#define ADSP2_WDT_TIMEOUT_STS_MASK 0x2000 214#define ADSP2_CTRL_ERR_PAUSE_ENA 0x0002 215#define ADSP2_CTRL_ERR_EINT 0x0001 216 217#define ADSP2_BUS_ERR_ADDR_MASK 0x00FFFFFF 218#define ADSP2_XMEM_ERR_ADDR_MASK 0x0000FFFF 219#define ADSP2_PMEM_ERR_ADDR_MASK 0x7FFF0000 220#define ADSP2_PMEM_ERR_ADDR_SHIFT 16 221#define ADSP2_WDT_ENA_MASK 0xFFFFFFFD 222 223#define ADSP2_LOCK_REGION_SHIFT 16 224 | |
225#define ADSP_MAX_STD_CTRL_SIZE 512 226 | 53#define ADSP_MAX_STD_CTRL_SIZE 512 54 |
227#define CS_DSP_ACKED_CTL_TIMEOUT_MS 100 228#define CS_DSP_ACKED_CTL_N_QUICKPOLLS 10 229#define CS_DSP_ACKED_CTL_MIN_VALUE 0 230#define CS_DSP_ACKED_CTL_MAX_VALUE 0xFFFFFF 231 232/* 233 * Event control messages 234 */ 235#define CS_DSP_FW_EVENT_SHUTDOWN 0x000001 236 237/* 238 * HALO system info 239 */ 240#define HALO_AHBM_WINDOW_DEBUG_0 0x02040 241#define HALO_AHBM_WINDOW_DEBUG_1 0x02044 242 243/* 244 * HALO core 245 */ 246#define HALO_SCRATCH1 0x005c0 247#define HALO_SCRATCH2 0x005c8 248#define HALO_SCRATCH3 0x005d0 249#define HALO_SCRATCH4 0x005d8 250#define HALO_CCM_CORE_CONTROL 0x41000 251#define HALO_CORE_SOFT_RESET 0x00010 252#define HALO_WDT_CONTROL 0x47000 253 254/* 255 * HALO MPU banks 256 */ 257#define HALO_MPU_XMEM_ACCESS_0 0x43000 258#define HALO_MPU_YMEM_ACCESS_0 0x43004 259#define HALO_MPU_WINDOW_ACCESS_0 0x43008 260#define HALO_MPU_XREG_ACCESS_0 0x4300C 261#define HALO_MPU_YREG_ACCESS_0 0x43014 262#define HALO_MPU_XMEM_ACCESS_1 0x43018 263#define HALO_MPU_YMEM_ACCESS_1 0x4301C 264#define HALO_MPU_WINDOW_ACCESS_1 0x43020 265#define HALO_MPU_XREG_ACCESS_1 0x43024 266#define HALO_MPU_YREG_ACCESS_1 0x4302C 267#define HALO_MPU_XMEM_ACCESS_2 0x43030 268#define HALO_MPU_YMEM_ACCESS_2 0x43034 269#define HALO_MPU_WINDOW_ACCESS_2 0x43038 270#define HALO_MPU_XREG_ACCESS_2 0x4303C 271#define HALO_MPU_YREG_ACCESS_2 0x43044 272#define HALO_MPU_XMEM_ACCESS_3 0x43048 273#define HALO_MPU_YMEM_ACCESS_3 0x4304C 274#define HALO_MPU_WINDOW_ACCESS_3 0x43050 275#define HALO_MPU_XREG_ACCESS_3 0x43054 276#define HALO_MPU_YREG_ACCESS_3 0x4305C 277#define HALO_MPU_XM_VIO_ADDR 0x43100 278#define HALO_MPU_XM_VIO_STATUS 0x43104 279#define HALO_MPU_YM_VIO_ADDR 0x43108 280#define HALO_MPU_YM_VIO_STATUS 0x4310C 281#define HALO_MPU_PM_VIO_ADDR 0x43110 282#define HALO_MPU_PM_VIO_STATUS 0x43114 283#define HALO_MPU_LOCK_CONFIG 0x43140 284 285/* 286 * HALO_AHBM_WINDOW_DEBUG_1 287 */ 288#define HALO_AHBM_CORE_ERR_ADDR_MASK 0x0fffff00 289#define HALO_AHBM_CORE_ERR_ADDR_SHIFT 8 290#define HALO_AHBM_FLAGS_ERR_MASK 0x000000ff 291 292/* 293 * HALO_CCM_CORE_CONTROL 294 */ 295#define HALO_CORE_RESET 0x00000200 296#define HALO_CORE_EN 0x00000001 297 298/* 299 * HALO_CORE_SOFT_RESET 300 */ 301#define HALO_CORE_SOFT_RESET_MASK 0x00000001 302 303/* 304 * HALO_WDT_CONTROL 305 */ 306#define HALO_WDT_EN_MASK 0x00000001 307 308/* 309 * HALO_MPU_?M_VIO_STATUS 310 */ 311#define HALO_MPU_VIO_STS_MASK 0x007e0000 312#define HALO_MPU_VIO_STS_SHIFT 17 313#define HALO_MPU_VIO_ERR_WR_MASK 0x00008000 314#define HALO_MPU_VIO_ERR_SRC_MASK 0x00007fff 315#define HALO_MPU_VIO_ERR_SRC_SHIFT 0 316 317static const struct cs_dsp_ops cs_dsp_adsp1_ops; 318static const struct cs_dsp_ops cs_dsp_adsp2_ops[]; 319static const struct cs_dsp_ops cs_dsp_halo_ops; 320 | |
321static const struct cs_dsp_client_ops wm_adsp1_client_ops; 322static const struct cs_dsp_client_ops wm_adsp2_client_ops; 323 | 55static const struct cs_dsp_client_ops wm_adsp1_client_ops; 56static const struct cs_dsp_client_ops wm_adsp2_client_ops; 57 |
324struct cs_dsp_buf { 325 struct list_head list; 326 void *buf; 327}; 328 329static struct cs_dsp_buf *cs_dsp_buf_alloc(const void *src, size_t len, 330 struct list_head *list) 331{ 332 struct cs_dsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL); 333 334 if (buf == NULL) 335 return NULL; 336 337 buf->buf = vmalloc(len); 338 if (!buf->buf) { 339 kfree(buf); 340 return NULL; 341 } 342 memcpy(buf->buf, src, len); 343 344 if (list) 345 list_add_tail(&buf->list, list); 346 347 return buf; 348} 349 350static void cs_dsp_buf_free(struct list_head *list) 351{ 352 while (!list_empty(list)) { 353 struct cs_dsp_buf *buf = list_first_entry(list, 354 struct cs_dsp_buf, 355 list); 356 list_del(&buf->list); 357 vfree(buf->buf); 358 kfree(buf); 359 } 360} 361 | |
362#define WM_ADSP_FW_MBC_VSS 0 363#define WM_ADSP_FW_HIFI 1 364#define WM_ADSP_FW_TX 2 365#define WM_ADSP_FW_TX_SPK 3 366#define WM_ADSP_FW_RX 4 367#define WM_ADSP_FW_RX_ANC 5 368#define WM_ADSP_FW_CTRL 6 369#define WM_ADSP_FW_ASR 7 --- 108 unchanged lines hidden (view full) --- 478 u32 *raw_buf; 479 unsigned int copied_total; 480 481 unsigned int sample_rate; 482 483 const char *name; 484}; 485 | 58#define WM_ADSP_FW_MBC_VSS 0 59#define WM_ADSP_FW_HIFI 1 60#define WM_ADSP_FW_TX 2 61#define WM_ADSP_FW_TX_SPK 3 62#define WM_ADSP_FW_RX 4 63#define WM_ADSP_FW_RX_ANC 5 64#define WM_ADSP_FW_CTRL 6 65#define WM_ADSP_FW_ASR 7 --- 108 unchanged lines hidden (view full) --- 174 u32 *raw_buf; 175 unsigned int copied_total; 176 177 unsigned int sample_rate; 178 179 const char *name; 180}; 181 |
486#define CS_DSP_DATA_WORD_SIZE 3 487 | |
488#define WM_ADSP_MIN_FRAGMENTS 1 489#define WM_ADSP_MAX_FRAGMENTS 256 490#define WM_ADSP_MIN_FRAGMENT_SIZE (64 * CS_DSP_DATA_WORD_SIZE) 491#define WM_ADSP_MAX_FRAGMENT_SIZE (4096 * CS_DSP_DATA_WORD_SIZE) 492 493#define WM_ADSP_ALG_XM_STRUCT_MAGIC 0x49aec7 494 495#define HOST_BUFFER_FIELD(field) \ --- 115 unchanged lines hidden (view full) --- 611 612struct wm_coeff_ctl { 613 const char *name; 614 struct cs_dsp_coeff_ctl *cs_ctl; 615 struct soc_bytes_ext bytes_ext; 616 struct work_struct work; 617}; 618 | 182#define WM_ADSP_MIN_FRAGMENTS 1 183#define WM_ADSP_MAX_FRAGMENTS 256 184#define WM_ADSP_MIN_FRAGMENT_SIZE (64 * CS_DSP_DATA_WORD_SIZE) 185#define WM_ADSP_MAX_FRAGMENT_SIZE (4096 * CS_DSP_DATA_WORD_SIZE) 186 187#define WM_ADSP_ALG_XM_STRUCT_MAGIC 0x49aec7 188 189#define HOST_BUFFER_FIELD(field) \ --- 115 unchanged lines hidden (view full) --- 305 306struct wm_coeff_ctl { 307 const char *name; 308 struct cs_dsp_coeff_ctl *cs_ctl; 309 struct soc_bytes_ext bytes_ext; 310 struct work_struct work; 311}; 312 |
619static const char *cs_dsp_mem_region_name(unsigned int type) 620{ 621 switch (type) { 622 case WMFW_ADSP1_PM: 623 return "PM"; 624 case WMFW_HALO_PM_PACKED: 625 return "PM_PACKED"; 626 case WMFW_ADSP1_DM: 627 return "DM"; 628 case WMFW_ADSP2_XM: 629 return "XM"; 630 case WMFW_HALO_XM_PACKED: 631 return "XM_PACKED"; 632 case WMFW_ADSP2_YM: 633 return "YM"; 634 case WMFW_HALO_YM_PACKED: 635 return "YM_PACKED"; 636 case WMFW_ADSP1_ZM: 637 return "ZM"; 638 default: 639 return NULL; 640 } 641} 642 643#ifdef CONFIG_DEBUG_FS 644static void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, const char *s) 645{ 646 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); 647 648 kfree(dsp->wmfw_file_name); 649 dsp->wmfw_file_name = tmp; 650} 651 652static void cs_dsp_debugfs_save_binname(struct cs_dsp *dsp, const char *s) 653{ 654 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); 655 656 kfree(dsp->bin_file_name); 657 dsp->bin_file_name = tmp; 658} 659 660static void cs_dsp_debugfs_clear(struct cs_dsp *dsp) 661{ 662 kfree(dsp->wmfw_file_name); 663 kfree(dsp->bin_file_name); 664 dsp->wmfw_file_name = NULL; 665 dsp->bin_file_name = NULL; 666} 667 668static ssize_t cs_dsp_debugfs_wmfw_read(struct file *file, 669 char __user *user_buf, 670 size_t count, loff_t *ppos) 671{ 672 struct cs_dsp *dsp = file->private_data; 673 ssize_t ret; 674 675 mutex_lock(&dsp->pwr_lock); 676 677 if (!dsp->wmfw_file_name || !dsp->booted) 678 ret = 0; 679 else 680 ret = simple_read_from_buffer(user_buf, count, ppos, 681 dsp->wmfw_file_name, 682 strlen(dsp->wmfw_file_name)); 683 684 mutex_unlock(&dsp->pwr_lock); 685 return ret; 686} 687 688static ssize_t cs_dsp_debugfs_bin_read(struct file *file, 689 char __user *user_buf, 690 size_t count, loff_t *ppos) 691{ 692 struct cs_dsp *dsp = file->private_data; 693 ssize_t ret; 694 695 mutex_lock(&dsp->pwr_lock); 696 697 if (!dsp->bin_file_name || !dsp->booted) 698 ret = 0; 699 else 700 ret = simple_read_from_buffer(user_buf, count, ppos, 701 dsp->bin_file_name, 702 strlen(dsp->bin_file_name)); 703 704 mutex_unlock(&dsp->pwr_lock); 705 return ret; 706} 707 708static const struct { 709 const char *name; 710 const struct file_operations fops; 711} cs_dsp_debugfs_fops[] = { 712 { 713 .name = "wmfw_file_name", 714 .fops = { 715 .open = simple_open, 716 .read = cs_dsp_debugfs_wmfw_read, 717 }, 718 }, 719 { 720 .name = "bin_file_name", 721 .fops = { 722 .open = simple_open, 723 .read = cs_dsp_debugfs_bin_read, 724 }, 725 }, 726}; 727 728static void cs_dsp_init_debugfs(struct cs_dsp *dsp, 729 struct dentry *debugfs_root) 730{ 731 struct dentry *root = NULL; 732 int i; 733 734 root = debugfs_create_dir(dsp->name, debugfs_root); 735 736 debugfs_create_bool("booted", 0444, root, &dsp->booted); 737 debugfs_create_bool("running", 0444, root, &dsp->running); 738 debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id); 739 debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version); 740 741 for (i = 0; i < ARRAY_SIZE(cs_dsp_debugfs_fops); ++i) 742 debugfs_create_file(cs_dsp_debugfs_fops[i].name, 0444, root, 743 dsp, &cs_dsp_debugfs_fops[i].fops); 744 745 dsp->debugfs_root = root; 746} 747 748static void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp) 749{ 750 cs_dsp_debugfs_clear(dsp); 751 debugfs_remove_recursive(dsp->debugfs_root); 752 dsp->debugfs_root = NULL; 753} 754#else 755static inline void cs_dsp_init_debugfs(struct cs_dsp *dsp, 756 struct dentry *debugfs_root) 757{ 758} 759 760static inline void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp) 761{ 762} 763 764static inline void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, 765 const char *s) 766{ 767} 768 769static inline void cs_dsp_debugfs_save_binname(struct cs_dsp *dsp, 770 const char *s) 771{ 772} 773 774static inline void cs_dsp_debugfs_clear(struct cs_dsp *dsp) 775{ 776} 777#endif 778 | |
779int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 780 struct snd_ctl_elem_value *ucontrol) 781{ 782 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 783 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 784 struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); 785 786 ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw; --- 35 unchanged lines hidden (view full) --- 822 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 823 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 824 SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 825 SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 826 SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 827}; 828EXPORT_SYMBOL_GPL(wm_adsp_fw_enum); 829 | 313int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 314 struct snd_ctl_elem_value *ucontrol) 315{ 316 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 317 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 318 struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); 319 320 ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw; --- 35 unchanged lines hidden (view full) --- 356 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 357 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 358 SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 359 SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 360 SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 361}; 362EXPORT_SYMBOL_GPL(wm_adsp_fw_enum); 363 |
830static const struct cs_dsp_region *cs_dsp_find_region(struct cs_dsp *dsp, 831 int type) 832{ 833 int i; 834 835 for (i = 0; i < dsp->num_mems; i++) 836 if (dsp->mem[i].type == type) 837 return &dsp->mem[i]; 838 839 return NULL; 840} 841 842static unsigned int cs_dsp_region_to_reg(struct cs_dsp_region const *mem, 843 unsigned int offset) 844{ 845 switch (mem->type) { 846 case WMFW_ADSP1_PM: 847 return mem->base + (offset * 3); 848 case WMFW_ADSP1_DM: 849 case WMFW_ADSP2_XM: 850 case WMFW_ADSP2_YM: 851 case WMFW_ADSP1_ZM: 852 return mem->base + (offset * 2); 853 default: 854 WARN(1, "Unknown memory region type"); 855 return offset; 856 } 857} 858 859static unsigned int cs_dsp_halo_region_to_reg(struct cs_dsp_region const *mem, 860 unsigned int offset) 861{ 862 switch (mem->type) { 863 case WMFW_ADSP2_XM: 864 case WMFW_ADSP2_YM: 865 return mem->base + (offset * 4); 866 case WMFW_HALO_XM_PACKED: 867 case WMFW_HALO_YM_PACKED: 868 return (mem->base + (offset * 3)) & ~0x3; 869 case WMFW_HALO_PM_PACKED: 870 return mem->base + (offset * 5); 871 default: 872 WARN(1, "Unknown memory region type"); 873 return offset; 874 } 875} 876 877static void cs_dsp_read_fw_status(struct cs_dsp *dsp, 878 int noffs, unsigned int *offs) 879{ 880 unsigned int i; 881 int ret; 882 883 for (i = 0; i < noffs; ++i) { 884 ret = regmap_read(dsp->regmap, dsp->base + offs[i], &offs[i]); 885 if (ret) { 886 cs_dsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret); 887 return; 888 } 889 } 890} 891 892static void cs_dsp_adsp2_show_fw_status(struct cs_dsp *dsp) 893{ 894 unsigned int offs[] = { 895 ADSP2_SCRATCH0, ADSP2_SCRATCH1, ADSP2_SCRATCH2, ADSP2_SCRATCH3, 896 }; 897 898 cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs); 899 900 cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 901 offs[0], offs[1], offs[2], offs[3]); 902} 903 904static void cs_dsp_adsp2v2_show_fw_status(struct cs_dsp *dsp) 905{ 906 unsigned int offs[] = { ADSP2V2_SCRATCH0_1, ADSP2V2_SCRATCH2_3 }; 907 908 cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs); 909 910 cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 911 offs[0] & 0xFFFF, offs[0] >> 16, 912 offs[1] & 0xFFFF, offs[1] >> 16); 913} 914 915static void cs_dsp_halo_show_fw_status(struct cs_dsp *dsp) 916{ 917 unsigned int offs[] = { 918 HALO_SCRATCH1, HALO_SCRATCH2, HALO_SCRATCH3, HALO_SCRATCH4, 919 }; 920 921 cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs); 922 923 cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 924 offs[0], offs[1], offs[2], offs[3]); 925} 926 | |
927static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext) 928{ 929 return container_of(ext, struct wm_coeff_ctl, bytes_ext); 930} 931 | 364static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext) 365{ 366 return container_of(ext, struct wm_coeff_ctl, bytes_ext); 367} 368 |
932static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg) 933{ 934 const struct cs_dsp_alg_region *alg_region = &ctl->alg_region; 935 struct cs_dsp *dsp = ctl->dsp; 936 const struct cs_dsp_region *mem; 937 938 mem = cs_dsp_find_region(dsp, alg_region->type); 939 if (!mem) { 940 cs_dsp_err(dsp, "No base for region %x\n", 941 alg_region->type); 942 return -EINVAL; 943 } 944 945 *reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset); 946 947 return 0; 948} 949 | |
950static int wm_coeff_info(struct snd_kcontrol *kctl, 951 struct snd_ctl_elem_info *uinfo) 952{ 953 struct soc_bytes_ext *bytes_ext = 954 (struct soc_bytes_ext *)kctl->private_value; 955 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 956 struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; 957 --- 9 unchanged lines hidden (view full) --- 967 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 968 uinfo->count = cs_ctl->len; 969 break; 970 } 971 972 return 0; 973} 974 | 369static int wm_coeff_info(struct snd_kcontrol *kctl, 370 struct snd_ctl_elem_info *uinfo) 371{ 372 struct soc_bytes_ext *bytes_ext = 373 (struct soc_bytes_ext *)kctl->private_value; 374 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 375 struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; 376 --- 9 unchanged lines hidden (view full) --- 386 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 387 uinfo->count = cs_ctl->len; 388 break; 389 } 390 391 return 0; 392} 393 |
975static int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, 976 unsigned int event_id) 977{ 978 struct cs_dsp *dsp = ctl->dsp; 979 __be32 val = cpu_to_be32(event_id); 980 unsigned int reg; 981 int i, ret; 982 983 if (!dsp->running) 984 return -EPERM; 985 986 ret = cs_dsp_coeff_base_reg(ctl, ®); 987 if (ret) 988 return ret; 989 990 cs_dsp_dbg(dsp, "Sending 0x%x to acked control alg 0x%x %s:0x%x\n", 991 event_id, ctl->alg_region.alg, 992 cs_dsp_mem_region_name(ctl->alg_region.type), ctl->offset); 993 994 ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); 995 if (ret) { 996 cs_dsp_err(dsp, "Failed to write %x: %d\n", reg, ret); 997 return ret; 998 } 999 1000 /* 1001 * Poll for ack, we initially poll at ~1ms intervals for firmwares 1002 * that respond quickly, then go to ~10ms polls. A firmware is unlikely 1003 * to ack instantly so we do the first 1ms delay before reading the 1004 * control to avoid a pointless bus transaction 1005 */ 1006 for (i = 0; i < CS_DSP_ACKED_CTL_TIMEOUT_MS;) { 1007 switch (i) { 1008 case 0 ... CS_DSP_ACKED_CTL_N_QUICKPOLLS - 1: 1009 usleep_range(1000, 2000); 1010 i++; 1011 break; 1012 default: 1013 usleep_range(10000, 20000); 1014 i += 10; 1015 break; 1016 } 1017 1018 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 1019 if (ret) { 1020 cs_dsp_err(dsp, "Failed to read %x: %d\n", reg, ret); 1021 return ret; 1022 } 1023 1024 if (val == 0) { 1025 cs_dsp_dbg(dsp, "Acked control ACKED at poll %u\n", i); 1026 return 0; 1027 } 1028 } 1029 1030 cs_dsp_warn(dsp, "Acked control @0x%x alg:0x%x %s:0x%x timed out\n", 1031 reg, ctl->alg_region.alg, 1032 cs_dsp_mem_region_name(ctl->alg_region.type), 1033 ctl->offset); 1034 1035 return -ETIMEDOUT; 1036} 1037 1038static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, 1039 const void *buf, size_t len) 1040{ 1041 struct cs_dsp *dsp = ctl->dsp; 1042 void *scratch; 1043 int ret; 1044 unsigned int reg; 1045 1046 ret = cs_dsp_coeff_base_reg(ctl, ®); 1047 if (ret) 1048 return ret; 1049 1050 scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA); 1051 if (!scratch) 1052 return -ENOMEM; 1053 1054 ret = regmap_raw_write(dsp->regmap, reg, scratch, 1055 len); 1056 if (ret) { 1057 cs_dsp_err(dsp, "Failed to write %zu bytes to %x: %d\n", 1058 len, reg, ret); 1059 kfree(scratch); 1060 return ret; 1061 } 1062 cs_dsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg); 1063 1064 kfree(scratch); 1065 1066 return 0; 1067} 1068 1069static int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, 1070 const void *buf, size_t len) 1071{ 1072 int ret = 0; 1073 1074 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 1075 ret = -EPERM; 1076 else if (buf != ctl->cache) 1077 memcpy(ctl->cache, buf, len); 1078 1079 ctl->set = 1; 1080 if (ctl->enabled && ctl->dsp->running) 1081 ret = cs_dsp_coeff_write_ctrl_raw(ctl, buf, len); 1082 1083 return ret; 1084} 1085 | |
1086static int wm_coeff_put(struct snd_kcontrol *kctl, 1087 struct snd_ctl_elem_value *ucontrol) 1088{ 1089 struct soc_bytes_ext *bytes_ext = 1090 (struct soc_bytes_ext *)kctl->private_value; 1091 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1092 struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; 1093 char *p = ucontrol->value.bytes.data; --- 47 unchanged lines hidden (view full) --- 1141 else 1142 ret = -EPERM; 1143 1144 mutex_unlock(&cs_ctl->dsp->pwr_lock); 1145 1146 return ret; 1147} 1148 | 394static int wm_coeff_put(struct snd_kcontrol *kctl, 395 struct snd_ctl_elem_value *ucontrol) 396{ 397 struct soc_bytes_ext *bytes_ext = 398 (struct soc_bytes_ext *)kctl->private_value; 399 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 400 struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; 401 char *p = ucontrol->value.bytes.data; --- 47 unchanged lines hidden (view full) --- 449 else 450 ret = -EPERM; 451 452 mutex_unlock(&cs_ctl->dsp->pwr_lock); 453 454 return ret; 455} 456 |
1149static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, 1150 void *buf, size_t len) 1151{ 1152 struct cs_dsp *dsp = ctl->dsp; 1153 void *scratch; 1154 int ret; 1155 unsigned int reg; 1156 1157 ret = cs_dsp_coeff_base_reg(ctl, ®); 1158 if (ret) 1159 return ret; 1160 1161 scratch = kmalloc(len, GFP_KERNEL | GFP_DMA); 1162 if (!scratch) 1163 return -ENOMEM; 1164 1165 ret = regmap_raw_read(dsp->regmap, reg, scratch, len); 1166 if (ret) { 1167 cs_dsp_err(dsp, "Failed to read %zu bytes from %x: %d\n", 1168 len, reg, ret); 1169 kfree(scratch); 1170 return ret; 1171 } 1172 cs_dsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg); 1173 1174 memcpy(buf, scratch, len); 1175 kfree(scratch); 1176 1177 return 0; 1178} 1179 1180static int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, void *buf, size_t len) 1181{ 1182 int ret = 0; 1183 1184 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { 1185 if (ctl->enabled && ctl->dsp->running) 1186 return cs_dsp_coeff_read_ctrl_raw(ctl, buf, len); 1187 else 1188 return -EPERM; 1189 } else { 1190 if (!ctl->flags && ctl->enabled && ctl->dsp->running) 1191 ret = cs_dsp_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len); 1192 1193 if (buf != ctl->cache) 1194 memcpy(buf, ctl->cache, len); 1195 } 1196 1197 return ret; 1198} 1199 | |
1200static int wm_coeff_get(struct snd_kcontrol *kctl, 1201 struct snd_ctl_elem_value *ucontrol) 1202{ 1203 struct soc_bytes_ext *bytes_ext = 1204 (struct soc_bytes_ext *)kctl->private_value; 1205 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1206 struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; 1207 char *p = ucontrol->value.bytes.data; --- 115 unchanged lines hidden (view full) --- 1323 1324 return 0; 1325 1326err_kcontrol: 1327 kfree(kcontrol); 1328 return ret; 1329} 1330 | 457static int wm_coeff_get(struct snd_kcontrol *kctl, 458 struct snd_ctl_elem_value *ucontrol) 459{ 460 struct soc_bytes_ext *bytes_ext = 461 (struct soc_bytes_ext *)kctl->private_value; 462 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 463 struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; 464 char *p = ucontrol->value.bytes.data; --- 115 unchanged lines hidden (view full) --- 580 581 return 0; 582 583err_kcontrol: 584 kfree(kcontrol); 585 return ret; 586} 587 |
1331static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp) 1332{ 1333 struct cs_dsp_coeff_ctl *ctl; 1334 int ret; 1335 1336 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1337 if (!ctl->enabled || ctl->set) 1338 continue; 1339 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 1340 continue; 1341 1342 /* 1343 * For readable controls populate the cache from the DSP memory. 1344 * For non-readable controls the cache was zero-filled when 1345 * created so we don't need to do anything. 1346 */ 1347 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) { 1348 ret = cs_dsp_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len); 1349 if (ret < 0) 1350 return ret; 1351 } 1352 } 1353 1354 return 0; 1355} 1356 1357static int cs_dsp_coeff_sync_controls(struct cs_dsp *dsp) 1358{ 1359 struct cs_dsp_coeff_ctl *ctl; 1360 int ret; 1361 1362 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1363 if (!ctl->enabled) 1364 continue; 1365 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) { 1366 ret = cs_dsp_coeff_write_ctrl_raw(ctl, ctl->cache, 1367 ctl->len); 1368 if (ret < 0) 1369 return ret; 1370 } 1371 } 1372 1373 return 0; 1374} 1375 1376static void cs_dsp_signal_event_controls(struct cs_dsp *dsp, 1377 unsigned int event) 1378{ 1379 struct cs_dsp_coeff_ctl *ctl; 1380 int ret; 1381 1382 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1383 if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT) 1384 continue; 1385 1386 if (!ctl->enabled) 1387 continue; 1388 1389 ret = cs_dsp_coeff_write_acked_control(ctl, event); 1390 if (ret) 1391 cs_dsp_warn(dsp, 1392 "Failed to send 0x%x event to alg 0x%x (%d)\n", 1393 event, ctl->alg_region.alg, ret); 1394 } 1395} 1396 | |
1397static void wm_adsp_ctl_work(struct work_struct *work) 1398{ 1399 struct wm_coeff_ctl *ctl = container_of(work, 1400 struct wm_coeff_ctl, 1401 work); 1402 struct wm_adsp *dsp = container_of(ctl->cs_ctl->dsp, 1403 struct wm_adsp, 1404 cs_dsp); 1405 1406 wmfw_add_ctl(dsp, ctl); 1407} 1408 | 588static void wm_adsp_ctl_work(struct work_struct *work) 589{ 590 struct wm_coeff_ctl *ctl = container_of(work, 591 struct wm_coeff_ctl, 592 work); 593 struct wm_adsp *dsp = container_of(ctl->cs_ctl->dsp, 594 struct wm_adsp, 595 cs_dsp); 596 597 wmfw_add_ctl(dsp, ctl); 598} 599 |
1409static void cs_dsp_free_ctl_blk(struct cs_dsp_coeff_ctl *ctl) 1410{ 1411 kfree(ctl->cache); 1412 kfree(ctl->subname); 1413 kfree(ctl); 1414} 1415 | |
1416static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl) 1417{ 1418 struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp); 1419 struct cs_dsp *cs_dsp = &dsp->cs_dsp; 1420 struct wm_coeff_ctl *ctl; 1421 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 1422 const char *region_name; 1423 int ret; --- 69 unchanged lines hidden (view full) --- 1493 struct wm_coeff_ctl *ctl = cs_ctl->priv; 1494 1495 cancel_work_sync(&ctl->work); 1496 1497 kfree(ctl->name); 1498 kfree(ctl); 1499} 1500 | 600static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl) 601{ 602 struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp); 603 struct cs_dsp *cs_dsp = &dsp->cs_dsp; 604 struct wm_coeff_ctl *ctl; 605 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 606 const char *region_name; 607 int ret; --- 69 unchanged lines hidden (view full) --- 677 struct wm_coeff_ctl *ctl = cs_ctl->priv; 678 679 cancel_work_sync(&ctl->work); 680 681 kfree(ctl->name); 682 kfree(ctl); 683} 684 |
1501static int cs_dsp_create_control(struct cs_dsp *dsp, 1502 const struct cs_dsp_alg_region *alg_region, 1503 unsigned int offset, unsigned int len, 1504 const char *subname, unsigned int subname_len, 1505 unsigned int flags, unsigned int type) 1506{ 1507 struct cs_dsp_coeff_ctl *ctl; 1508 int ret; 1509 1510 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1511 if (ctl->fw_name == dsp->fw_name && 1512 ctl->alg_region.alg == alg_region->alg && 1513 ctl->alg_region.type == alg_region->type) { 1514 if ((!subname && !ctl->subname) || 1515 (subname && !strncmp(ctl->subname, subname, ctl->subname_len))) { 1516 if (!ctl->enabled) 1517 ctl->enabled = 1; 1518 return 0; 1519 } 1520 } 1521 } 1522 1523 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); 1524 if (!ctl) 1525 return -ENOMEM; 1526 1527 ctl->fw_name = dsp->fw_name; 1528 ctl->alg_region = *alg_region; 1529 if (subname && dsp->fw_ver >= 2) { 1530 ctl->subname_len = subname_len; 1531 ctl->subname = kmemdup(subname, 1532 strlen(subname) + 1, GFP_KERNEL); 1533 if (!ctl->subname) { 1534 ret = -ENOMEM; 1535 goto err_ctl; 1536 } 1537 } 1538 ctl->enabled = 1; 1539 ctl->set = 0; 1540 ctl->dsp = dsp; 1541 1542 ctl->flags = flags; 1543 ctl->type = type; 1544 ctl->offset = offset; 1545 ctl->len = len; 1546 ctl->cache = kzalloc(ctl->len, GFP_KERNEL); 1547 if (!ctl->cache) { 1548 ret = -ENOMEM; 1549 goto err_ctl_subname; 1550 } 1551 1552 list_add(&ctl->list, &dsp->ctl_list); 1553 1554 if (dsp->client_ops->control_add) { 1555 ret = dsp->client_ops->control_add(ctl); 1556 if (ret) 1557 goto err_list_del; 1558 } 1559 1560 return 0; 1561 1562err_list_del: 1563 list_del(&ctl->list); 1564 kfree(ctl->cache); 1565err_ctl_subname: 1566 kfree(ctl->subname); 1567err_ctl: 1568 kfree(ctl); 1569 1570 return ret; 1571} 1572 1573struct cs_dsp_coeff_parsed_alg { 1574 int id; 1575 const u8 *name; 1576 int name_len; 1577 int ncoeff; 1578}; 1579 1580struct cs_dsp_coeff_parsed_coeff { 1581 int offset; 1582 int mem_type; 1583 const u8 *name; 1584 int name_len; 1585 unsigned int ctl_type; 1586 int flags; 1587 int len; 1588}; 1589 1590static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str) 1591{ 1592 int length; 1593 1594 switch (bytes) { 1595 case 1: 1596 length = **pos; 1597 break; 1598 case 2: 1599 length = le16_to_cpu(*((__le16 *)*pos)); 1600 break; 1601 default: 1602 return 0; 1603 } 1604 1605 if (str) 1606 *str = *pos + bytes; 1607 1608 *pos += ((length + bytes) + 3) & ~0x03; 1609 1610 return length; 1611} 1612 1613static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos) 1614{ 1615 int val = 0; 1616 1617 switch (bytes) { 1618 case 2: 1619 val = le16_to_cpu(*((__le16 *)*pos)); 1620 break; 1621 case 4: 1622 val = le32_to_cpu(*((__le32 *)*pos)); 1623 break; 1624 default: 1625 break; 1626 } 1627 1628 *pos += bytes; 1629 1630 return val; 1631} 1632 1633static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data, 1634 struct cs_dsp_coeff_parsed_alg *blk) 1635{ 1636 const struct wmfw_adsp_alg_data *raw; 1637 1638 switch (dsp->fw_ver) { 1639 case 0: 1640 case 1: 1641 raw = (const struct wmfw_adsp_alg_data *)*data; 1642 *data = raw->data; 1643 1644 blk->id = le32_to_cpu(raw->id); 1645 blk->name = raw->name; 1646 blk->name_len = strlen(raw->name); 1647 blk->ncoeff = le32_to_cpu(raw->ncoeff); 1648 break; 1649 default: 1650 blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data); 1651 blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data, 1652 &blk->name); 1653 cs_dsp_coeff_parse_string(sizeof(u16), data, NULL); 1654 blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data); 1655 break; 1656 } 1657 1658 cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); 1659 cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); 1660 cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); 1661} 1662 1663static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data, 1664 struct cs_dsp_coeff_parsed_coeff *blk) 1665{ 1666 const struct wmfw_adsp_coeff_data *raw; 1667 const u8 *tmp; 1668 int length; 1669 1670 switch (dsp->fw_ver) { 1671 case 0: 1672 case 1: 1673 raw = (const struct wmfw_adsp_coeff_data *)*data; 1674 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); 1675 1676 blk->offset = le16_to_cpu(raw->hdr.offset); 1677 blk->mem_type = le16_to_cpu(raw->hdr.type); 1678 blk->name = raw->name; 1679 blk->name_len = strlen(raw->name); 1680 blk->ctl_type = le16_to_cpu(raw->ctl_type); 1681 blk->flags = le16_to_cpu(raw->flags); 1682 blk->len = le32_to_cpu(raw->len); 1683 break; 1684 default: 1685 tmp = *data; 1686 blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp); 1687 blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp); 1688 length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp); 1689 blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, 1690 &blk->name); 1691 cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL); 1692 cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL); 1693 blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp); 1694 blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp); 1695 blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp); 1696 1697 *data = *data + sizeof(raw->hdr) + length; 1698 break; 1699 } 1700 1701 cs_dsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); 1702 cs_dsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); 1703 cs_dsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name); 1704 cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); 1705 cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); 1706 cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); 1707} 1708 1709static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp, 1710 const struct cs_dsp_coeff_parsed_coeff *coeff_blk, 1711 unsigned int f_required, 1712 unsigned int f_illegal) 1713{ 1714 if ((coeff_blk->flags & f_illegal) || 1715 ((coeff_blk->flags & f_required) != f_required)) { 1716 cs_dsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n", 1717 coeff_blk->flags, coeff_blk->ctl_type); 1718 return -EINVAL; 1719 } 1720 1721 return 0; 1722} 1723 1724static int cs_dsp_parse_coeff(struct cs_dsp *dsp, 1725 const struct wmfw_region *region) 1726{ 1727 struct cs_dsp_alg_region alg_region = {}; 1728 struct cs_dsp_coeff_parsed_alg alg_blk; 1729 struct cs_dsp_coeff_parsed_coeff coeff_blk; 1730 const u8 *data = region->data; 1731 int i, ret; 1732 1733 cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk); 1734 for (i = 0; i < alg_blk.ncoeff; i++) { 1735 cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk); 1736 1737 switch (coeff_blk.ctl_type) { 1738 case WMFW_CTL_TYPE_BYTES: 1739 break; 1740 case WMFW_CTL_TYPE_ACKED: 1741 if (coeff_blk.flags & WMFW_CTL_FLAG_SYS) 1742 continue; /* ignore */ 1743 1744 ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk, 1745 WMFW_CTL_FLAG_VOLATILE | 1746 WMFW_CTL_FLAG_WRITEABLE | 1747 WMFW_CTL_FLAG_READABLE, 1748 0); 1749 if (ret) 1750 return -EINVAL; 1751 break; 1752 case WMFW_CTL_TYPE_HOSTEVENT: 1753 ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk, 1754 WMFW_CTL_FLAG_SYS | 1755 WMFW_CTL_FLAG_VOLATILE | 1756 WMFW_CTL_FLAG_WRITEABLE | 1757 WMFW_CTL_FLAG_READABLE, 1758 0); 1759 if (ret) 1760 return -EINVAL; 1761 break; 1762 case WMFW_CTL_TYPE_HOST_BUFFER: 1763 ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk, 1764 WMFW_CTL_FLAG_SYS | 1765 WMFW_CTL_FLAG_VOLATILE | 1766 WMFW_CTL_FLAG_READABLE, 1767 0); 1768 if (ret) 1769 return -EINVAL; 1770 break; 1771 default: 1772 cs_dsp_err(dsp, "Unknown control type: %d\n", 1773 coeff_blk.ctl_type); 1774 return -EINVAL; 1775 } 1776 1777 alg_region.type = coeff_blk.mem_type; 1778 alg_region.alg = alg_blk.id; 1779 1780 ret = cs_dsp_create_control(dsp, &alg_region, 1781 coeff_blk.offset, 1782 coeff_blk.len, 1783 coeff_blk.name, 1784 coeff_blk.name_len, 1785 coeff_blk.flags, 1786 coeff_blk.ctl_type); 1787 if (ret < 0) 1788 cs_dsp_err(dsp, "Failed to create control: %.*s, %d\n", 1789 coeff_blk.name_len, coeff_blk.name, ret); 1790 } 1791 1792 return 0; 1793} 1794 1795static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp, 1796 const char * const file, 1797 unsigned int pos, 1798 const struct firmware *firmware) 1799{ 1800 const struct wmfw_adsp1_sizes *adsp1_sizes; 1801 1802 adsp1_sizes = (void *)&firmware->data[pos]; 1803 1804 cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file, 1805 le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm), 1806 le32_to_cpu(adsp1_sizes->zm)); 1807 1808 return pos + sizeof(*adsp1_sizes); 1809} 1810 1811static void wm_adsp_release_firmware_files(struct wm_adsp *dsp, 1812 const struct firmware *wmfw_firmware, 1813 char *wmfw_filename, 1814 const struct firmware *coeff_firmware, 1815 char *coeff_filename) 1816{ 1817 if (wmfw_firmware) 1818 release_firmware(wmfw_firmware); 1819 kfree(wmfw_filename); 1820 1821 if (coeff_firmware) 1822 release_firmware(coeff_firmware); 1823 kfree(coeff_filename); 1824} 1825 1826static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, 1827 const struct firmware **firmware, 1828 char **filename, 1829 char *suffix) 1830{ 1831 struct cs_dsp *cs_dsp = &dsp->cs_dsp; 1832 int ret = 0; 1833 1834 *filename = kasprintf(GFP_KERNEL, "%s-%s-%s.%s", dsp->part, dsp->fwf_name, 1835 wm_adsp_fw[dsp->fw].file, suffix); 1836 if (*filename == NULL) 1837 return -ENOMEM; 1838 1839 ret = request_firmware(firmware, *filename, cs_dsp->dev); 1840 if (ret != 0) { 1841 adsp_err(dsp, "Failed to request '%s'\n", *filename); 1842 kfree(*filename); 1843 *filename = NULL; 1844 } 1845 1846 return ret; 1847} 1848 1849static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, 1850 const struct firmware **wmfw_firmware, 1851 char **wmfw_filename, 1852 const struct firmware **coeff_firmware, 1853 char **coeff_filename) 1854{ 1855 int ret = 0; 1856 1857 ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, "wmfw"); 1858 if (ret != 0) 1859 return ret; 1860 1861 wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, "bin"); 1862 1863 return 0; 1864} 1865 1866static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp, 1867 const char * const file, 1868 unsigned int pos, 1869 const struct firmware *firmware) 1870{ 1871 const struct wmfw_adsp2_sizes *adsp2_sizes; 1872 1873 adsp2_sizes = (void *)&firmware->data[pos]; 1874 1875 cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file, 1876 le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym), 1877 le32_to_cpu(adsp2_sizes->pm), le32_to_cpu(adsp2_sizes->zm)); 1878 1879 return pos + sizeof(*adsp2_sizes); 1880} 1881 1882static bool cs_dsp_validate_version(struct cs_dsp *dsp, unsigned int version) 1883{ 1884 switch (version) { 1885 case 0: 1886 cs_dsp_warn(dsp, "Deprecated file format %d\n", version); 1887 return true; 1888 case 1: 1889 case 2: 1890 return true; 1891 default: 1892 return false; 1893 } 1894} 1895 1896static bool cs_dsp_halo_validate_version(struct cs_dsp *dsp, unsigned int version) 1897{ 1898 switch (version) { 1899 case 3: 1900 return true; 1901 default: 1902 return false; 1903 } 1904} 1905 1906static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, 1907 const char *file) 1908{ 1909 LIST_HEAD(buf_list); 1910 struct regmap *regmap = dsp->regmap; 1911 unsigned int pos = 0; 1912 const struct wmfw_header *header; 1913 const struct wmfw_adsp1_sizes *adsp1_sizes; 1914 const struct wmfw_footer *footer; 1915 const struct wmfw_region *region; 1916 const struct cs_dsp_region *mem; 1917 const char *region_name; 1918 char *text = NULL; 1919 struct cs_dsp_buf *buf; 1920 unsigned int reg; 1921 int regions = 0; 1922 int ret, offset, type; 1923 1924 ret = -EINVAL; 1925 1926 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1927 if (pos >= firmware->size) { 1928 cs_dsp_err(dsp, "%s: file too short, %zu bytes\n", 1929 file, firmware->size); 1930 goto out_fw; 1931 } 1932 1933 header = (void *)&firmware->data[0]; 1934 1935 if (memcmp(&header->magic[0], "WMFW", 4) != 0) { 1936 cs_dsp_err(dsp, "%s: invalid magic\n", file); 1937 goto out_fw; 1938 } 1939 1940 if (!dsp->ops->validate_version(dsp, header->ver)) { 1941 cs_dsp_err(dsp, "%s: unknown file format %d\n", 1942 file, header->ver); 1943 goto out_fw; 1944 } 1945 1946 cs_dsp_info(dsp, "Firmware version: %d\n", header->ver); 1947 dsp->fw_ver = header->ver; 1948 1949 if (header->core != dsp->type) { 1950 cs_dsp_err(dsp, "%s: invalid core %d != %d\n", 1951 file, header->core, dsp->type); 1952 goto out_fw; 1953 } 1954 1955 pos = sizeof(*header); 1956 pos = dsp->ops->parse_sizes(dsp, file, pos, firmware); 1957 1958 footer = (void *)&firmware->data[pos]; 1959 pos += sizeof(*footer); 1960 1961 if (le32_to_cpu(header->len) != pos) { 1962 cs_dsp_err(dsp, "%s: unexpected header length %d\n", 1963 file, le32_to_cpu(header->len)); 1964 goto out_fw; 1965 } 1966 1967 cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file, 1968 le64_to_cpu(footer->timestamp)); 1969 1970 while (pos < firmware->size && 1971 sizeof(*region) < firmware->size - pos) { 1972 region = (void *)&(firmware->data[pos]); 1973 region_name = "Unknown"; 1974 reg = 0; 1975 text = NULL; 1976 offset = le32_to_cpu(region->offset) & 0xffffff; 1977 type = be32_to_cpu(region->type) & 0xff; 1978 1979 switch (type) { 1980 case WMFW_NAME_TEXT: 1981 region_name = "Firmware name"; 1982 text = kzalloc(le32_to_cpu(region->len) + 1, 1983 GFP_KERNEL); 1984 break; 1985 case WMFW_ALGORITHM_DATA: 1986 region_name = "Algorithm"; 1987 ret = cs_dsp_parse_coeff(dsp, region); 1988 if (ret != 0) 1989 goto out_fw; 1990 break; 1991 case WMFW_INFO_TEXT: 1992 region_name = "Information"; 1993 text = kzalloc(le32_to_cpu(region->len) + 1, 1994 GFP_KERNEL); 1995 break; 1996 case WMFW_ABSOLUTE: 1997 region_name = "Absolute"; 1998 reg = offset; 1999 break; 2000 case WMFW_ADSP1_PM: 2001 case WMFW_ADSP1_DM: 2002 case WMFW_ADSP2_XM: 2003 case WMFW_ADSP2_YM: 2004 case WMFW_ADSP1_ZM: 2005 case WMFW_HALO_PM_PACKED: 2006 case WMFW_HALO_XM_PACKED: 2007 case WMFW_HALO_YM_PACKED: 2008 mem = cs_dsp_find_region(dsp, type); 2009 if (!mem) { 2010 cs_dsp_err(dsp, "No region of type: %x\n", type); 2011 ret = -EINVAL; 2012 goto out_fw; 2013 } 2014 2015 region_name = cs_dsp_mem_region_name(type); 2016 reg = dsp->ops->region_to_reg(mem, offset); 2017 break; 2018 default: 2019 cs_dsp_warn(dsp, 2020 "%s.%d: Unknown region type %x at %d(%x)\n", 2021 file, regions, type, pos, pos); 2022 break; 2023 } 2024 2025 cs_dsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 2026 regions, le32_to_cpu(region->len), offset, 2027 region_name); 2028 2029 if (le32_to_cpu(region->len) > 2030 firmware->size - pos - sizeof(*region)) { 2031 cs_dsp_err(dsp, 2032 "%s.%d: %s region len %d bytes exceeds file length %zu\n", 2033 file, regions, region_name, 2034 le32_to_cpu(region->len), firmware->size); 2035 ret = -EINVAL; 2036 goto out_fw; 2037 } 2038 2039 if (text) { 2040 memcpy(text, region->data, le32_to_cpu(region->len)); 2041 cs_dsp_info(dsp, "%s: %s\n", file, text); 2042 kfree(text); 2043 text = NULL; 2044 } 2045 2046 if (reg) { 2047 buf = cs_dsp_buf_alloc(region->data, 2048 le32_to_cpu(region->len), 2049 &buf_list); 2050 if (!buf) { 2051 cs_dsp_err(dsp, "Out of memory\n"); 2052 ret = -ENOMEM; 2053 goto out_fw; 2054 } 2055 2056 ret = regmap_raw_write_async(regmap, reg, buf->buf, 2057 le32_to_cpu(region->len)); 2058 if (ret != 0) { 2059 cs_dsp_err(dsp, 2060 "%s.%d: Failed to write %d bytes at %d in %s: %d\n", 2061 file, regions, 2062 le32_to_cpu(region->len), offset, 2063 region_name, ret); 2064 goto out_fw; 2065 } 2066 } 2067 2068 pos += le32_to_cpu(region->len) + sizeof(*region); 2069 regions++; 2070 } 2071 2072 ret = regmap_async_complete(regmap); 2073 if (ret != 0) { 2074 cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret); 2075 goto out_fw; 2076 } 2077 2078 if (pos > firmware->size) 2079 cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 2080 file, regions, pos - firmware->size); 2081 2082 cs_dsp_debugfs_save_wmfwname(dsp, file); 2083 2084out_fw: 2085 regmap_async_complete(regmap); 2086 cs_dsp_buf_free(&buf_list); 2087 kfree(text); 2088 2089 return ret; 2090} 2091 2092/* 2093 * Find cs_dsp_coeff_ctl with input name as its subname 2094 * If not found, return NULL 2095 */ 2096static struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, 2097 const char *name, int type, 2098 unsigned int alg) 2099{ 2100 struct cs_dsp_coeff_ctl *pos, *rslt = NULL; 2101 2102 list_for_each_entry(pos, &dsp->ctl_list, list) { 2103 if (!pos->subname) 2104 continue; 2105 if (strncmp(pos->subname, name, pos->subname_len) == 0 && 2106 pos->fw_name == dsp->fw_name && 2107 pos->alg_region.alg == alg && 2108 pos->alg_region.type == type) { 2109 rslt = pos; 2110 break; 2111 } 2112 } 2113 2114 return rslt; 2115} 2116 | |
2117int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, 2118 unsigned int alg, void *buf, size_t len) 2119{ 2120 struct cs_dsp_coeff_ctl *cs_ctl; 2121 struct wm_coeff_ctl *ctl; 2122 struct snd_kcontrol *kcontrol; 2123 char ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 2124 int ret; --- 45 unchanged lines hidden (view full) --- 2170 2171 if (len > cs_ctl->len) 2172 return -EINVAL; 2173 2174 return cs_dsp_coeff_read_ctrl(cs_ctl, buf, len); 2175} 2176EXPORT_SYMBOL_GPL(wm_adsp_read_ctl); 2177 | 685int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, 686 unsigned int alg, void *buf, size_t len) 687{ 688 struct cs_dsp_coeff_ctl *cs_ctl; 689 struct wm_coeff_ctl *ctl; 690 struct snd_kcontrol *kcontrol; 691 char ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 692 int ret; --- 45 unchanged lines hidden (view full) --- 738 739 if (len > cs_ctl->len) 740 return -EINVAL; 741 742 return cs_dsp_coeff_read_ctrl(cs_ctl, buf, len); 743} 744EXPORT_SYMBOL_GPL(wm_adsp_read_ctl); 745 |
2178static void cs_dsp_ctl_fixup_base(struct cs_dsp *dsp, 2179 const struct cs_dsp_alg_region *alg_region) | 746static void wm_adsp_release_firmware_files(struct wm_adsp *dsp, 747 const struct firmware *wmfw_firmware, 748 char *wmfw_filename, 749 const struct firmware *coeff_firmware, 750 char *coeff_filename) |
2180{ | 751{ |
2181 struct cs_dsp_coeff_ctl *ctl; | 752 if (wmfw_firmware) 753 release_firmware(wmfw_firmware); 754 kfree(wmfw_filename); |
2182 | 755 |
2183 list_for_each_entry(ctl, &dsp->ctl_list, list) { 2184 if (ctl->fw_name == dsp->fw_name && 2185 alg_region->alg == ctl->alg_region.alg && 2186 alg_region->type == ctl->alg_region.type) { 2187 ctl->alg_region.base = alg_region->base; 2188 } 2189 } | 756 if (coeff_firmware) 757 release_firmware(coeff_firmware); 758 kfree(coeff_filename); |
2190} 2191 | 759} 760 |
2192static void *cs_dsp_read_algs(struct cs_dsp *dsp, size_t n_algs, 2193 const struct cs_dsp_region *mem, 2194 unsigned int pos, unsigned int len) | 761static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, 762 const struct firmware **firmware, 763 char **filename, 764 char *suffix) |
2195{ | 765{ |
2196 void *alg; 2197 unsigned int reg; 2198 int ret; 2199 __be32 val; | 766 struct cs_dsp *cs_dsp = &dsp->cs_dsp; 767 int ret = 0; |
2200 | 768 |
2201 if (n_algs == 0) { 2202 cs_dsp_err(dsp, "No algorithms\n"); 2203 return ERR_PTR(-EINVAL); 2204 } | 769 *filename = kasprintf(GFP_KERNEL, "%s-%s-%s.%s", dsp->part, dsp->fwf_name, 770 wm_adsp_fw[dsp->fw].file, suffix); 771 if (*filename == NULL) 772 return -ENOMEM; |
2205 | 773 |
2206 if (n_algs > 1024) { 2207 cs_dsp_err(dsp, "Algorithm count %zx excessive\n", n_algs); 2208 return ERR_PTR(-EINVAL); 2209 } 2210 2211 /* Read the terminator first to validate the length */ 2212 reg = dsp->ops->region_to_reg(mem, pos + len); 2213 2214 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); | 774 ret = request_firmware(firmware, *filename, cs_dsp->dev); |
2215 if (ret != 0) { | 775 if (ret != 0) { |
2216 cs_dsp_err(dsp, "Failed to read algorithm list end: %d\n", 2217 ret); 2218 return ERR_PTR(ret); | 776 adsp_err(dsp, "Failed to request '%s'\n", *filename); 777 kfree(*filename); 778 *filename = NULL; |
2219 } 2220 | 779 } 780 |
2221 if (be32_to_cpu(val) != 0xbedead) 2222 cs_dsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n", 2223 reg, be32_to_cpu(val)); 2224 2225 /* Convert length from DSP words to bytes */ 2226 len *= sizeof(u32); 2227 2228 alg = kzalloc(len, GFP_KERNEL | GFP_DMA); 2229 if (!alg) 2230 return ERR_PTR(-ENOMEM); 2231 2232 reg = dsp->ops->region_to_reg(mem, pos); 2233 2234 ret = regmap_raw_read(dsp->regmap, reg, alg, len); 2235 if (ret != 0) { 2236 cs_dsp_err(dsp, "Failed to read algorithm list: %d\n", ret); 2237 kfree(alg); 2238 return ERR_PTR(ret); 2239 } 2240 2241 return alg; 2242} 2243 2244static struct cs_dsp_alg_region * 2245 cs_dsp_find_alg_region(struct cs_dsp *dsp, int type, unsigned int id) 2246{ 2247 struct cs_dsp_alg_region *alg_region; 2248 2249 list_for_each_entry(alg_region, &dsp->alg_regions, list) { 2250 if (id == alg_region->alg && type == alg_region->type) 2251 return alg_region; 2252 } 2253 2254 return NULL; 2255} 2256 2257static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp, 2258 int type, __be32 id, 2259 __be32 base) 2260{ 2261 struct cs_dsp_alg_region *alg_region; 2262 2263 alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL); 2264 if (!alg_region) 2265 return ERR_PTR(-ENOMEM); 2266 2267 alg_region->type = type; 2268 alg_region->alg = be32_to_cpu(id); 2269 alg_region->base = be32_to_cpu(base); 2270 2271 list_add_tail(&alg_region->list, &dsp->alg_regions); 2272 2273 if (dsp->fw_ver > 0) 2274 cs_dsp_ctl_fixup_base(dsp, alg_region); 2275 2276 return alg_region; 2277} 2278 2279static void cs_dsp_free_alg_regions(struct cs_dsp *dsp) 2280{ 2281 struct cs_dsp_alg_region *alg_region; 2282 2283 while (!list_empty(&dsp->alg_regions)) { 2284 alg_region = list_first_entry(&dsp->alg_regions, 2285 struct cs_dsp_alg_region, 2286 list); 2287 list_del(&alg_region->list); 2288 kfree(alg_region); 2289 } 2290} 2291 2292static void cs_dsp_parse_wmfw_id_header(struct cs_dsp *dsp, 2293 struct wmfw_id_hdr *fw, int nalgs) 2294{ 2295 dsp->fw_id = be32_to_cpu(fw->id); 2296 dsp->fw_id_version = be32_to_cpu(fw->ver); 2297 2298 cs_dsp_info(dsp, "Firmware: %x v%d.%d.%d, %d algorithms\n", 2299 dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16, 2300 (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, 2301 nalgs); 2302} 2303 2304static void cs_dsp_parse_wmfw_v3_id_header(struct cs_dsp *dsp, 2305 struct wmfw_v3_id_hdr *fw, int nalgs) 2306{ 2307 dsp->fw_id = be32_to_cpu(fw->id); 2308 dsp->fw_id_version = be32_to_cpu(fw->ver); 2309 dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id); 2310 2311 cs_dsp_info(dsp, "Firmware: %x vendor: 0x%x v%d.%d.%d, %d algorithms\n", 2312 dsp->fw_id, dsp->fw_vendor_id, 2313 (dsp->fw_id_version & 0xff0000) >> 16, 2314 (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, 2315 nalgs); 2316} 2317 2318static int cs_dsp_create_regions(struct cs_dsp *dsp, __be32 id, int nregions, 2319 const int *type, __be32 *base) 2320{ 2321 struct cs_dsp_alg_region *alg_region; 2322 int i; 2323 2324 for (i = 0; i < nregions; i++) { 2325 alg_region = cs_dsp_create_region(dsp, type[i], id, base[i]); 2326 if (IS_ERR(alg_region)) 2327 return PTR_ERR(alg_region); 2328 } 2329 2330 return 0; 2331} 2332 2333static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp) 2334{ 2335 struct wmfw_adsp1_id_hdr adsp1_id; 2336 struct wmfw_adsp1_alg_hdr *adsp1_alg; 2337 struct cs_dsp_alg_region *alg_region; 2338 const struct cs_dsp_region *mem; 2339 unsigned int pos, len; 2340 size_t n_algs; 2341 int i, ret; 2342 2343 mem = cs_dsp_find_region(dsp, WMFW_ADSP1_DM); 2344 if (WARN_ON(!mem)) 2345 return -EINVAL; 2346 2347 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id, 2348 sizeof(adsp1_id)); 2349 if (ret != 0) { 2350 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n", 2351 ret); 2352 return ret; 2353 } 2354 2355 n_algs = be32_to_cpu(adsp1_id.n_algs); 2356 2357 cs_dsp_parse_wmfw_id_header(dsp, &adsp1_id.fw, n_algs); 2358 2359 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM, 2360 adsp1_id.fw.id, adsp1_id.zm); 2361 if (IS_ERR(alg_region)) 2362 return PTR_ERR(alg_region); 2363 2364 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM, 2365 adsp1_id.fw.id, adsp1_id.dm); 2366 if (IS_ERR(alg_region)) 2367 return PTR_ERR(alg_region); 2368 2369 /* Calculate offset and length in DSP words */ 2370 pos = sizeof(adsp1_id) / sizeof(u32); 2371 len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32); 2372 2373 adsp1_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len); 2374 if (IS_ERR(adsp1_alg)) 2375 return PTR_ERR(adsp1_alg); 2376 2377 for (i = 0; i < n_algs; i++) { 2378 cs_dsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", 2379 i, be32_to_cpu(adsp1_alg[i].alg.id), 2380 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, 2381 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, 2382 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, 2383 be32_to_cpu(adsp1_alg[i].dm), 2384 be32_to_cpu(adsp1_alg[i].zm)); 2385 2386 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM, 2387 adsp1_alg[i].alg.id, 2388 adsp1_alg[i].dm); 2389 if (IS_ERR(alg_region)) { 2390 ret = PTR_ERR(alg_region); 2391 goto out; 2392 } 2393 if (dsp->fw_ver == 0) { 2394 if (i + 1 < n_algs) { 2395 len = be32_to_cpu(adsp1_alg[i + 1].dm); 2396 len -= be32_to_cpu(adsp1_alg[i].dm); 2397 len *= 4; 2398 cs_dsp_create_control(dsp, alg_region, 0, 2399 len, NULL, 0, 0, 2400 WMFW_CTL_TYPE_BYTES); 2401 } else { 2402 cs_dsp_warn(dsp, "Missing length info for region DM with ID %x\n", 2403 be32_to_cpu(adsp1_alg[i].alg.id)); 2404 } 2405 } 2406 2407 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM, 2408 adsp1_alg[i].alg.id, 2409 adsp1_alg[i].zm); 2410 if (IS_ERR(alg_region)) { 2411 ret = PTR_ERR(alg_region); 2412 goto out; 2413 } 2414 if (dsp->fw_ver == 0) { 2415 if (i + 1 < n_algs) { 2416 len = be32_to_cpu(adsp1_alg[i + 1].zm); 2417 len -= be32_to_cpu(adsp1_alg[i].zm); 2418 len *= 4; 2419 cs_dsp_create_control(dsp, alg_region, 0, 2420 len, NULL, 0, 0, 2421 WMFW_CTL_TYPE_BYTES); 2422 } else { 2423 cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 2424 be32_to_cpu(adsp1_alg[i].alg.id)); 2425 } 2426 } 2427 } 2428 2429out: 2430 kfree(adsp1_alg); | |
2431 return ret; 2432} 2433 | 781 return ret; 782} 783 |
2434static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) | 784static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, 785 const struct firmware **wmfw_firmware, 786 char **wmfw_filename, 787 const struct firmware **coeff_firmware, 788 char **coeff_filename) |
2435{ | 789{ |
2436 struct wmfw_adsp2_id_hdr adsp2_id; 2437 struct wmfw_adsp2_alg_hdr *adsp2_alg; 2438 struct cs_dsp_alg_region *alg_region; 2439 const struct cs_dsp_region *mem; 2440 unsigned int pos, len; 2441 size_t n_algs; 2442 int i, ret; | 790 int ret = 0; |
2443 | 791 |
2444 mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM); 2445 if (WARN_ON(!mem)) 2446 return -EINVAL; 2447 2448 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id, 2449 sizeof(adsp2_id)); 2450 if (ret != 0) { 2451 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n", 2452 ret); 2453 return ret; 2454 } 2455 2456 n_algs = be32_to_cpu(adsp2_id.n_algs); 2457 2458 cs_dsp_parse_wmfw_id_header(dsp, &adsp2_id.fw, n_algs); 2459 2460 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM, 2461 adsp2_id.fw.id, adsp2_id.xm); 2462 if (IS_ERR(alg_region)) 2463 return PTR_ERR(alg_region); 2464 2465 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM, 2466 adsp2_id.fw.id, adsp2_id.ym); 2467 if (IS_ERR(alg_region)) 2468 return PTR_ERR(alg_region); 2469 2470 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM, 2471 adsp2_id.fw.id, adsp2_id.zm); 2472 if (IS_ERR(alg_region)) 2473 return PTR_ERR(alg_region); 2474 2475 /* Calculate offset and length in DSP words */ 2476 pos = sizeof(adsp2_id) / sizeof(u32); 2477 len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32); 2478 2479 adsp2_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len); 2480 if (IS_ERR(adsp2_alg)) 2481 return PTR_ERR(adsp2_alg); 2482 2483 for (i = 0; i < n_algs; i++) { 2484 cs_dsp_info(dsp, 2485 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", 2486 i, be32_to_cpu(adsp2_alg[i].alg.id), 2487 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, 2488 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, 2489 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, 2490 be32_to_cpu(adsp2_alg[i].xm), 2491 be32_to_cpu(adsp2_alg[i].ym), 2492 be32_to_cpu(adsp2_alg[i].zm)); 2493 2494 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM, 2495 adsp2_alg[i].alg.id, 2496 adsp2_alg[i].xm); 2497 if (IS_ERR(alg_region)) { 2498 ret = PTR_ERR(alg_region); 2499 goto out; 2500 } 2501 if (dsp->fw_ver == 0) { 2502 if (i + 1 < n_algs) { 2503 len = be32_to_cpu(adsp2_alg[i + 1].xm); 2504 len -= be32_to_cpu(adsp2_alg[i].xm); 2505 len *= 4; 2506 cs_dsp_create_control(dsp, alg_region, 0, 2507 len, NULL, 0, 0, 2508 WMFW_CTL_TYPE_BYTES); 2509 } else { 2510 cs_dsp_warn(dsp, "Missing length info for region XM with ID %x\n", 2511 be32_to_cpu(adsp2_alg[i].alg.id)); 2512 } 2513 } 2514 2515 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM, 2516 adsp2_alg[i].alg.id, 2517 adsp2_alg[i].ym); 2518 if (IS_ERR(alg_region)) { 2519 ret = PTR_ERR(alg_region); 2520 goto out; 2521 } 2522 if (dsp->fw_ver == 0) { 2523 if (i + 1 < n_algs) { 2524 len = be32_to_cpu(adsp2_alg[i + 1].ym); 2525 len -= be32_to_cpu(adsp2_alg[i].ym); 2526 len *= 4; 2527 cs_dsp_create_control(dsp, alg_region, 0, 2528 len, NULL, 0, 0, 2529 WMFW_CTL_TYPE_BYTES); 2530 } else { 2531 cs_dsp_warn(dsp, "Missing length info for region YM with ID %x\n", 2532 be32_to_cpu(adsp2_alg[i].alg.id)); 2533 } 2534 } 2535 2536 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM, 2537 adsp2_alg[i].alg.id, 2538 adsp2_alg[i].zm); 2539 if (IS_ERR(alg_region)) { 2540 ret = PTR_ERR(alg_region); 2541 goto out; 2542 } 2543 if (dsp->fw_ver == 0) { 2544 if (i + 1 < n_algs) { 2545 len = be32_to_cpu(adsp2_alg[i + 1].zm); 2546 len -= be32_to_cpu(adsp2_alg[i].zm); 2547 len *= 4; 2548 cs_dsp_create_control(dsp, alg_region, 0, 2549 len, NULL, 0, 0, 2550 WMFW_CTL_TYPE_BYTES); 2551 } else { 2552 cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 2553 be32_to_cpu(adsp2_alg[i].alg.id)); 2554 } 2555 } 2556 } 2557 2558out: 2559 kfree(adsp2_alg); 2560 return ret; 2561} 2562 2563static int cs_dsp_halo_create_regions(struct cs_dsp *dsp, __be32 id, 2564 __be32 xm_base, __be32 ym_base) 2565{ 2566 static const int types[] = { 2567 WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED, 2568 WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED 2569 }; 2570 __be32 bases[] = { xm_base, xm_base, ym_base, ym_base }; 2571 2572 return cs_dsp_create_regions(dsp, id, ARRAY_SIZE(types), types, bases); 2573} 2574 2575static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp) 2576{ 2577 struct wmfw_halo_id_hdr halo_id; 2578 struct wmfw_halo_alg_hdr *halo_alg; 2579 const struct cs_dsp_region *mem; 2580 unsigned int pos, len; 2581 size_t n_algs; 2582 int i, ret; 2583 2584 mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM); 2585 if (WARN_ON(!mem)) 2586 return -EINVAL; 2587 2588 ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id, 2589 sizeof(halo_id)); 2590 if (ret != 0) { 2591 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n", 2592 ret); 2593 return ret; 2594 } 2595 2596 n_algs = be32_to_cpu(halo_id.n_algs); 2597 2598 cs_dsp_parse_wmfw_v3_id_header(dsp, &halo_id.fw, n_algs); 2599 2600 ret = cs_dsp_halo_create_regions(dsp, halo_id.fw.id, 2601 halo_id.xm_base, halo_id.ym_base); 2602 if (ret) 2603 return ret; 2604 2605 /* Calculate offset and length in DSP words */ 2606 pos = sizeof(halo_id) / sizeof(u32); 2607 len = (sizeof(*halo_alg) * n_algs) / sizeof(u32); 2608 2609 halo_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len); 2610 if (IS_ERR(halo_alg)) 2611 return PTR_ERR(halo_alg); 2612 2613 for (i = 0; i < n_algs; i++) { 2614 cs_dsp_info(dsp, 2615 "%d: ID %x v%d.%d.%d XM@%x YM@%x\n", 2616 i, be32_to_cpu(halo_alg[i].alg.id), 2617 (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16, 2618 (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8, 2619 be32_to_cpu(halo_alg[i].alg.ver) & 0xff, 2620 be32_to_cpu(halo_alg[i].xm_base), 2621 be32_to_cpu(halo_alg[i].ym_base)); 2622 2623 ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id, 2624 halo_alg[i].xm_base, 2625 halo_alg[i].ym_base); 2626 if (ret) 2627 goto out; 2628 } 2629 2630out: 2631 kfree(halo_alg); 2632 return ret; 2633} 2634 2635static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware, 2636 const char *file) 2637{ 2638 LIST_HEAD(buf_list); 2639 struct regmap *regmap = dsp->regmap; 2640 struct wmfw_coeff_hdr *hdr; 2641 struct wmfw_coeff_item *blk; 2642 const struct cs_dsp_region *mem; 2643 struct cs_dsp_alg_region *alg_region; 2644 const char *region_name; 2645 int ret, pos, blocks, type, offset, reg; 2646 struct cs_dsp_buf *buf; 2647 2648 if (!firmware) 2649 return 0; 2650 2651 ret = -EINVAL; 2652 2653 if (sizeof(*hdr) >= firmware->size) { 2654 cs_dsp_err(dsp, "%s: coefficient file too short, %zu bytes\n", 2655 file, firmware->size); 2656 goto out_fw; 2657 } 2658 2659 hdr = (void *)&firmware->data[0]; 2660 if (memcmp(hdr->magic, "WMDR", 4) != 0) { 2661 cs_dsp_err(dsp, "%s: invalid coefficient magic\n", file); 2662 goto out_fw; 2663 } 2664 2665 switch (be32_to_cpu(hdr->rev) & 0xff) { 2666 case 1: 2667 break; 2668 default: 2669 cs_dsp_err(dsp, "%s: Unsupported coefficient file format %d\n", 2670 file, be32_to_cpu(hdr->rev) & 0xff); 2671 ret = -EINVAL; 2672 goto out_fw; 2673 } 2674 2675 cs_dsp_dbg(dsp, "%s: v%d.%d.%d\n", file, 2676 (le32_to_cpu(hdr->ver) >> 16) & 0xff, 2677 (le32_to_cpu(hdr->ver) >> 8) & 0xff, 2678 le32_to_cpu(hdr->ver) & 0xff); 2679 2680 pos = le32_to_cpu(hdr->len); 2681 2682 blocks = 0; 2683 while (pos < firmware->size && 2684 sizeof(*blk) < firmware->size - pos) { 2685 blk = (void *)(&firmware->data[pos]); 2686 2687 type = le16_to_cpu(blk->type); 2688 offset = le16_to_cpu(blk->offset); 2689 2690 cs_dsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", 2691 file, blocks, le32_to_cpu(blk->id), 2692 (le32_to_cpu(blk->ver) >> 16) & 0xff, 2693 (le32_to_cpu(blk->ver) >> 8) & 0xff, 2694 le32_to_cpu(blk->ver) & 0xff); 2695 cs_dsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", 2696 file, blocks, le32_to_cpu(blk->len), offset, type); 2697 2698 reg = 0; 2699 region_name = "Unknown"; 2700 switch (type) { 2701 case (WMFW_NAME_TEXT << 8): 2702 case (WMFW_INFO_TEXT << 8): 2703 case (WMFW_METADATA << 8): 2704 break; 2705 case (WMFW_ABSOLUTE << 8): 2706 /* 2707 * Old files may use this for global 2708 * coefficients. 2709 */ 2710 if (le32_to_cpu(blk->id) == dsp->fw_id && 2711 offset == 0) { 2712 region_name = "global coefficients"; 2713 mem = cs_dsp_find_region(dsp, type); 2714 if (!mem) { 2715 cs_dsp_err(dsp, "No ZM\n"); 2716 break; 2717 } 2718 reg = dsp->ops->region_to_reg(mem, 0); 2719 2720 } else { 2721 region_name = "register"; 2722 reg = offset; 2723 } 2724 break; 2725 2726 case WMFW_ADSP1_DM: 2727 case WMFW_ADSP1_ZM: 2728 case WMFW_ADSP2_XM: 2729 case WMFW_ADSP2_YM: 2730 case WMFW_HALO_XM_PACKED: 2731 case WMFW_HALO_YM_PACKED: 2732 case WMFW_HALO_PM_PACKED: 2733 cs_dsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", 2734 file, blocks, le32_to_cpu(blk->len), 2735 type, le32_to_cpu(blk->id)); 2736 2737 mem = cs_dsp_find_region(dsp, type); 2738 if (!mem) { 2739 cs_dsp_err(dsp, "No base for region %x\n", type); 2740 break; 2741 } 2742 2743 alg_region = cs_dsp_find_alg_region(dsp, type, 2744 le32_to_cpu(blk->id)); 2745 if (alg_region) { 2746 reg = alg_region->base; 2747 reg = dsp->ops->region_to_reg(mem, reg); 2748 reg += offset; 2749 } else { 2750 cs_dsp_err(dsp, "No %x for algorithm %x\n", 2751 type, le32_to_cpu(blk->id)); 2752 } 2753 break; 2754 2755 default: 2756 cs_dsp_err(dsp, "%s.%d: Unknown region type %x at %d\n", 2757 file, blocks, type, pos); 2758 break; 2759 } 2760 2761 if (reg) { 2762 if (le32_to_cpu(blk->len) > 2763 firmware->size - pos - sizeof(*blk)) { 2764 cs_dsp_err(dsp, 2765 "%s.%d: %s region len %d bytes exceeds file length %zu\n", 2766 file, blocks, region_name, 2767 le32_to_cpu(blk->len), 2768 firmware->size); 2769 ret = -EINVAL; 2770 goto out_fw; 2771 } 2772 2773 buf = cs_dsp_buf_alloc(blk->data, 2774 le32_to_cpu(blk->len), 2775 &buf_list); 2776 if (!buf) { 2777 cs_dsp_err(dsp, "Out of memory\n"); 2778 ret = -ENOMEM; 2779 goto out_fw; 2780 } 2781 2782 cs_dsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", 2783 file, blocks, le32_to_cpu(blk->len), 2784 reg); 2785 ret = regmap_raw_write_async(regmap, reg, buf->buf, 2786 le32_to_cpu(blk->len)); 2787 if (ret != 0) { 2788 cs_dsp_err(dsp, 2789 "%s.%d: Failed to write to %x in %s: %d\n", 2790 file, blocks, reg, region_name, ret); 2791 } 2792 } 2793 2794 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03; 2795 blocks++; 2796 } 2797 2798 ret = regmap_async_complete(regmap); | 792 ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, "wmfw"); |
2799 if (ret != 0) | 793 if (ret != 0) |
2800 cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret); 2801 2802 if (pos > firmware->size) 2803 cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 2804 file, blocks, pos - firmware->size); 2805 2806 cs_dsp_debugfs_save_binname(dsp, file); 2807 2808out_fw: 2809 regmap_async_complete(regmap); 2810 cs_dsp_buf_free(&buf_list); 2811 return ret; 2812} 2813 2814static int cs_dsp_create_name(struct cs_dsp *dsp) 2815{ 2816 if (!dsp->name) { 2817 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d", 2818 dsp->num); 2819 if (!dsp->name) 2820 return -ENOMEM; 2821 } 2822 2823 return 0; 2824} 2825 2826static int cs_dsp_common_init(struct cs_dsp *dsp) 2827{ 2828 int ret; 2829 2830 ret = cs_dsp_create_name(dsp); 2831 if (ret) | |
2832 return ret; 2833 | 794 return ret; 795 |
2834 INIT_LIST_HEAD(&dsp->alg_regions); 2835 INIT_LIST_HEAD(&dsp->ctl_list); | 796 wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, "bin"); |
2836 | 797 |
2837 mutex_init(&dsp->pwr_lock); 2838 | |
2839 return 0; 2840} 2841 2842static int wm_adsp_common_init(struct wm_adsp *dsp) 2843{ 2844 char *p; 2845 2846 INIT_LIST_HEAD(&dsp->compr_list); --- 7 unchanged lines hidden (view full) --- 2854 dsp->fwf_name = p; 2855 for (; *p != 0; ++p) 2856 *p = tolower(*p); 2857 } 2858 2859 return 0; 2860} 2861 | 798 return 0; 799} 800 801static int wm_adsp_common_init(struct wm_adsp *dsp) 802{ 803 char *p; 804 805 INIT_LIST_HEAD(&dsp->compr_list); --- 7 unchanged lines hidden (view full) --- 813 dsp->fwf_name = p; 814 for (; *p != 0; ++p) 815 *p = tolower(*p); 816 } 817 818 return 0; 819} 820 |
2862static int cs_dsp_adsp1_init(struct cs_dsp *dsp) 2863{ 2864 dsp->ops = &cs_dsp_adsp1_ops; 2865 2866 return cs_dsp_common_init(dsp); 2867} 2868 | |
2869int wm_adsp1_init(struct wm_adsp *dsp) 2870{ 2871 int ret; 2872 2873 dsp->cs_dsp.client_ops = &wm_adsp1_client_ops; 2874 2875 ret = cs_dsp_adsp1_init(&dsp->cs_dsp); 2876 if (ret) 2877 return ret; 2878 2879 return wm_adsp_common_init(dsp); 2880} 2881EXPORT_SYMBOL_GPL(wm_adsp1_init); 2882 | 821int wm_adsp1_init(struct wm_adsp *dsp) 822{ 823 int ret; 824 825 dsp->cs_dsp.client_ops = &wm_adsp1_client_ops; 826 827 ret = cs_dsp_adsp1_init(&dsp->cs_dsp); 828 if (ret) 829 return ret; 830 831 return wm_adsp_common_init(dsp); 832} 833EXPORT_SYMBOL_GPL(wm_adsp1_init); 834 |
2883static int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, 2884 const struct firmware *wmfw_firmware, char *wmfw_filename, 2885 const struct firmware *coeff_firmware, char *coeff_filename, 2886 const char *fw_name) 2887{ 2888 unsigned int val; 2889 int ret; 2890 2891 mutex_lock(&dsp->pwr_lock); 2892 2893 dsp->fw_name = fw_name; 2894 2895 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2896 ADSP1_SYS_ENA, ADSP1_SYS_ENA); 2897 2898 /* 2899 * For simplicity set the DSP clock rate to be the 2900 * SYSCLK rate rather than making it configurable. 2901 */ 2902 if (dsp->sysclk_reg) { 2903 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); 2904 if (ret != 0) { 2905 cs_dsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); 2906 goto err_mutex; 2907 } 2908 2909 val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift; 2910 2911 ret = regmap_update_bits(dsp->regmap, 2912 dsp->base + ADSP1_CONTROL_31, 2913 ADSP1_CLK_SEL_MASK, val); 2914 if (ret != 0) { 2915 cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret); 2916 goto err_mutex; 2917 } 2918 } 2919 2920 ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename); 2921 if (ret != 0) 2922 goto err_ena; 2923 2924 ret = cs_dsp_adsp1_setup_algs(dsp); 2925 if (ret != 0) 2926 goto err_ena; 2927 2928 ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename); 2929 if (ret != 0) 2930 goto err_ena; 2931 2932 /* Initialize caches for enabled and unset controls */ 2933 ret = cs_dsp_coeff_init_control_caches(dsp); 2934 if (ret != 0) 2935 goto err_ena; 2936 2937 /* Sync set controls */ 2938 ret = cs_dsp_coeff_sync_controls(dsp); 2939 if (ret != 0) 2940 goto err_ena; 2941 2942 dsp->booted = true; 2943 2944 /* Start the core running */ 2945 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2946 ADSP1_CORE_ENA | ADSP1_START, 2947 ADSP1_CORE_ENA | ADSP1_START); 2948 2949 dsp->running = true; 2950 2951 mutex_unlock(&dsp->pwr_lock); 2952 2953 return 0; 2954 2955err_ena: 2956 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2957 ADSP1_SYS_ENA, 0); 2958err_mutex: 2959 mutex_unlock(&dsp->pwr_lock); 2960 return ret; 2961} 2962 2963static void cs_dsp_adsp1_power_down(struct cs_dsp *dsp) 2964{ 2965 struct cs_dsp_coeff_ctl *ctl; 2966 2967 mutex_lock(&dsp->pwr_lock); 2968 2969 dsp->running = false; 2970 dsp->booted = false; 2971 2972 /* Halt the core */ 2973 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2974 ADSP1_CORE_ENA | ADSP1_START, 0); 2975 2976 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, 2977 ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); 2978 2979 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2980 ADSP1_SYS_ENA, 0); 2981 2982 list_for_each_entry(ctl, &dsp->ctl_list, list) 2983 ctl->enabled = 0; 2984 2985 cs_dsp_free_alg_regions(dsp); 2986 2987 mutex_unlock(&dsp->pwr_lock); 2988} 2989 | |
2990int wm_adsp1_event(struct snd_soc_dapm_widget *w, 2991 struct snd_kcontrol *kcontrol, 2992 int event) 2993{ 2994 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2995 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2996 struct wm_adsp *dsp = &dsps[w->shift]; 2997 int ret = 0; --- 27 unchanged lines hidden (view full) --- 3025 default: 3026 break; 3027 } 3028 3029 return ret; 3030} 3031EXPORT_SYMBOL_GPL(wm_adsp1_event); 3032 | 835int wm_adsp1_event(struct snd_soc_dapm_widget *w, 836 struct snd_kcontrol *kcontrol, 837 int event) 838{ 839 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 840 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 841 struct wm_adsp *dsp = &dsps[w->shift]; 842 int ret = 0; --- 27 unchanged lines hidden (view full) --- 870 default: 871 break; 872 } 873 874 return ret; 875} 876EXPORT_SYMBOL_GPL(wm_adsp1_event); 877 |
3033static int cs_dsp_adsp2v2_enable_core(struct cs_dsp *dsp) 3034{ 3035 unsigned int val; 3036 int ret, count; 3037 3038 /* Wait for the RAM to start, should be near instantaneous */ 3039 for (count = 0; count < 10; ++count) { 3040 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val); 3041 if (ret != 0) 3042 return ret; 3043 3044 if (val & ADSP2_RAM_RDY) 3045 break; 3046 3047 usleep_range(250, 500); 3048 } 3049 3050 if (!(val & ADSP2_RAM_RDY)) { 3051 cs_dsp_err(dsp, "Failed to start DSP RAM\n"); 3052 return -EBUSY; 3053 } 3054 3055 cs_dsp_dbg(dsp, "RAM ready after %d polls\n", count); 3056 3057 return 0; 3058} 3059 3060static int cs_dsp_adsp2_enable_core(struct cs_dsp *dsp) 3061{ 3062 int ret; 3063 3064 ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL, 3065 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 3066 if (ret != 0) 3067 return ret; 3068 3069 return cs_dsp_adsp2v2_enable_core(dsp); 3070} 3071 3072static int cs_dsp_adsp2_lock(struct cs_dsp *dsp, unsigned int lock_regions) 3073{ 3074 struct regmap *regmap = dsp->regmap; 3075 unsigned int code0, code1, lock_reg; 3076 3077 if (!(lock_regions & CS_ADSP2_REGION_ALL)) 3078 return 0; 3079 3080 lock_regions &= CS_ADSP2_REGION_ALL; 3081 lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0; 3082 3083 while (lock_regions) { 3084 code0 = code1 = 0; 3085 if (lock_regions & BIT(0)) { 3086 code0 = ADSP2_LOCK_CODE_0; 3087 code1 = ADSP2_LOCK_CODE_1; 3088 } 3089 if (lock_regions & BIT(1)) { 3090 code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT; 3091 code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT; 3092 } 3093 regmap_write(regmap, lock_reg, code0); 3094 regmap_write(regmap, lock_reg, code1); 3095 lock_regions >>= 2; 3096 lock_reg += 2; 3097 } 3098 3099 return 0; 3100} 3101 3102static int cs_dsp_adsp2_enable_memory(struct cs_dsp *dsp) 3103{ 3104 return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 3105 ADSP2_MEM_ENA, ADSP2_MEM_ENA); 3106} 3107 3108static void cs_dsp_adsp2_disable_memory(struct cs_dsp *dsp) 3109{ 3110 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 3111 ADSP2_MEM_ENA, 0); 3112} 3113 3114static void cs_dsp_adsp2_disable_core(struct cs_dsp *dsp) 3115{ 3116 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); 3117 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); 3118 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); 3119 3120 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 3121 ADSP2_SYS_ENA, 0); 3122} 3123 3124static void cs_dsp_adsp2v2_disable_core(struct cs_dsp *dsp) 3125{ 3126 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); 3127 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); 3128 regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0); 3129} 3130 3131static int cs_dsp_halo_configure_mpu(struct cs_dsp *dsp, unsigned int lock_regions) 3132{ 3133 struct reg_sequence config[] = { 3134 { dsp->base + HALO_MPU_LOCK_CONFIG, 0x5555 }, 3135 { dsp->base + HALO_MPU_LOCK_CONFIG, 0xAAAA }, 3136 { dsp->base + HALO_MPU_XMEM_ACCESS_0, 0xFFFFFFFF }, 3137 { dsp->base + HALO_MPU_YMEM_ACCESS_0, 0xFFFFFFFF }, 3138 { dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions }, 3139 { dsp->base + HALO_MPU_XREG_ACCESS_0, lock_regions }, 3140 { dsp->base + HALO_MPU_YREG_ACCESS_0, lock_regions }, 3141 { dsp->base + HALO_MPU_XMEM_ACCESS_1, 0xFFFFFFFF }, 3142 { dsp->base + HALO_MPU_YMEM_ACCESS_1, 0xFFFFFFFF }, 3143 { dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions }, 3144 { dsp->base + HALO_MPU_XREG_ACCESS_1, lock_regions }, 3145 { dsp->base + HALO_MPU_YREG_ACCESS_1, lock_regions }, 3146 { dsp->base + HALO_MPU_XMEM_ACCESS_2, 0xFFFFFFFF }, 3147 { dsp->base + HALO_MPU_YMEM_ACCESS_2, 0xFFFFFFFF }, 3148 { dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions }, 3149 { dsp->base + HALO_MPU_XREG_ACCESS_2, lock_regions }, 3150 { dsp->base + HALO_MPU_YREG_ACCESS_2, lock_regions }, 3151 { dsp->base + HALO_MPU_XMEM_ACCESS_3, 0xFFFFFFFF }, 3152 { dsp->base + HALO_MPU_YMEM_ACCESS_3, 0xFFFFFFFF }, 3153 { dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions }, 3154 { dsp->base + HALO_MPU_XREG_ACCESS_3, lock_regions }, 3155 { dsp->base + HALO_MPU_YREG_ACCESS_3, lock_regions }, 3156 { dsp->base + HALO_MPU_LOCK_CONFIG, 0 }, 3157 }; 3158 3159 return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config)); 3160} 3161 3162static int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq) 3163{ 3164 int ret; 3165 3166 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING, 3167 ADSP2_CLK_SEL_MASK, 3168 freq << ADSP2_CLK_SEL_SHIFT); 3169 if (ret) 3170 cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret); 3171 3172 return ret; 3173} 3174 | |
3175int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq) 3176{ 3177 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 3178 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 3179 struct wm_adsp *dsp = &dsps[w->shift]; 3180 3181 return cs_dsp_set_dspclk(&dsp->cs_dsp, freq); 3182} --- 37 unchanged lines hidden (view full) --- 3220 snd_soc_dapm_sync(dapm); 3221 3222 flush_work(&dsp->boot_work); 3223 3224 return 0; 3225} 3226EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); 3227 | 878int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq) 879{ 880 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 881 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 882 struct wm_adsp *dsp = &dsps[w->shift]; 883 884 return cs_dsp_set_dspclk(&dsp->cs_dsp, freq); 885} --- 37 unchanged lines hidden (view full) --- 923 snd_soc_dapm_sync(dapm); 924 925 flush_work(&dsp->boot_work); 926 927 return 0; 928} 929EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); 930 |
3228static void cs_dsp_stop_watchdog(struct cs_dsp *dsp) 3229{ 3230 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG, 3231 ADSP2_WDT_ENA_MASK, 0); 3232} 3233 3234static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp) 3235{ 3236 regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL, 3237 HALO_WDT_EN_MASK, 0); 3238} 3239 3240static int cs_dsp_power_up(struct cs_dsp *dsp, 3241 const struct firmware *wmfw_firmware, char *wmfw_filename, 3242 const struct firmware *coeff_firmware, char *coeff_filename, 3243 const char *fw_name) 3244{ 3245 int ret; 3246 3247 mutex_lock(&dsp->pwr_lock); 3248 3249 dsp->fw_name = fw_name; 3250 3251 if (dsp->ops->enable_memory) { 3252 ret = dsp->ops->enable_memory(dsp); 3253 if (ret != 0) 3254 goto err_mutex; 3255 } 3256 3257 if (dsp->ops->enable_core) { 3258 ret = dsp->ops->enable_core(dsp); 3259 if (ret != 0) 3260 goto err_mem; 3261 } 3262 3263 ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename); 3264 if (ret != 0) 3265 goto err_ena; 3266 3267 ret = dsp->ops->setup_algs(dsp); 3268 if (ret != 0) 3269 goto err_ena; 3270 3271 ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename); 3272 if (ret != 0) 3273 goto err_ena; 3274 3275 /* Initialize caches for enabled and unset controls */ 3276 ret = cs_dsp_coeff_init_control_caches(dsp); 3277 if (ret != 0) 3278 goto err_ena; 3279 3280 if (dsp->ops->disable_core) 3281 dsp->ops->disable_core(dsp); 3282 3283 dsp->booted = true; 3284 3285 mutex_unlock(&dsp->pwr_lock); 3286 3287 return 0; 3288err_ena: 3289 if (dsp->ops->disable_core) 3290 dsp->ops->disable_core(dsp); 3291err_mem: 3292 if (dsp->ops->disable_memory) 3293 dsp->ops->disable_memory(dsp); 3294err_mutex: 3295 mutex_unlock(&dsp->pwr_lock); 3296 3297 return ret; 3298} 3299 3300static void cs_dsp_power_down(struct cs_dsp *dsp) 3301{ 3302 struct cs_dsp_coeff_ctl *ctl; 3303 3304 mutex_lock(&dsp->pwr_lock); 3305 3306 cs_dsp_debugfs_clear(dsp); 3307 3308 dsp->fw_id = 0; 3309 dsp->fw_id_version = 0; 3310 3311 dsp->booted = false; 3312 3313 if (dsp->ops->disable_memory) 3314 dsp->ops->disable_memory(dsp); 3315 3316 list_for_each_entry(ctl, &dsp->ctl_list, list) 3317 ctl->enabled = 0; 3318 3319 cs_dsp_free_alg_regions(dsp); 3320 3321 mutex_unlock(&dsp->pwr_lock); 3322 3323 cs_dsp_dbg(dsp, "Shutdown complete\n"); 3324} 3325 | |
3326static void wm_adsp_boot_work(struct work_struct *work) 3327{ 3328 struct wm_adsp *dsp = container_of(work, 3329 struct wm_adsp, 3330 boot_work); 3331 int ret = 0; 3332 char *wmfw_filename = NULL; 3333 const struct firmware *wmfw_firmware = NULL; --- 33 unchanged lines hidden (view full) --- 3367 default: 3368 break; 3369 } 3370 3371 return 0; 3372} 3373EXPORT_SYMBOL_GPL(wm_adsp_early_event); 3374 | 931static void wm_adsp_boot_work(struct work_struct *work) 932{ 933 struct wm_adsp *dsp = container_of(work, 934 struct wm_adsp, 935 boot_work); 936 int ret = 0; 937 char *wmfw_filename = NULL; 938 const struct firmware *wmfw_firmware = NULL; --- 33 unchanged lines hidden (view full) --- 972 default: 973 break; 974 } 975 976 return 0; 977} 978EXPORT_SYMBOL_GPL(wm_adsp_early_event); 979 |
3375static int cs_dsp_adsp2_start_core(struct cs_dsp *dsp) 3376{ 3377 return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 3378 ADSP2_CORE_ENA | ADSP2_START, 3379 ADSP2_CORE_ENA | ADSP2_START); 3380} 3381 3382static void cs_dsp_adsp2_stop_core(struct cs_dsp *dsp) 3383{ 3384 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 3385 ADSP2_CORE_ENA | ADSP2_START, 0); 3386} 3387 | |
3388static int wm_adsp_event_post_run(struct cs_dsp *cs_dsp) 3389{ 3390 struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp); 3391 3392 if (wm_adsp_fw[dsp->fw].num_caps != 0) 3393 return wm_adsp_buffer_init(dsp); 3394 3395 return 0; --- 4 unchanged lines hidden (view full) --- 3400 struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp); 3401 3402 if (wm_adsp_fw[dsp->fw].num_caps != 0) 3403 wm_adsp_buffer_free(dsp); 3404 3405 dsp->fatal_error = false; 3406} 3407 | 980static int wm_adsp_event_post_run(struct cs_dsp *cs_dsp) 981{ 982 struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp); 983 984 if (wm_adsp_fw[dsp->fw].num_caps != 0) 985 return wm_adsp_buffer_init(dsp); 986 987 return 0; --- 4 unchanged lines hidden (view full) --- 992 struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp); 993 994 if (wm_adsp_fw[dsp->fw].num_caps != 0) 995 wm_adsp_buffer_free(dsp); 996 997 dsp->fatal_error = false; 998} 999 |
3408static int cs_dsp_run(struct cs_dsp *dsp) 3409{ 3410 int ret; 3411 3412 mutex_lock(&dsp->pwr_lock); 3413 3414 if (!dsp->booted) { 3415 ret = -EIO; 3416 goto err; 3417 } 3418 3419 if (dsp->ops->enable_core) { 3420 ret = dsp->ops->enable_core(dsp); 3421 if (ret != 0) 3422 goto err; 3423 } 3424 3425 /* Sync set controls */ 3426 ret = cs_dsp_coeff_sync_controls(dsp); 3427 if (ret != 0) 3428 goto err; 3429 3430 if (dsp->ops->lock_memory) { 3431 ret = dsp->ops->lock_memory(dsp, dsp->lock_regions); 3432 if (ret != 0) { 3433 cs_dsp_err(dsp, "Error configuring MPU: %d\n", ret); 3434 goto err; 3435 } 3436 } 3437 3438 if (dsp->ops->start_core) { 3439 ret = dsp->ops->start_core(dsp); 3440 if (ret != 0) 3441 goto err; 3442 } 3443 3444 dsp->running = true; 3445 3446 if (dsp->client_ops->post_run) { 3447 ret = dsp->client_ops->post_run(dsp); 3448 if (ret) 3449 goto err; 3450 } 3451 3452 mutex_unlock(&dsp->pwr_lock); 3453 3454 return 0; 3455 3456err: 3457 if (dsp->ops->stop_core) 3458 dsp->ops->stop_core(dsp); 3459 if (dsp->ops->disable_core) 3460 dsp->ops->disable_core(dsp); 3461 mutex_unlock(&dsp->pwr_lock); 3462 3463 return ret; 3464} 3465 3466static void cs_dsp_stop(struct cs_dsp *dsp) 3467{ 3468 /* Tell the firmware to cleanup */ 3469 cs_dsp_signal_event_controls(dsp, CS_DSP_FW_EVENT_SHUTDOWN); 3470 3471 if (dsp->ops->stop_watchdog) 3472 dsp->ops->stop_watchdog(dsp); 3473 3474 /* Log firmware state, it can be useful for analysis */ 3475 if (dsp->ops->show_fw_status) 3476 dsp->ops->show_fw_status(dsp); 3477 3478 mutex_lock(&dsp->pwr_lock); 3479 3480 dsp->running = false; 3481 3482 if (dsp->ops->stop_core) 3483 dsp->ops->stop_core(dsp); 3484 if (dsp->ops->disable_core) 3485 dsp->ops->disable_core(dsp); 3486 3487 if (dsp->client_ops->post_stop) 3488 dsp->client_ops->post_stop(dsp); 3489 3490 mutex_unlock(&dsp->pwr_lock); 3491 3492 cs_dsp_dbg(dsp, "Execution stopped\n"); 3493} 3494 | |
3495int wm_adsp_event(struct snd_soc_dapm_widget *w, 3496 struct snd_kcontrol *kcontrol, int event) 3497{ 3498 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 3499 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 3500 struct wm_adsp *dsp = &dsps[w->shift]; 3501 int ret = 0; 3502 --- 8 unchanged lines hidden (view full) --- 3511 default: 3512 break; 3513 } 3514 3515 return ret; 3516} 3517EXPORT_SYMBOL_GPL(wm_adsp_event); 3518 | 1000int wm_adsp_event(struct snd_soc_dapm_widget *w, 1001 struct snd_kcontrol *kcontrol, int event) 1002{ 1003 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1004 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 1005 struct wm_adsp *dsp = &dsps[w->shift]; 1006 int ret = 0; 1007 --- 8 unchanged lines hidden (view full) --- 1016 default: 1017 break; 1018 } 1019 1020 return ret; 1021} 1022EXPORT_SYMBOL_GPL(wm_adsp_event); 1023 |
3519static int cs_dsp_halo_start_core(struct cs_dsp *dsp) 3520{ 3521 return regmap_update_bits(dsp->regmap, 3522 dsp->base + HALO_CCM_CORE_CONTROL, 3523 HALO_CORE_RESET | HALO_CORE_EN, 3524 HALO_CORE_RESET | HALO_CORE_EN); 3525} 3526 3527static void cs_dsp_halo_stop_core(struct cs_dsp *dsp) 3528{ 3529 regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL, 3530 HALO_CORE_EN, 0); 3531 3532 /* reset halo core with CORE_SOFT_RESET */ 3533 regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET, 3534 HALO_CORE_SOFT_RESET_MASK, 1); 3535} 3536 | |
3537int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component) 3538{ 3539 char preload[32]; 3540 3541 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name); 3542 snd_soc_component_disable_pin(component, preload); 3543 3544 cs_dsp_init_debugfs(&dsp->cs_dsp, component->debugfs_root); --- 7 unchanged lines hidden (view full) --- 3552int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component) 3553{ 3554 cs_dsp_cleanup_debugfs(&dsp->cs_dsp); 3555 3556 return 0; 3557} 3558EXPORT_SYMBOL_GPL(wm_adsp2_component_remove); 3559 | 1024int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component) 1025{ 1026 char preload[32]; 1027 1028 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name); 1029 snd_soc_component_disable_pin(component, preload); 1030 1031 cs_dsp_init_debugfs(&dsp->cs_dsp, component->debugfs_root); --- 7 unchanged lines hidden (view full) --- 1039int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component) 1040{ 1041 cs_dsp_cleanup_debugfs(&dsp->cs_dsp); 1042 1043 return 0; 1044} 1045EXPORT_SYMBOL_GPL(wm_adsp2_component_remove); 1046 |
3560static int cs_dsp_adsp2_init(struct cs_dsp *dsp) 3561{ 3562 int ret; 3563 3564 switch (dsp->rev) { 3565 case 0: 3566 /* 3567 * Disable the DSP memory by default when in reset for a small 3568 * power saving. 3569 */ 3570 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 3571 ADSP2_MEM_ENA, 0); 3572 if (ret) { 3573 cs_dsp_err(dsp, 3574 "Failed to clear memory retention: %d\n", ret); 3575 return ret; 3576 } 3577 3578 dsp->ops = &cs_dsp_adsp2_ops[0]; 3579 break; 3580 case 1: 3581 dsp->ops = &cs_dsp_adsp2_ops[1]; 3582 break; 3583 default: 3584 dsp->ops = &cs_dsp_adsp2_ops[2]; 3585 break; 3586 } 3587 3588 return cs_dsp_common_init(dsp); 3589} 3590 | |
3591int wm_adsp2_init(struct wm_adsp *dsp) 3592{ 3593 int ret; 3594 3595 INIT_WORK(&dsp->boot_work, wm_adsp_boot_work); 3596 3597 dsp->sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr); 3598 dsp->cs_dsp.client_ops = &wm_adsp2_client_ops; 3599 3600 ret = cs_dsp_adsp2_init(&dsp->cs_dsp); 3601 if (ret) 3602 return ret; 3603 3604 return wm_adsp_common_init(dsp); 3605} 3606EXPORT_SYMBOL_GPL(wm_adsp2_init); 3607 | 1047int wm_adsp2_init(struct wm_adsp *dsp) 1048{ 1049 int ret; 1050 1051 INIT_WORK(&dsp->boot_work, wm_adsp_boot_work); 1052 1053 dsp->sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr); 1054 dsp->cs_dsp.client_ops = &wm_adsp2_client_ops; 1055 1056 ret = cs_dsp_adsp2_init(&dsp->cs_dsp); 1057 if (ret) 1058 return ret; 1059 1060 return wm_adsp_common_init(dsp); 1061} 1062EXPORT_SYMBOL_GPL(wm_adsp2_init); 1063 |
3608static int cs_dsp_halo_init(struct cs_dsp *dsp) 3609{ 3610 dsp->ops = &cs_dsp_halo_ops; 3611 3612 return cs_dsp_common_init(dsp); 3613} 3614 | |
3615int wm_halo_init(struct wm_adsp *dsp) 3616{ 3617 int ret; 3618 3619 INIT_WORK(&dsp->boot_work, wm_adsp_boot_work); 3620 3621 dsp->sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr); 3622 dsp->cs_dsp.client_ops = &wm_adsp2_client_ops; 3623 3624 ret = cs_dsp_halo_init(&dsp->cs_dsp); 3625 if (ret) 3626 return ret; 3627 3628 return wm_adsp_common_init(dsp); 3629} 3630EXPORT_SYMBOL_GPL(wm_halo_init); 3631 | 1064int wm_halo_init(struct wm_adsp *dsp) 1065{ 1066 int ret; 1067 1068 INIT_WORK(&dsp->boot_work, wm_adsp_boot_work); 1069 1070 dsp->sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr); 1071 dsp->cs_dsp.client_ops = &wm_adsp2_client_ops; 1072 1073 ret = cs_dsp_halo_init(&dsp->cs_dsp); 1074 if (ret) 1075 return ret; 1076 1077 return wm_adsp_common_init(dsp); 1078} 1079EXPORT_SYMBOL_GPL(wm_halo_init); 1080 |
3632static void cs_dsp_remove(struct cs_dsp *dsp) 3633{ 3634 struct cs_dsp_coeff_ctl *ctl; 3635 3636 while (!list_empty(&dsp->ctl_list)) { 3637 ctl = list_first_entry(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 3638 3639 if (dsp->client_ops->control_remove) 3640 dsp->client_ops->control_remove(ctl); 3641 3642 list_del(&ctl->list); 3643 cs_dsp_free_ctl_blk(ctl); 3644 } 3645} 3646 | |
3647void wm_adsp2_remove(struct wm_adsp *dsp) 3648{ 3649 cs_dsp_remove(&dsp->cs_dsp); 3650} 3651EXPORT_SYMBOL_GPL(wm_adsp2_remove); 3652 3653static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr) 3654{ --- 213 unchanged lines hidden (view full) --- 3868 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS; 3869 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS; 3870 } 3871 3872 return 0; 3873} 3874EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); 3875 | 1081void wm_adsp2_remove(struct wm_adsp *dsp) 1082{ 1083 cs_dsp_remove(&dsp->cs_dsp); 1084} 1085EXPORT_SYMBOL_GPL(wm_adsp2_remove); 1086 1087static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr) 1088{ --- 213 unchanged lines hidden (view full) --- 1302 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS; 1303 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS; 1304 } 1305 1306 return 0; 1307} 1308EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); 1309 |
3876static int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, 3877 unsigned int mem_addr, 3878 unsigned int num_words, __be32 *data) 3879{ 3880 struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type); 3881 unsigned int reg; 3882 int ret; 3883 3884 if (!mem) 3885 return -EINVAL; 3886 3887 reg = dsp->ops->region_to_reg(mem, mem_addr); 3888 3889 ret = regmap_raw_read(dsp->regmap, reg, data, 3890 sizeof(*data) * num_words); 3891 if (ret < 0) 3892 return ret; 3893 3894 return 0; 3895} 3896 3897static int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, 3898 unsigned int mem_addr, u32 *data) 3899{ 3900 __be32 raw; 3901 int ret; 3902 3903 ret = cs_dsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw); 3904 if (ret < 0) 3905 return ret; 3906 3907 *data = be32_to_cpu(raw) & 0x00ffffffu; 3908 3909 return 0; 3910} 3911 3912static int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, 3913 unsigned int mem_addr, u32 data) 3914{ 3915 struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type); 3916 __be32 val = cpu_to_be32(data & 0x00ffffffu); 3917 unsigned int reg; 3918 3919 if (!mem) 3920 return -EINVAL; 3921 3922 reg = dsp->ops->region_to_reg(mem, mem_addr); 3923 3924 return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); 3925} 3926 | |
3927static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, 3928 unsigned int field_offset, u32 *data) 3929{ 3930 return cs_dsp_read_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type, 3931 buf->host_buf_ptr + field_offset, data); 3932} 3933 3934static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, 3935 unsigned int field_offset, u32 data) 3936{ 3937 return cs_dsp_write_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type, 3938 buf->host_buf_ptr + field_offset, 3939 data); 3940} 3941 | 1310static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, 1311 unsigned int field_offset, u32 *data) 1312{ 1313 return cs_dsp_read_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type, 1314 buf->host_buf_ptr + field_offset, data); 1315} 1316 1317static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, 1318 unsigned int field_offset, u32 data) 1319{ 1320 return cs_dsp_write_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type, 1321 buf->host_buf_ptr + field_offset, 1322 data); 1323} 1324 |
3942static void cs_dsp_remove_padding(u32 *buf, int nwords) 3943{ 3944 const __be32 *pack_in = (__be32 *)buf; 3945 u8 *pack_out = (u8 *)buf; 3946 int i; 3947 3948 /* 3949 * DSP words from the register map have pad bytes and the data bytes 3950 * are in swapped order. This swaps back to the original little-endian 3951 * order and strips the pad bytes. 3952 */ 3953 for (i = 0; i < nwords; i++) { 3954 u32 word = be32_to_cpu(*pack_in++); 3955 *pack_out++ = (u8)word; 3956 *pack_out++ = (u8)(word >> 8); 3957 *pack_out++ = (u8)(word >> 16); 3958 } 3959} 3960 | |
3961static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) 3962{ 3963 const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; 3964 struct wm_adsp_buffer_region *region; 3965 u32 offset = 0; 3966 int i, ret; 3967 3968 buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions), --- 594 unchanged lines hidden (view full) --- 4563 dsp->fatal_error = true; 4564 4565 list_for_each_entry(compr, &dsp->compr_list, list) { 4566 if (compr->stream) 4567 snd_compr_fragment_elapsed(compr->stream); 4568 } 4569} 4570 | 1325static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) 1326{ 1327 const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; 1328 struct wm_adsp_buffer_region *region; 1329 u32 offset = 0; 1330 int i, ret; 1331 1332 buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions), --- 594 unchanged lines hidden (view full) --- 1927 dsp->fatal_error = true; 1928 1929 list_for_each_entry(compr, &dsp->compr_list, list) { 1930 if (compr->stream) 1931 snd_compr_fragment_elapsed(compr->stream); 1932 } 1933} 1934 |
4571static void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp) 4572{ 4573 unsigned int val; 4574 struct regmap *regmap = dsp->regmap; 4575 int ret = 0; 4576 4577 mutex_lock(&dsp->pwr_lock); 4578 4579 ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val); 4580 if (ret) { 4581 cs_dsp_err(dsp, 4582 "Failed to read Region Lock Ctrl register: %d\n", ret); 4583 goto error; 4584 } 4585 4586 if (val & ADSP2_WDT_TIMEOUT_STS_MASK) { 4587 cs_dsp_err(dsp, "watchdog timeout error\n"); 4588 dsp->ops->stop_watchdog(dsp); 4589 if (dsp->client_ops->watchdog_expired) 4590 dsp->client_ops->watchdog_expired(dsp); 4591 } 4592 4593 if (val & (ADSP2_ADDR_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) { 4594 if (val & ADSP2_ADDR_ERR_MASK) 4595 cs_dsp_err(dsp, "bus error: address error\n"); 4596 else 4597 cs_dsp_err(dsp, "bus error: region lock error\n"); 4598 4599 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val); 4600 if (ret) { 4601 cs_dsp_err(dsp, 4602 "Failed to read Bus Err Addr register: %d\n", 4603 ret); 4604 goto error; 4605 } 4606 4607 cs_dsp_err(dsp, "bus error address = 0x%x\n", 4608 val & ADSP2_BUS_ERR_ADDR_MASK); 4609 4610 ret = regmap_read(regmap, 4611 dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR, 4612 &val); 4613 if (ret) { 4614 cs_dsp_err(dsp, 4615 "Failed to read Pmem Xmem Err Addr register: %d\n", 4616 ret); 4617 goto error; 4618 } 4619 4620 cs_dsp_err(dsp, "xmem error address = 0x%x\n", 4621 val & ADSP2_XMEM_ERR_ADDR_MASK); 4622 cs_dsp_err(dsp, "pmem error address = 0x%x\n", 4623 (val & ADSP2_PMEM_ERR_ADDR_MASK) >> 4624 ADSP2_PMEM_ERR_ADDR_SHIFT); 4625 } 4626 4627 regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, 4628 ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT); 4629 4630error: 4631 mutex_unlock(&dsp->pwr_lock); 4632} 4633 | |
4634irqreturn_t wm_adsp2_bus_error(int irq, void *data) 4635{ 4636 struct wm_adsp *dsp = (struct wm_adsp *)data; 4637 4638 cs_dsp_adsp2_bus_error(&dsp->cs_dsp); 4639 4640 return IRQ_HANDLED; 4641} 4642EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); 4643 | 1935irqreturn_t wm_adsp2_bus_error(int irq, void *data) 1936{ 1937 struct wm_adsp *dsp = (struct wm_adsp *)data; 1938 1939 cs_dsp_adsp2_bus_error(&dsp->cs_dsp); 1940 1941 return IRQ_HANDLED; 1942} 1943EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); 1944 |
4644static void cs_dsp_halo_bus_error(struct cs_dsp *dsp) 4645{ 4646 struct regmap *regmap = dsp->regmap; 4647 unsigned int fault[6]; 4648 struct reg_sequence clear[] = { 4649 { dsp->base + HALO_MPU_XM_VIO_STATUS, 0x0 }, 4650 { dsp->base + HALO_MPU_YM_VIO_STATUS, 0x0 }, 4651 { dsp->base + HALO_MPU_PM_VIO_STATUS, 0x0 }, 4652 }; 4653 int ret; 4654 4655 mutex_lock(&dsp->pwr_lock); 4656 4657 ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1, 4658 fault); 4659 if (ret) { 4660 cs_dsp_warn(dsp, "Failed to read AHB DEBUG_1: %d\n", ret); 4661 goto exit_unlock; 4662 } 4663 4664 cs_dsp_warn(dsp, "AHB: STATUS: 0x%x ADDR: 0x%x\n", 4665 *fault & HALO_AHBM_FLAGS_ERR_MASK, 4666 (*fault & HALO_AHBM_CORE_ERR_ADDR_MASK) >> 4667 HALO_AHBM_CORE_ERR_ADDR_SHIFT); 4668 4669 ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0, 4670 fault); 4671 if (ret) { 4672 cs_dsp_warn(dsp, "Failed to read AHB DEBUG_0: %d\n", ret); 4673 goto exit_unlock; 4674 } 4675 4676 cs_dsp_warn(dsp, "AHB: SYS_ADDR: 0x%x\n", *fault); 4677 4678 ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR, 4679 fault, ARRAY_SIZE(fault)); 4680 if (ret) { 4681 cs_dsp_warn(dsp, "Failed to read MPU fault info: %d\n", ret); 4682 goto exit_unlock; 4683 } 4684 4685 cs_dsp_warn(dsp, "XM: STATUS:0x%x ADDR:0x%x\n", fault[1], fault[0]); 4686 cs_dsp_warn(dsp, "YM: STATUS:0x%x ADDR:0x%x\n", fault[3], fault[2]); 4687 cs_dsp_warn(dsp, "PM: STATUS:0x%x ADDR:0x%x\n", fault[5], fault[4]); 4688 4689 ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear)); 4690 if (ret) 4691 cs_dsp_warn(dsp, "Failed to clear MPU status: %d\n", ret); 4692 4693exit_unlock: 4694 mutex_unlock(&dsp->pwr_lock); 4695} 4696 | |
4697irqreturn_t wm_halo_bus_error(int irq, void *data) 4698{ 4699 struct wm_adsp *dsp = (struct wm_adsp *)data; 4700 4701 cs_dsp_halo_bus_error(&dsp->cs_dsp); 4702 4703 return IRQ_HANDLED; 4704} 4705EXPORT_SYMBOL_GPL(wm_halo_bus_error); 4706 | 1945irqreturn_t wm_halo_bus_error(int irq, void *data) 1946{ 1947 struct wm_adsp *dsp = (struct wm_adsp *)data; 1948 1949 cs_dsp_halo_bus_error(&dsp->cs_dsp); 1950 1951 return IRQ_HANDLED; 1952} 1953EXPORT_SYMBOL_GPL(wm_halo_bus_error); 1954 |
4707static void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp) 4708{ 4709 mutex_lock(&dsp->pwr_lock); 4710 4711 cs_dsp_warn(dsp, "WDT Expiry Fault\n"); 4712 4713 dsp->ops->stop_watchdog(dsp); 4714 if (dsp->client_ops->watchdog_expired) 4715 dsp->client_ops->watchdog_expired(dsp); 4716 4717 mutex_unlock(&dsp->pwr_lock); 4718} 4719 | |
4720irqreturn_t wm_halo_wdt_expire(int irq, void *data) 4721{ 4722 struct wm_adsp *dsp = data; 4723 4724 cs_dsp_halo_wdt_expire(&dsp->cs_dsp); 4725 4726 return IRQ_HANDLED; 4727} 4728EXPORT_SYMBOL_GPL(wm_halo_wdt_expire); 4729 | 1955irqreturn_t wm_halo_wdt_expire(int irq, void *data) 1956{ 1957 struct wm_adsp *dsp = data; 1958 1959 cs_dsp_halo_wdt_expire(&dsp->cs_dsp); 1960 1961 return IRQ_HANDLED; 1962} 1963EXPORT_SYMBOL_GPL(wm_halo_wdt_expire); 1964 |
4730static const struct cs_dsp_ops cs_dsp_adsp1_ops = { 4731 .validate_version = cs_dsp_validate_version, 4732 .parse_sizes = cs_dsp_adsp1_parse_sizes, 4733 .region_to_reg = cs_dsp_region_to_reg, 4734}; 4735 | |
4736static const struct cs_dsp_client_ops wm_adsp1_client_ops = { 4737 .control_add = wm_adsp_control_add, 4738 .control_remove = wm_adsp_control_remove, 4739}; 4740 | 1965static const struct cs_dsp_client_ops wm_adsp1_client_ops = { 1966 .control_add = wm_adsp_control_add, 1967 .control_remove = wm_adsp_control_remove, 1968}; 1969 |
4741static const struct cs_dsp_ops cs_dsp_adsp2_ops[] = { 4742 { 4743 .parse_sizes = cs_dsp_adsp2_parse_sizes, 4744 .validate_version = cs_dsp_validate_version, 4745 .setup_algs = cs_dsp_adsp2_setup_algs, 4746 .region_to_reg = cs_dsp_region_to_reg, 4747 4748 .show_fw_status = cs_dsp_adsp2_show_fw_status, 4749 4750 .enable_memory = cs_dsp_adsp2_enable_memory, 4751 .disable_memory = cs_dsp_adsp2_disable_memory, 4752 4753 .enable_core = cs_dsp_adsp2_enable_core, 4754 .disable_core = cs_dsp_adsp2_disable_core, 4755 4756 .start_core = cs_dsp_adsp2_start_core, 4757 .stop_core = cs_dsp_adsp2_stop_core, 4758 4759 }, 4760 { 4761 .parse_sizes = cs_dsp_adsp2_parse_sizes, 4762 .validate_version = cs_dsp_validate_version, 4763 .setup_algs = cs_dsp_adsp2_setup_algs, 4764 .region_to_reg = cs_dsp_region_to_reg, 4765 4766 .show_fw_status = cs_dsp_adsp2v2_show_fw_status, 4767 4768 .enable_memory = cs_dsp_adsp2_enable_memory, 4769 .disable_memory = cs_dsp_adsp2_disable_memory, 4770 .lock_memory = cs_dsp_adsp2_lock, 4771 4772 .enable_core = cs_dsp_adsp2v2_enable_core, 4773 .disable_core = cs_dsp_adsp2v2_disable_core, 4774 4775 .start_core = cs_dsp_adsp2_start_core, 4776 .stop_core = cs_dsp_adsp2_stop_core, 4777 }, 4778 { 4779 .parse_sizes = cs_dsp_adsp2_parse_sizes, 4780 .validate_version = cs_dsp_validate_version, 4781 .setup_algs = cs_dsp_adsp2_setup_algs, 4782 .region_to_reg = cs_dsp_region_to_reg, 4783 4784 .show_fw_status = cs_dsp_adsp2v2_show_fw_status, 4785 .stop_watchdog = cs_dsp_stop_watchdog, 4786 4787 .enable_memory = cs_dsp_adsp2_enable_memory, 4788 .disable_memory = cs_dsp_adsp2_disable_memory, 4789 .lock_memory = cs_dsp_adsp2_lock, 4790 4791 .enable_core = cs_dsp_adsp2v2_enable_core, 4792 .disable_core = cs_dsp_adsp2v2_disable_core, 4793 4794 .start_core = cs_dsp_adsp2_start_core, 4795 .stop_core = cs_dsp_adsp2_stop_core, 4796 }, 4797}; 4798 4799static const struct cs_dsp_ops cs_dsp_halo_ops = { 4800 .parse_sizes = cs_dsp_adsp2_parse_sizes, 4801 .validate_version = cs_dsp_halo_validate_version, 4802 .setup_algs = cs_dsp_halo_setup_algs, 4803 .region_to_reg = cs_dsp_halo_region_to_reg, 4804 4805 .show_fw_status = cs_dsp_halo_show_fw_status, 4806 .stop_watchdog = cs_dsp_halo_stop_watchdog, 4807 4808 .lock_memory = cs_dsp_halo_configure_mpu, 4809 4810 .start_core = cs_dsp_halo_start_core, 4811 .stop_core = cs_dsp_halo_stop_core, 4812}; 4813 | |
4814static const struct cs_dsp_client_ops wm_adsp2_client_ops = { 4815 .control_add = wm_adsp_control_add, 4816 .control_remove = wm_adsp_control_remove, 4817 .post_run = wm_adsp_event_post_run, 4818 .post_stop = wm_adsp_event_post_stop, 4819 .watchdog_expired = wm_adsp_fatal_error, 4820}; 4821 4822MODULE_LICENSE("GPL v2"); | 1970static const struct cs_dsp_client_ops wm_adsp2_client_ops = { 1971 .control_add = wm_adsp_control_add, 1972 .control_remove = wm_adsp_control_remove, 1973 .post_run = wm_adsp_event_post_run, 1974 .post_stop = wm_adsp_event_post_stop, 1975 .watchdog_expired = wm_adsp_fatal_error, 1976}; 1977 1978MODULE_LICENSE("GPL v2"); |