1 /* 2 * wm_adsp.c -- Wolfson ADSP support 3 * 4 * Copyright 2012 Wolfson Microelectronics plc 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/ctype.h> 14 #include <linux/module.h> 15 #include <linux/moduleparam.h> 16 #include <linux/init.h> 17 #include <linux/delay.h> 18 #include <linux/firmware.h> 19 #include <linux/list.h> 20 #include <linux/pm.h> 21 #include <linux/pm_runtime.h> 22 #include <linux/regmap.h> 23 #include <linux/regulator/consumer.h> 24 #include <linux/slab.h> 25 #include <linux/vmalloc.h> 26 #include <linux/workqueue.h> 27 #include <linux/debugfs.h> 28 #include <sound/core.h> 29 #include <sound/pcm.h> 30 #include <sound/pcm_params.h> 31 #include <sound/soc.h> 32 #include <sound/jack.h> 33 #include <sound/initval.h> 34 #include <sound/tlv.h> 35 36 #include "wm_adsp.h" 37 38 #define adsp_crit(_dsp, fmt, ...) \ 39 dev_crit(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 40 #define adsp_err(_dsp, fmt, ...) \ 41 dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 42 #define adsp_warn(_dsp, fmt, ...) \ 43 dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 44 #define adsp_info(_dsp, fmt, ...) \ 45 dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 46 #define adsp_dbg(_dsp, fmt, ...) \ 47 dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__) 48 49 #define ADSP1_CONTROL_1 0x00 50 #define ADSP1_CONTROL_2 0x02 51 #define ADSP1_CONTROL_3 0x03 52 #define ADSP1_CONTROL_4 0x04 53 #define ADSP1_CONTROL_5 0x06 54 #define ADSP1_CONTROL_6 0x07 55 #define ADSP1_CONTROL_7 0x08 56 #define ADSP1_CONTROL_8 0x09 57 #define ADSP1_CONTROL_9 0x0A 58 #define ADSP1_CONTROL_10 0x0B 59 #define ADSP1_CONTROL_11 0x0C 60 #define ADSP1_CONTROL_12 0x0D 61 #define ADSP1_CONTROL_13 0x0F 62 #define ADSP1_CONTROL_14 0x10 63 #define ADSP1_CONTROL_15 0x11 64 #define ADSP1_CONTROL_16 0x12 65 #define ADSP1_CONTROL_17 0x13 66 #define ADSP1_CONTROL_18 0x14 67 #define ADSP1_CONTROL_19 0x16 68 #define ADSP1_CONTROL_20 0x17 69 #define ADSP1_CONTROL_21 0x18 70 #define ADSP1_CONTROL_22 0x1A 71 #define ADSP1_CONTROL_23 0x1B 72 #define ADSP1_CONTROL_24 0x1C 73 #define ADSP1_CONTROL_25 0x1E 74 #define ADSP1_CONTROL_26 0x20 75 #define ADSP1_CONTROL_27 0x21 76 #define ADSP1_CONTROL_28 0x22 77 #define ADSP1_CONTROL_29 0x23 78 #define ADSP1_CONTROL_30 0x24 79 #define ADSP1_CONTROL_31 0x26 80 81 /* 82 * ADSP1 Control 19 83 */ 84 #define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 85 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 86 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 87 88 89 /* 90 * ADSP1 Control 30 91 */ 92 #define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */ 93 #define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */ 94 #define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */ 95 #define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */ 96 #define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 97 #define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 98 #define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 99 #define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 100 #define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 101 #define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 102 #define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 103 #define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 104 #define ADSP1_START 0x0001 /* DSP1_START */ 105 #define ADSP1_START_MASK 0x0001 /* DSP1_START */ 106 #define ADSP1_START_SHIFT 0 /* DSP1_START */ 107 #define ADSP1_START_WIDTH 1 /* DSP1_START */ 108 109 /* 110 * ADSP1 Control 31 111 */ 112 #define ADSP1_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 113 #define ADSP1_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 114 #define ADSP1_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 115 116 #define ADSP2_CONTROL 0x0 117 #define ADSP2_CLOCKING 0x1 118 #define ADSP2V2_CLOCKING 0x2 119 #define ADSP2_STATUS1 0x4 120 #define ADSP2_WDMA_CONFIG_1 0x30 121 #define ADSP2_WDMA_CONFIG_2 0x31 122 #define ADSP2V2_WDMA_CONFIG_2 0x32 123 #define ADSP2_RDMA_CONFIG_1 0x34 124 125 #define ADSP2_SCRATCH0 0x40 126 #define ADSP2_SCRATCH1 0x41 127 #define ADSP2_SCRATCH2 0x42 128 #define ADSP2_SCRATCH3 0x43 129 130 #define ADSP2V2_SCRATCH0_1 0x40 131 #define ADSP2V2_SCRATCH2_3 0x42 132 133 /* 134 * ADSP2 Control 135 */ 136 137 #define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */ 138 #define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */ 139 #define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */ 140 #define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */ 141 #define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 142 #define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 143 #define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 144 #define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 145 #define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 146 #define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 147 #define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 148 #define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 149 #define ADSP2_START 0x0001 /* DSP1_START */ 150 #define ADSP2_START_MASK 0x0001 /* DSP1_START */ 151 #define ADSP2_START_SHIFT 0 /* DSP1_START */ 152 #define ADSP2_START_WIDTH 1 /* DSP1_START */ 153 154 /* 155 * ADSP2 clocking 156 */ 157 #define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 158 #define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 159 #define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 160 161 /* 162 * ADSP2V2 clocking 163 */ 164 #define ADSP2V2_CLK_SEL_MASK 0x70000 /* CLK_SEL_ENA */ 165 #define ADSP2V2_CLK_SEL_SHIFT 16 /* CLK_SEL_ENA */ 166 #define ADSP2V2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 167 168 #define ADSP2V2_RATE_MASK 0x7800 /* DSP_RATE */ 169 #define ADSP2V2_RATE_SHIFT 11 /* DSP_RATE */ 170 #define ADSP2V2_RATE_WIDTH 4 /* DSP_RATE */ 171 172 /* 173 * ADSP2 Status 1 174 */ 175 #define ADSP2_RAM_RDY 0x0001 176 #define ADSP2_RAM_RDY_MASK 0x0001 177 #define ADSP2_RAM_RDY_SHIFT 0 178 #define ADSP2_RAM_RDY_WIDTH 1 179 180 /* 181 * ADSP2 Lock support 182 */ 183 #define ADSP2_LOCK_CODE_0 0x5555 184 #define ADSP2_LOCK_CODE_1 0xAAAA 185 186 #define ADSP2_WATCHDOG 0x0A 187 #define ADSP2_BUS_ERR_ADDR 0x52 188 #define ADSP2_REGION_LOCK_STATUS 0x64 189 #define ADSP2_LOCK_REGION_1_LOCK_REGION_0 0x66 190 #define ADSP2_LOCK_REGION_3_LOCK_REGION_2 0x68 191 #define ADSP2_LOCK_REGION_5_LOCK_REGION_4 0x6A 192 #define ADSP2_LOCK_REGION_7_LOCK_REGION_6 0x6C 193 #define ADSP2_LOCK_REGION_9_LOCK_REGION_8 0x6E 194 #define ADSP2_LOCK_REGION_CTRL 0x7A 195 #define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR 0x7C 196 197 #define ADSP2_REGION_LOCK_ERR_MASK 0x8000 198 #define ADSP2_SLAVE_ERR_MASK 0x4000 199 #define ADSP2_WDT_TIMEOUT_STS_MASK 0x2000 200 #define ADSP2_CTRL_ERR_PAUSE_ENA 0x0002 201 #define ADSP2_CTRL_ERR_EINT 0x0001 202 203 #define ADSP2_BUS_ERR_ADDR_MASK 0x00FFFFFF 204 #define ADSP2_XMEM_ERR_ADDR_MASK 0x0000FFFF 205 #define ADSP2_PMEM_ERR_ADDR_MASK 0x7FFF0000 206 #define ADSP2_PMEM_ERR_ADDR_SHIFT 16 207 #define ADSP2_WDT_ENA_MASK 0xFFFFFFFD 208 209 #define ADSP2_LOCK_REGION_SHIFT 16 210 211 #define ADSP_MAX_STD_CTRL_SIZE 512 212 213 #define WM_ADSP_ACKED_CTL_TIMEOUT_MS 100 214 #define WM_ADSP_ACKED_CTL_N_QUICKPOLLS 10 215 #define WM_ADSP_ACKED_CTL_MIN_VALUE 0 216 #define WM_ADSP_ACKED_CTL_MAX_VALUE 0xFFFFFF 217 218 /* 219 * Event control messages 220 */ 221 #define WM_ADSP_FW_EVENT_SHUTDOWN 0x000001 222 223 struct wm_adsp_buf { 224 struct list_head list; 225 void *buf; 226 }; 227 228 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len, 229 struct list_head *list) 230 { 231 struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL); 232 233 if (buf == NULL) 234 return NULL; 235 236 buf->buf = vmalloc(len); 237 if (!buf->buf) { 238 kfree(buf); 239 return NULL; 240 } 241 memcpy(buf->buf, src, len); 242 243 if (list) 244 list_add_tail(&buf->list, list); 245 246 return buf; 247 } 248 249 static void wm_adsp_buf_free(struct list_head *list) 250 { 251 while (!list_empty(list)) { 252 struct wm_adsp_buf *buf = list_first_entry(list, 253 struct wm_adsp_buf, 254 list); 255 list_del(&buf->list); 256 vfree(buf->buf); 257 kfree(buf); 258 } 259 } 260 261 #define WM_ADSP_FW_MBC_VSS 0 262 #define WM_ADSP_FW_HIFI 1 263 #define WM_ADSP_FW_TX 2 264 #define WM_ADSP_FW_TX_SPK 3 265 #define WM_ADSP_FW_RX 4 266 #define WM_ADSP_FW_RX_ANC 5 267 #define WM_ADSP_FW_CTRL 6 268 #define WM_ADSP_FW_ASR 7 269 #define WM_ADSP_FW_TRACE 8 270 #define WM_ADSP_FW_SPK_PROT 9 271 #define WM_ADSP_FW_MISC 10 272 273 #define WM_ADSP_NUM_FW 11 274 275 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { 276 [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", 277 [WM_ADSP_FW_HIFI] = "MasterHiFi", 278 [WM_ADSP_FW_TX] = "Tx", 279 [WM_ADSP_FW_TX_SPK] = "Tx Speaker", 280 [WM_ADSP_FW_RX] = "Rx", 281 [WM_ADSP_FW_RX_ANC] = "Rx ANC", 282 [WM_ADSP_FW_CTRL] = "Voice Ctrl", 283 [WM_ADSP_FW_ASR] = "ASR Assist", 284 [WM_ADSP_FW_TRACE] = "Dbg Trace", 285 [WM_ADSP_FW_SPK_PROT] = "Protection", 286 [WM_ADSP_FW_MISC] = "Misc", 287 }; 288 289 struct wm_adsp_system_config_xm_hdr { 290 __be32 sys_enable; 291 __be32 fw_id; 292 __be32 fw_rev; 293 __be32 boot_status; 294 __be32 watchdog; 295 __be32 dma_buffer_size; 296 __be32 rdma[6]; 297 __be32 wdma[8]; 298 __be32 build_job_name[3]; 299 __be32 build_job_number; 300 }; 301 302 struct wm_adsp_alg_xm_struct { 303 __be32 magic; 304 __be32 smoothing; 305 __be32 threshold; 306 __be32 host_buf_ptr; 307 __be32 start_seq; 308 __be32 high_water_mark; 309 __be32 low_water_mark; 310 __be64 smoothed_power; 311 }; 312 313 struct wm_adsp_buffer { 314 __be32 X_buf_base; /* XM base addr of first X area */ 315 __be32 X_buf_size; /* Size of 1st X area in words */ 316 __be32 X_buf_base2; /* XM base addr of 2nd X area */ 317 __be32 X_buf_brk; /* Total X size in words */ 318 __be32 Y_buf_base; /* YM base addr of Y area */ 319 __be32 wrap; /* Total size X and Y in words */ 320 __be32 high_water_mark; /* Point at which IRQ is asserted */ 321 __be32 irq_count; /* bits 1-31 count IRQ assertions */ 322 __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */ 323 __be32 next_write_index; /* word index of next write */ 324 __be32 next_read_index; /* word index of next read */ 325 __be32 error; /* error if any */ 326 __be32 oldest_block_index; /* word index of oldest surviving */ 327 __be32 requested_rewind; /* how many blocks rewind was done */ 328 __be32 reserved_space; /* internal */ 329 __be32 min_free; /* min free space since stream start */ 330 __be32 blocks_written[2]; /* total blocks written (64 bit) */ 331 __be32 words_written[2]; /* total words written (64 bit) */ 332 }; 333 334 struct wm_adsp_compr; 335 336 struct wm_adsp_compr_buf { 337 struct wm_adsp *dsp; 338 struct wm_adsp_compr *compr; 339 340 struct wm_adsp_buffer_region *regions; 341 u32 host_buf_ptr; 342 343 u32 error; 344 u32 irq_count; 345 int read_index; 346 int avail; 347 }; 348 349 struct wm_adsp_compr { 350 struct wm_adsp *dsp; 351 struct wm_adsp_compr_buf *buf; 352 353 struct snd_compr_stream *stream; 354 struct snd_compressed_buffer size; 355 356 u32 *raw_buf; 357 unsigned int copied_total; 358 359 unsigned int sample_rate; 360 }; 361 362 #define WM_ADSP_DATA_WORD_SIZE 3 363 364 #define WM_ADSP_MIN_FRAGMENTS 1 365 #define WM_ADSP_MAX_FRAGMENTS 256 366 #define WM_ADSP_MIN_FRAGMENT_SIZE (64 * WM_ADSP_DATA_WORD_SIZE) 367 #define WM_ADSP_MAX_FRAGMENT_SIZE (4096 * WM_ADSP_DATA_WORD_SIZE) 368 369 #define WM_ADSP_ALG_XM_STRUCT_MAGIC 0x49aec7 370 371 #define HOST_BUFFER_FIELD(field) \ 372 (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32)) 373 374 #define ALG_XM_FIELD(field) \ 375 (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32)) 376 377 static int wm_adsp_buffer_init(struct wm_adsp *dsp); 378 static int wm_adsp_buffer_free(struct wm_adsp *dsp); 379 380 struct wm_adsp_buffer_region { 381 unsigned int offset; 382 unsigned int cumulative_size; 383 unsigned int mem_type; 384 unsigned int base_addr; 385 }; 386 387 struct wm_adsp_buffer_region_def { 388 unsigned int mem_type; 389 unsigned int base_offset; 390 unsigned int size_offset; 391 }; 392 393 static const struct wm_adsp_buffer_region_def default_regions[] = { 394 { 395 .mem_type = WMFW_ADSP2_XM, 396 .base_offset = HOST_BUFFER_FIELD(X_buf_base), 397 .size_offset = HOST_BUFFER_FIELD(X_buf_size), 398 }, 399 { 400 .mem_type = WMFW_ADSP2_XM, 401 .base_offset = HOST_BUFFER_FIELD(X_buf_base2), 402 .size_offset = HOST_BUFFER_FIELD(X_buf_brk), 403 }, 404 { 405 .mem_type = WMFW_ADSP2_YM, 406 .base_offset = HOST_BUFFER_FIELD(Y_buf_base), 407 .size_offset = HOST_BUFFER_FIELD(wrap), 408 }, 409 }; 410 411 struct wm_adsp_fw_caps { 412 u32 id; 413 struct snd_codec_desc desc; 414 int num_regions; 415 const struct wm_adsp_buffer_region_def *region_defs; 416 }; 417 418 static const struct wm_adsp_fw_caps ctrl_caps[] = { 419 { 420 .id = SND_AUDIOCODEC_BESPOKE, 421 .desc = { 422 .max_ch = 8, 423 .sample_rates = { 16000 }, 424 .num_sample_rates = 1, 425 .formats = SNDRV_PCM_FMTBIT_S16_LE, 426 }, 427 .num_regions = ARRAY_SIZE(default_regions), 428 .region_defs = default_regions, 429 }, 430 }; 431 432 static const struct wm_adsp_fw_caps trace_caps[] = { 433 { 434 .id = SND_AUDIOCODEC_BESPOKE, 435 .desc = { 436 .max_ch = 8, 437 .sample_rates = { 438 4000, 8000, 11025, 12000, 16000, 22050, 439 24000, 32000, 44100, 48000, 64000, 88200, 440 96000, 176400, 192000 441 }, 442 .num_sample_rates = 15, 443 .formats = SNDRV_PCM_FMTBIT_S16_LE, 444 }, 445 .num_regions = ARRAY_SIZE(default_regions), 446 .region_defs = default_regions, 447 }, 448 }; 449 450 static const struct { 451 const char *file; 452 int compr_direction; 453 int num_caps; 454 const struct wm_adsp_fw_caps *caps; 455 bool voice_trigger; 456 } wm_adsp_fw[WM_ADSP_NUM_FW] = { 457 [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" }, 458 [WM_ADSP_FW_HIFI] = { .file = "hifi" }, 459 [WM_ADSP_FW_TX] = { .file = "tx" }, 460 [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" }, 461 [WM_ADSP_FW_RX] = { .file = "rx" }, 462 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, 463 [WM_ADSP_FW_CTRL] = { 464 .file = "ctrl", 465 .compr_direction = SND_COMPRESS_CAPTURE, 466 .num_caps = ARRAY_SIZE(ctrl_caps), 467 .caps = ctrl_caps, 468 .voice_trigger = true, 469 }, 470 [WM_ADSP_FW_ASR] = { .file = "asr" }, 471 [WM_ADSP_FW_TRACE] = { 472 .file = "trace", 473 .compr_direction = SND_COMPRESS_CAPTURE, 474 .num_caps = ARRAY_SIZE(trace_caps), 475 .caps = trace_caps, 476 }, 477 [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" }, 478 [WM_ADSP_FW_MISC] = { .file = "misc" }, 479 }; 480 481 struct wm_coeff_ctl_ops { 482 int (*xget)(struct snd_kcontrol *kcontrol, 483 struct snd_ctl_elem_value *ucontrol); 484 int (*xput)(struct snd_kcontrol *kcontrol, 485 struct snd_ctl_elem_value *ucontrol); 486 }; 487 488 struct wm_coeff_ctl { 489 const char *name; 490 const char *fw_name; 491 struct wm_adsp_alg_region alg_region; 492 struct wm_coeff_ctl_ops ops; 493 struct wm_adsp *dsp; 494 unsigned int enabled:1; 495 struct list_head list; 496 void *cache; 497 unsigned int offset; 498 size_t len; 499 unsigned int set:1; 500 struct soc_bytes_ext bytes_ext; 501 unsigned int flags; 502 unsigned int type; 503 }; 504 505 static const char *wm_adsp_mem_region_name(unsigned int type) 506 { 507 switch (type) { 508 case WMFW_ADSP1_PM: 509 return "PM"; 510 case WMFW_ADSP1_DM: 511 return "DM"; 512 case WMFW_ADSP2_XM: 513 return "XM"; 514 case WMFW_ADSP2_YM: 515 return "YM"; 516 case WMFW_ADSP1_ZM: 517 return "ZM"; 518 default: 519 return NULL; 520 } 521 } 522 523 #ifdef CONFIG_DEBUG_FS 524 static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) 525 { 526 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); 527 528 kfree(dsp->wmfw_file_name); 529 dsp->wmfw_file_name = tmp; 530 } 531 532 static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) 533 { 534 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); 535 536 kfree(dsp->bin_file_name); 537 dsp->bin_file_name = tmp; 538 } 539 540 static void wm_adsp_debugfs_clear(struct wm_adsp *dsp) 541 { 542 kfree(dsp->wmfw_file_name); 543 kfree(dsp->bin_file_name); 544 dsp->wmfw_file_name = NULL; 545 dsp->bin_file_name = NULL; 546 } 547 548 static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, 549 char __user *user_buf, 550 size_t count, loff_t *ppos) 551 { 552 struct wm_adsp *dsp = file->private_data; 553 ssize_t ret; 554 555 mutex_lock(&dsp->pwr_lock); 556 557 if (!dsp->wmfw_file_name || !dsp->booted) 558 ret = 0; 559 else 560 ret = simple_read_from_buffer(user_buf, count, ppos, 561 dsp->wmfw_file_name, 562 strlen(dsp->wmfw_file_name)); 563 564 mutex_unlock(&dsp->pwr_lock); 565 return ret; 566 } 567 568 static ssize_t wm_adsp_debugfs_bin_read(struct file *file, 569 char __user *user_buf, 570 size_t count, loff_t *ppos) 571 { 572 struct wm_adsp *dsp = file->private_data; 573 ssize_t ret; 574 575 mutex_lock(&dsp->pwr_lock); 576 577 if (!dsp->bin_file_name || !dsp->booted) 578 ret = 0; 579 else 580 ret = simple_read_from_buffer(user_buf, count, ppos, 581 dsp->bin_file_name, 582 strlen(dsp->bin_file_name)); 583 584 mutex_unlock(&dsp->pwr_lock); 585 return ret; 586 } 587 588 static const struct { 589 const char *name; 590 const struct file_operations fops; 591 } wm_adsp_debugfs_fops[] = { 592 { 593 .name = "wmfw_file_name", 594 .fops = { 595 .open = simple_open, 596 .read = wm_adsp_debugfs_wmfw_read, 597 }, 598 }, 599 { 600 .name = "bin_file_name", 601 .fops = { 602 .open = simple_open, 603 .read = wm_adsp_debugfs_bin_read, 604 }, 605 }, 606 }; 607 608 static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, 609 struct snd_soc_component *component) 610 { 611 struct dentry *root = NULL; 612 int i; 613 614 if (!component->debugfs_root) { 615 adsp_err(dsp, "No codec debugfs root\n"); 616 goto err; 617 } 618 619 root = debugfs_create_dir(dsp->name, component->debugfs_root); 620 621 if (!root) 622 goto err; 623 624 if (!debugfs_create_bool("booted", 0444, root, &dsp->booted)) 625 goto err; 626 627 if (!debugfs_create_bool("running", 0444, root, &dsp->running)) 628 goto err; 629 630 if (!debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id)) 631 goto err; 632 633 if (!debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version)) 634 goto err; 635 636 for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) { 637 if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name, 638 0444, root, dsp, 639 &wm_adsp_debugfs_fops[i].fops)) 640 goto err; 641 } 642 643 dsp->debugfs_root = root; 644 return; 645 646 err: 647 debugfs_remove_recursive(root); 648 adsp_err(dsp, "Failed to create debugfs\n"); 649 } 650 651 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) 652 { 653 wm_adsp_debugfs_clear(dsp); 654 debugfs_remove_recursive(dsp->debugfs_root); 655 } 656 #else 657 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp, 658 struct snd_soc_component *component) 659 { 660 } 661 662 static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) 663 { 664 } 665 666 static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, 667 const char *s) 668 { 669 } 670 671 static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, 672 const char *s) 673 { 674 } 675 676 static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp) 677 { 678 } 679 #endif 680 681 int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 682 struct snd_ctl_elem_value *ucontrol) 683 { 684 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 685 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 686 struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); 687 688 ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw; 689 690 return 0; 691 } 692 EXPORT_SYMBOL_GPL(wm_adsp_fw_get); 693 694 int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, 695 struct snd_ctl_elem_value *ucontrol) 696 { 697 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 698 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 699 struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); 700 int ret = 0; 701 702 if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw) 703 return 0; 704 705 if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW) 706 return -EINVAL; 707 708 mutex_lock(&dsp[e->shift_l].pwr_lock); 709 710 if (dsp[e->shift_l].booted || dsp[e->shift_l].compr) 711 ret = -EBUSY; 712 else 713 dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0]; 714 715 mutex_unlock(&dsp[e->shift_l].pwr_lock); 716 717 return ret; 718 } 719 EXPORT_SYMBOL_GPL(wm_adsp_fw_put); 720 721 const struct soc_enum wm_adsp_fw_enum[] = { 722 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 723 SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 724 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 725 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 726 SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 727 SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 728 SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 729 }; 730 EXPORT_SYMBOL_GPL(wm_adsp_fw_enum); 731 732 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, 733 int type) 734 { 735 int i; 736 737 for (i = 0; i < dsp->num_mems; i++) 738 if (dsp->mem[i].type == type) 739 return &dsp->mem[i]; 740 741 return NULL; 742 } 743 744 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem, 745 unsigned int offset) 746 { 747 if (WARN_ON(!mem)) 748 return offset; 749 switch (mem->type) { 750 case WMFW_ADSP1_PM: 751 return mem->base + (offset * 3); 752 case WMFW_ADSP1_DM: 753 return mem->base + (offset * 2); 754 case WMFW_ADSP2_XM: 755 return mem->base + (offset * 2); 756 case WMFW_ADSP2_YM: 757 return mem->base + (offset * 2); 758 case WMFW_ADSP1_ZM: 759 return mem->base + (offset * 2); 760 default: 761 WARN(1, "Unknown memory region type"); 762 return offset; 763 } 764 } 765 766 static void wm_adsp2_show_fw_status(struct wm_adsp *dsp) 767 { 768 u16 scratch[4]; 769 int ret; 770 771 ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0, 772 scratch, sizeof(scratch)); 773 if (ret) { 774 adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret); 775 return; 776 } 777 778 adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 779 be16_to_cpu(scratch[0]), 780 be16_to_cpu(scratch[1]), 781 be16_to_cpu(scratch[2]), 782 be16_to_cpu(scratch[3])); 783 } 784 785 static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp) 786 { 787 u32 scratch[2]; 788 int ret; 789 790 ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1, 791 scratch, sizeof(scratch)); 792 793 if (ret) { 794 adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret); 795 return; 796 } 797 798 scratch[0] = be32_to_cpu(scratch[0]); 799 scratch[1] = be32_to_cpu(scratch[1]); 800 801 adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 802 scratch[0] & 0xFFFF, 803 scratch[0] >> 16, 804 scratch[1] & 0xFFFF, 805 scratch[1] >> 16); 806 } 807 808 static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext) 809 { 810 return container_of(ext, struct wm_coeff_ctl, bytes_ext); 811 } 812 813 static int wm_coeff_base_reg(struct wm_coeff_ctl *ctl, unsigned int *reg) 814 { 815 const struct wm_adsp_alg_region *alg_region = &ctl->alg_region; 816 struct wm_adsp *dsp = ctl->dsp; 817 const struct wm_adsp_region *mem; 818 819 mem = wm_adsp_find_region(dsp, alg_region->type); 820 if (!mem) { 821 adsp_err(dsp, "No base for region %x\n", 822 alg_region->type); 823 return -EINVAL; 824 } 825 826 *reg = wm_adsp_region_to_reg(mem, ctl->alg_region.base + ctl->offset); 827 828 return 0; 829 } 830 831 static int wm_coeff_info(struct snd_kcontrol *kctl, 832 struct snd_ctl_elem_info *uinfo) 833 { 834 struct soc_bytes_ext *bytes_ext = 835 (struct soc_bytes_ext *)kctl->private_value; 836 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 837 838 switch (ctl->type) { 839 case WMFW_CTL_TYPE_ACKED: 840 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 841 uinfo->value.integer.min = WM_ADSP_ACKED_CTL_MIN_VALUE; 842 uinfo->value.integer.max = WM_ADSP_ACKED_CTL_MAX_VALUE; 843 uinfo->value.integer.step = 1; 844 uinfo->count = 1; 845 break; 846 default: 847 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 848 uinfo->count = ctl->len; 849 break; 850 } 851 852 return 0; 853 } 854 855 static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl, 856 unsigned int event_id) 857 { 858 struct wm_adsp *dsp = ctl->dsp; 859 u32 val = cpu_to_be32(event_id); 860 unsigned int reg; 861 int i, ret; 862 863 ret = wm_coeff_base_reg(ctl, ®); 864 if (ret) 865 return ret; 866 867 adsp_dbg(dsp, "Sending 0x%x to acked control alg 0x%x %s:0x%x\n", 868 event_id, ctl->alg_region.alg, 869 wm_adsp_mem_region_name(ctl->alg_region.type), ctl->offset); 870 871 ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); 872 if (ret) { 873 adsp_err(dsp, "Failed to write %x: %d\n", reg, ret); 874 return ret; 875 } 876 877 /* 878 * Poll for ack, we initially poll at ~1ms intervals for firmwares 879 * that respond quickly, then go to ~10ms polls. A firmware is unlikely 880 * to ack instantly so we do the first 1ms delay before reading the 881 * control to avoid a pointless bus transaction 882 */ 883 for (i = 0; i < WM_ADSP_ACKED_CTL_TIMEOUT_MS;) { 884 switch (i) { 885 case 0 ... WM_ADSP_ACKED_CTL_N_QUICKPOLLS - 1: 886 usleep_range(1000, 2000); 887 i++; 888 break; 889 default: 890 usleep_range(10000, 20000); 891 i += 10; 892 break; 893 } 894 895 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 896 if (ret) { 897 adsp_err(dsp, "Failed to read %x: %d\n", reg, ret); 898 return ret; 899 } 900 901 if (val == 0) { 902 adsp_dbg(dsp, "Acked control ACKED at poll %u\n", i); 903 return 0; 904 } 905 } 906 907 adsp_warn(dsp, "Acked control @0x%x alg:0x%x %s:0x%x timed out\n", 908 reg, ctl->alg_region.alg, 909 wm_adsp_mem_region_name(ctl->alg_region.type), 910 ctl->offset); 911 912 return -ETIMEDOUT; 913 } 914 915 static int wm_coeff_write_control(struct wm_coeff_ctl *ctl, 916 const void *buf, size_t len) 917 { 918 struct wm_adsp *dsp = ctl->dsp; 919 void *scratch; 920 int ret; 921 unsigned int reg; 922 923 ret = wm_coeff_base_reg(ctl, ®); 924 if (ret) 925 return ret; 926 927 scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA); 928 if (!scratch) 929 return -ENOMEM; 930 931 ret = regmap_raw_write(dsp->regmap, reg, scratch, 932 len); 933 if (ret) { 934 adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n", 935 len, reg, ret); 936 kfree(scratch); 937 return ret; 938 } 939 adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg); 940 941 kfree(scratch); 942 943 return 0; 944 } 945 946 static int wm_coeff_put(struct snd_kcontrol *kctl, 947 struct snd_ctl_elem_value *ucontrol) 948 { 949 struct soc_bytes_ext *bytes_ext = 950 (struct soc_bytes_ext *)kctl->private_value; 951 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 952 char *p = ucontrol->value.bytes.data; 953 int ret = 0; 954 955 mutex_lock(&ctl->dsp->pwr_lock); 956 957 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 958 ret = -EPERM; 959 else 960 memcpy(ctl->cache, p, ctl->len); 961 962 ctl->set = 1; 963 if (ctl->enabled && ctl->dsp->running) 964 ret = wm_coeff_write_control(ctl, p, ctl->len); 965 966 mutex_unlock(&ctl->dsp->pwr_lock); 967 968 return ret; 969 } 970 971 static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, 972 const unsigned int __user *bytes, unsigned int size) 973 { 974 struct soc_bytes_ext *bytes_ext = 975 (struct soc_bytes_ext *)kctl->private_value; 976 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 977 int ret = 0; 978 979 mutex_lock(&ctl->dsp->pwr_lock); 980 981 if (copy_from_user(ctl->cache, bytes, size)) { 982 ret = -EFAULT; 983 } else { 984 ctl->set = 1; 985 if (ctl->enabled && ctl->dsp->running) 986 ret = wm_coeff_write_control(ctl, ctl->cache, size); 987 else if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 988 ret = -EPERM; 989 } 990 991 mutex_unlock(&ctl->dsp->pwr_lock); 992 993 return ret; 994 } 995 996 static int wm_coeff_put_acked(struct snd_kcontrol *kctl, 997 struct snd_ctl_elem_value *ucontrol) 998 { 999 struct soc_bytes_ext *bytes_ext = 1000 (struct soc_bytes_ext *)kctl->private_value; 1001 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1002 unsigned int val = ucontrol->value.integer.value[0]; 1003 int ret; 1004 1005 if (val == 0) 1006 return 0; /* 0 means no event */ 1007 1008 mutex_lock(&ctl->dsp->pwr_lock); 1009 1010 if (ctl->enabled && ctl->dsp->running) 1011 ret = wm_coeff_write_acked_control(ctl, val); 1012 else 1013 ret = -EPERM; 1014 1015 mutex_unlock(&ctl->dsp->pwr_lock); 1016 1017 return ret; 1018 } 1019 1020 static int wm_coeff_read_control(struct wm_coeff_ctl *ctl, 1021 void *buf, size_t len) 1022 { 1023 struct wm_adsp *dsp = ctl->dsp; 1024 void *scratch; 1025 int ret; 1026 unsigned int reg; 1027 1028 ret = wm_coeff_base_reg(ctl, ®); 1029 if (ret) 1030 return ret; 1031 1032 scratch = kmalloc(len, GFP_KERNEL | GFP_DMA); 1033 if (!scratch) 1034 return -ENOMEM; 1035 1036 ret = regmap_raw_read(dsp->regmap, reg, scratch, len); 1037 if (ret) { 1038 adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n", 1039 len, reg, ret); 1040 kfree(scratch); 1041 return ret; 1042 } 1043 adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg); 1044 1045 memcpy(buf, scratch, len); 1046 kfree(scratch); 1047 1048 return 0; 1049 } 1050 1051 static int wm_coeff_get(struct snd_kcontrol *kctl, 1052 struct snd_ctl_elem_value *ucontrol) 1053 { 1054 struct soc_bytes_ext *bytes_ext = 1055 (struct soc_bytes_ext *)kctl->private_value; 1056 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1057 char *p = ucontrol->value.bytes.data; 1058 int ret = 0; 1059 1060 mutex_lock(&ctl->dsp->pwr_lock); 1061 1062 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { 1063 if (ctl->enabled && ctl->dsp->running) 1064 ret = wm_coeff_read_control(ctl, p, ctl->len); 1065 else 1066 ret = -EPERM; 1067 } else { 1068 if (!ctl->flags && ctl->enabled && ctl->dsp->running) 1069 ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); 1070 1071 memcpy(p, ctl->cache, ctl->len); 1072 } 1073 1074 mutex_unlock(&ctl->dsp->pwr_lock); 1075 1076 return ret; 1077 } 1078 1079 static int wm_coeff_tlv_get(struct snd_kcontrol *kctl, 1080 unsigned int __user *bytes, unsigned int size) 1081 { 1082 struct soc_bytes_ext *bytes_ext = 1083 (struct soc_bytes_ext *)kctl->private_value; 1084 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1085 int ret = 0; 1086 1087 mutex_lock(&ctl->dsp->pwr_lock); 1088 1089 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { 1090 if (ctl->enabled && ctl->dsp->running) 1091 ret = wm_coeff_read_control(ctl, ctl->cache, size); 1092 else 1093 ret = -EPERM; 1094 } else { 1095 if (!ctl->flags && ctl->enabled && ctl->dsp->running) 1096 ret = wm_coeff_read_control(ctl, ctl->cache, size); 1097 } 1098 1099 if (!ret && copy_to_user(bytes, ctl->cache, size)) 1100 ret = -EFAULT; 1101 1102 mutex_unlock(&ctl->dsp->pwr_lock); 1103 1104 return ret; 1105 } 1106 1107 static int wm_coeff_get_acked(struct snd_kcontrol *kcontrol, 1108 struct snd_ctl_elem_value *ucontrol) 1109 { 1110 /* 1111 * Although it's not useful to read an acked control, we must satisfy 1112 * user-side assumptions that all controls are readable and that a 1113 * write of the same value should be filtered out (it's valid to send 1114 * the same event number again to the firmware). We therefore return 0, 1115 * meaning "no event" so valid event numbers will always be a change 1116 */ 1117 ucontrol->value.integer.value[0] = 0; 1118 1119 return 0; 1120 } 1121 1122 struct wmfw_ctl_work { 1123 struct wm_adsp *dsp; 1124 struct wm_coeff_ctl *ctl; 1125 struct work_struct work; 1126 }; 1127 1128 static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len) 1129 { 1130 unsigned int out, rd, wr, vol; 1131 1132 if (len > ADSP_MAX_STD_CTRL_SIZE) { 1133 rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ; 1134 wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE; 1135 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE; 1136 1137 out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; 1138 } else { 1139 rd = SNDRV_CTL_ELEM_ACCESS_READ; 1140 wr = SNDRV_CTL_ELEM_ACCESS_WRITE; 1141 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE; 1142 1143 out = 0; 1144 } 1145 1146 if (in) { 1147 if (in & WMFW_CTL_FLAG_READABLE) 1148 out |= rd; 1149 if (in & WMFW_CTL_FLAG_WRITEABLE) 1150 out |= wr; 1151 if (in & WMFW_CTL_FLAG_VOLATILE) 1152 out |= vol; 1153 } else { 1154 out |= rd | wr | vol; 1155 } 1156 1157 return out; 1158 } 1159 1160 static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl) 1161 { 1162 struct snd_kcontrol_new *kcontrol; 1163 int ret; 1164 1165 if (!ctl || !ctl->name) 1166 return -EINVAL; 1167 1168 kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); 1169 if (!kcontrol) 1170 return -ENOMEM; 1171 1172 kcontrol->name = ctl->name; 1173 kcontrol->info = wm_coeff_info; 1174 kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1175 kcontrol->tlv.c = snd_soc_bytes_tlv_callback; 1176 kcontrol->private_value = (unsigned long)&ctl->bytes_ext; 1177 kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len); 1178 1179 switch (ctl->type) { 1180 case WMFW_CTL_TYPE_ACKED: 1181 kcontrol->get = wm_coeff_get_acked; 1182 kcontrol->put = wm_coeff_put_acked; 1183 break; 1184 default: 1185 if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 1186 ctl->bytes_ext.max = ctl->len; 1187 ctl->bytes_ext.get = wm_coeff_tlv_get; 1188 ctl->bytes_ext.put = wm_coeff_tlv_put; 1189 } else { 1190 kcontrol->get = wm_coeff_get; 1191 kcontrol->put = wm_coeff_put; 1192 } 1193 break; 1194 } 1195 1196 ret = snd_soc_add_component_controls(dsp->component, kcontrol, 1); 1197 if (ret < 0) 1198 goto err_kcontrol; 1199 1200 kfree(kcontrol); 1201 1202 return 0; 1203 1204 err_kcontrol: 1205 kfree(kcontrol); 1206 return ret; 1207 } 1208 1209 static int wm_coeff_init_control_caches(struct wm_adsp *dsp) 1210 { 1211 struct wm_coeff_ctl *ctl; 1212 int ret; 1213 1214 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1215 if (!ctl->enabled || ctl->set) 1216 continue; 1217 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 1218 continue; 1219 1220 /* 1221 * For readable controls populate the cache from the DSP memory. 1222 * For non-readable controls the cache was zero-filled when 1223 * created so we don't need to do anything. 1224 */ 1225 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) { 1226 ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); 1227 if (ret < 0) 1228 return ret; 1229 } 1230 } 1231 1232 return 0; 1233 } 1234 1235 static int wm_coeff_sync_controls(struct wm_adsp *dsp) 1236 { 1237 struct wm_coeff_ctl *ctl; 1238 int ret; 1239 1240 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1241 if (!ctl->enabled) 1242 continue; 1243 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) { 1244 ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len); 1245 if (ret < 0) 1246 return ret; 1247 } 1248 } 1249 1250 return 0; 1251 } 1252 1253 static void wm_adsp_signal_event_controls(struct wm_adsp *dsp, 1254 unsigned int event) 1255 { 1256 struct wm_coeff_ctl *ctl; 1257 int ret; 1258 1259 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1260 if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT) 1261 continue; 1262 1263 if (!ctl->enabled) 1264 continue; 1265 1266 ret = wm_coeff_write_acked_control(ctl, event); 1267 if (ret) 1268 adsp_warn(dsp, 1269 "Failed to send 0x%x event to alg 0x%x (%d)\n", 1270 event, ctl->alg_region.alg, ret); 1271 } 1272 } 1273 1274 static void wm_adsp_ctl_work(struct work_struct *work) 1275 { 1276 struct wmfw_ctl_work *ctl_work = container_of(work, 1277 struct wmfw_ctl_work, 1278 work); 1279 1280 wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl); 1281 kfree(ctl_work); 1282 } 1283 1284 static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl) 1285 { 1286 kfree(ctl->cache); 1287 kfree(ctl->name); 1288 kfree(ctl); 1289 } 1290 1291 static int wm_adsp_create_control(struct wm_adsp *dsp, 1292 const struct wm_adsp_alg_region *alg_region, 1293 unsigned int offset, unsigned int len, 1294 const char *subname, unsigned int subname_len, 1295 unsigned int flags, unsigned int type) 1296 { 1297 struct wm_coeff_ctl *ctl; 1298 struct wmfw_ctl_work *ctl_work; 1299 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 1300 const char *region_name; 1301 int ret; 1302 1303 region_name = wm_adsp_mem_region_name(alg_region->type); 1304 if (!region_name) { 1305 adsp_err(dsp, "Unknown region type: %d\n", alg_region->type); 1306 return -EINVAL; 1307 } 1308 1309 switch (dsp->fw_ver) { 1310 case 0: 1311 case 1: 1312 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x", 1313 dsp->name, region_name, alg_region->alg); 1314 break; 1315 default: 1316 ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1317 "%s%c %.12s %x", dsp->name, *region_name, 1318 wm_adsp_fw_text[dsp->fw], alg_region->alg); 1319 1320 /* Truncate the subname from the start if it is too long */ 1321 if (subname) { 1322 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2; 1323 int skip = 0; 1324 1325 if (dsp->component->name_prefix) 1326 avail -= strlen(dsp->component->name_prefix) + 1; 1327 1328 if (subname_len > avail) 1329 skip = subname_len - avail; 1330 1331 snprintf(name + ret, 1332 SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s", 1333 subname_len - skip, subname + skip); 1334 } 1335 break; 1336 } 1337 1338 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1339 if (!strcmp(ctl->name, name)) { 1340 if (!ctl->enabled) 1341 ctl->enabled = 1; 1342 return 0; 1343 } 1344 } 1345 1346 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); 1347 if (!ctl) 1348 return -ENOMEM; 1349 ctl->fw_name = wm_adsp_fw_text[dsp->fw]; 1350 ctl->alg_region = *alg_region; 1351 ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); 1352 if (!ctl->name) { 1353 ret = -ENOMEM; 1354 goto err_ctl; 1355 } 1356 ctl->enabled = 1; 1357 ctl->set = 0; 1358 ctl->ops.xget = wm_coeff_get; 1359 ctl->ops.xput = wm_coeff_put; 1360 ctl->dsp = dsp; 1361 1362 ctl->flags = flags; 1363 ctl->type = type; 1364 ctl->offset = offset; 1365 ctl->len = len; 1366 ctl->cache = kzalloc(ctl->len, GFP_KERNEL); 1367 if (!ctl->cache) { 1368 ret = -ENOMEM; 1369 goto err_ctl_name; 1370 } 1371 1372 list_add(&ctl->list, &dsp->ctl_list); 1373 1374 if (flags & WMFW_CTL_FLAG_SYS) 1375 return 0; 1376 1377 ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); 1378 if (!ctl_work) { 1379 ret = -ENOMEM; 1380 goto err_ctl_cache; 1381 } 1382 1383 ctl_work->dsp = dsp; 1384 ctl_work->ctl = ctl; 1385 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); 1386 schedule_work(&ctl_work->work); 1387 1388 return 0; 1389 1390 err_ctl_cache: 1391 kfree(ctl->cache); 1392 err_ctl_name: 1393 kfree(ctl->name); 1394 err_ctl: 1395 kfree(ctl); 1396 1397 return ret; 1398 } 1399 1400 struct wm_coeff_parsed_alg { 1401 int id; 1402 const u8 *name; 1403 int name_len; 1404 int ncoeff; 1405 }; 1406 1407 struct wm_coeff_parsed_coeff { 1408 int offset; 1409 int mem_type; 1410 const u8 *name; 1411 int name_len; 1412 int ctl_type; 1413 int flags; 1414 int len; 1415 }; 1416 1417 static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str) 1418 { 1419 int length; 1420 1421 switch (bytes) { 1422 case 1: 1423 length = **pos; 1424 break; 1425 case 2: 1426 length = le16_to_cpu(*((__le16 *)*pos)); 1427 break; 1428 default: 1429 return 0; 1430 } 1431 1432 if (str) 1433 *str = *pos + bytes; 1434 1435 *pos += ((length + bytes) + 3) & ~0x03; 1436 1437 return length; 1438 } 1439 1440 static int wm_coeff_parse_int(int bytes, const u8 **pos) 1441 { 1442 int val = 0; 1443 1444 switch (bytes) { 1445 case 2: 1446 val = le16_to_cpu(*((__le16 *)*pos)); 1447 break; 1448 case 4: 1449 val = le32_to_cpu(*((__le32 *)*pos)); 1450 break; 1451 default: 1452 break; 1453 } 1454 1455 *pos += bytes; 1456 1457 return val; 1458 } 1459 1460 static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data, 1461 struct wm_coeff_parsed_alg *blk) 1462 { 1463 const struct wmfw_adsp_alg_data *raw; 1464 1465 switch (dsp->fw_ver) { 1466 case 0: 1467 case 1: 1468 raw = (const struct wmfw_adsp_alg_data *)*data; 1469 *data = raw->data; 1470 1471 blk->id = le32_to_cpu(raw->id); 1472 blk->name = raw->name; 1473 blk->name_len = strlen(raw->name); 1474 blk->ncoeff = le32_to_cpu(raw->ncoeff); 1475 break; 1476 default: 1477 blk->id = wm_coeff_parse_int(sizeof(raw->id), data); 1478 blk->name_len = wm_coeff_parse_string(sizeof(u8), data, 1479 &blk->name); 1480 wm_coeff_parse_string(sizeof(u16), data, NULL); 1481 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data); 1482 break; 1483 } 1484 1485 adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); 1486 adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); 1487 adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); 1488 } 1489 1490 static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, 1491 struct wm_coeff_parsed_coeff *blk) 1492 { 1493 const struct wmfw_adsp_coeff_data *raw; 1494 const u8 *tmp; 1495 int length; 1496 1497 switch (dsp->fw_ver) { 1498 case 0: 1499 case 1: 1500 raw = (const struct wmfw_adsp_coeff_data *)*data; 1501 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); 1502 1503 blk->offset = le16_to_cpu(raw->hdr.offset); 1504 blk->mem_type = le16_to_cpu(raw->hdr.type); 1505 blk->name = raw->name; 1506 blk->name_len = strlen(raw->name); 1507 blk->ctl_type = le16_to_cpu(raw->ctl_type); 1508 blk->flags = le16_to_cpu(raw->flags); 1509 blk->len = le32_to_cpu(raw->len); 1510 break; 1511 default: 1512 tmp = *data; 1513 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp); 1514 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp); 1515 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp); 1516 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp, 1517 &blk->name); 1518 wm_coeff_parse_string(sizeof(u8), &tmp, NULL); 1519 wm_coeff_parse_string(sizeof(u16), &tmp, NULL); 1520 blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp); 1521 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp); 1522 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp); 1523 1524 *data = *data + sizeof(raw->hdr) + length; 1525 break; 1526 } 1527 1528 adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); 1529 adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); 1530 adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name); 1531 adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); 1532 adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); 1533 adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); 1534 } 1535 1536 static int wm_adsp_check_coeff_flags(struct wm_adsp *dsp, 1537 const struct wm_coeff_parsed_coeff *coeff_blk, 1538 unsigned int f_required, 1539 unsigned int f_illegal) 1540 { 1541 if ((coeff_blk->flags & f_illegal) || 1542 ((coeff_blk->flags & f_required) != f_required)) { 1543 adsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n", 1544 coeff_blk->flags, coeff_blk->ctl_type); 1545 return -EINVAL; 1546 } 1547 1548 return 0; 1549 } 1550 1551 static int wm_adsp_parse_coeff(struct wm_adsp *dsp, 1552 const struct wmfw_region *region) 1553 { 1554 struct wm_adsp_alg_region alg_region = {}; 1555 struct wm_coeff_parsed_alg alg_blk; 1556 struct wm_coeff_parsed_coeff coeff_blk; 1557 const u8 *data = region->data; 1558 int i, ret; 1559 1560 wm_coeff_parse_alg(dsp, &data, &alg_blk); 1561 for (i = 0; i < alg_blk.ncoeff; i++) { 1562 wm_coeff_parse_coeff(dsp, &data, &coeff_blk); 1563 1564 switch (coeff_blk.ctl_type) { 1565 case SNDRV_CTL_ELEM_TYPE_BYTES: 1566 break; 1567 case WMFW_CTL_TYPE_ACKED: 1568 if (coeff_blk.flags & WMFW_CTL_FLAG_SYS) 1569 continue; /* ignore */ 1570 1571 ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk, 1572 WMFW_CTL_FLAG_VOLATILE | 1573 WMFW_CTL_FLAG_WRITEABLE | 1574 WMFW_CTL_FLAG_READABLE, 1575 0); 1576 if (ret) 1577 return -EINVAL; 1578 break; 1579 case WMFW_CTL_TYPE_HOSTEVENT: 1580 ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk, 1581 WMFW_CTL_FLAG_SYS | 1582 WMFW_CTL_FLAG_VOLATILE | 1583 WMFW_CTL_FLAG_WRITEABLE | 1584 WMFW_CTL_FLAG_READABLE, 1585 0); 1586 if (ret) 1587 return -EINVAL; 1588 break; 1589 case WMFW_CTL_TYPE_HOST_BUFFER: 1590 ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk, 1591 WMFW_CTL_FLAG_SYS | 1592 WMFW_CTL_FLAG_VOLATILE | 1593 WMFW_CTL_FLAG_READABLE, 1594 0); 1595 if (ret) 1596 return -EINVAL; 1597 break; 1598 default: 1599 adsp_err(dsp, "Unknown control type: %d\n", 1600 coeff_blk.ctl_type); 1601 return -EINVAL; 1602 } 1603 1604 alg_region.type = coeff_blk.mem_type; 1605 alg_region.alg = alg_blk.id; 1606 1607 ret = wm_adsp_create_control(dsp, &alg_region, 1608 coeff_blk.offset, 1609 coeff_blk.len, 1610 coeff_blk.name, 1611 coeff_blk.name_len, 1612 coeff_blk.flags, 1613 coeff_blk.ctl_type); 1614 if (ret < 0) 1615 adsp_err(dsp, "Failed to create control: %.*s, %d\n", 1616 coeff_blk.name_len, coeff_blk.name, ret); 1617 } 1618 1619 return 0; 1620 } 1621 1622 static int wm_adsp_load(struct wm_adsp *dsp) 1623 { 1624 LIST_HEAD(buf_list); 1625 const struct firmware *firmware; 1626 struct regmap *regmap = dsp->regmap; 1627 unsigned int pos = 0; 1628 const struct wmfw_header *header; 1629 const struct wmfw_adsp1_sizes *adsp1_sizes; 1630 const struct wmfw_adsp2_sizes *adsp2_sizes; 1631 const struct wmfw_footer *footer; 1632 const struct wmfw_region *region; 1633 const struct wm_adsp_region *mem; 1634 const char *region_name; 1635 char *file, *text = NULL; 1636 struct wm_adsp_buf *buf; 1637 unsigned int reg; 1638 int regions = 0; 1639 int ret, offset, type, sizes; 1640 1641 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 1642 if (file == NULL) 1643 return -ENOMEM; 1644 1645 snprintf(file, PAGE_SIZE, "%s-%s-%s.wmfw", dsp->part, dsp->fwf_name, 1646 wm_adsp_fw[dsp->fw].file); 1647 file[PAGE_SIZE - 1] = '\0'; 1648 1649 ret = request_firmware(&firmware, file, dsp->dev); 1650 if (ret != 0) { 1651 adsp_err(dsp, "Failed to request '%s'\n", file); 1652 goto out; 1653 } 1654 ret = -EINVAL; 1655 1656 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1657 if (pos >= firmware->size) { 1658 adsp_err(dsp, "%s: file too short, %zu bytes\n", 1659 file, firmware->size); 1660 goto out_fw; 1661 } 1662 1663 header = (void *)&firmware->data[0]; 1664 1665 if (memcmp(&header->magic[0], "WMFW", 4) != 0) { 1666 adsp_err(dsp, "%s: invalid magic\n", file); 1667 goto out_fw; 1668 } 1669 1670 switch (header->ver) { 1671 case 0: 1672 adsp_warn(dsp, "%s: Depreciated file format %d\n", 1673 file, header->ver); 1674 break; 1675 case 1: 1676 case 2: 1677 break; 1678 default: 1679 adsp_err(dsp, "%s: unknown file format %d\n", 1680 file, header->ver); 1681 goto out_fw; 1682 } 1683 1684 adsp_info(dsp, "Firmware version: %d\n", header->ver); 1685 dsp->fw_ver = header->ver; 1686 1687 if (header->core != dsp->type) { 1688 adsp_err(dsp, "%s: invalid core %d != %d\n", 1689 file, header->core, dsp->type); 1690 goto out_fw; 1691 } 1692 1693 switch (dsp->type) { 1694 case WMFW_ADSP1: 1695 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1696 adsp1_sizes = (void *)&(header[1]); 1697 footer = (void *)&(adsp1_sizes[1]); 1698 sizes = sizeof(*adsp1_sizes); 1699 1700 adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", 1701 file, le32_to_cpu(adsp1_sizes->dm), 1702 le32_to_cpu(adsp1_sizes->pm), 1703 le32_to_cpu(adsp1_sizes->zm)); 1704 break; 1705 1706 case WMFW_ADSP2: 1707 pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer); 1708 adsp2_sizes = (void *)&(header[1]); 1709 footer = (void *)&(adsp2_sizes[1]); 1710 sizes = sizeof(*adsp2_sizes); 1711 1712 adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", 1713 file, le32_to_cpu(adsp2_sizes->xm), 1714 le32_to_cpu(adsp2_sizes->ym), 1715 le32_to_cpu(adsp2_sizes->pm), 1716 le32_to_cpu(adsp2_sizes->zm)); 1717 break; 1718 1719 default: 1720 WARN(1, "Unknown DSP type"); 1721 goto out_fw; 1722 } 1723 1724 if (le32_to_cpu(header->len) != sizeof(*header) + 1725 sizes + sizeof(*footer)) { 1726 adsp_err(dsp, "%s: unexpected header length %d\n", 1727 file, le32_to_cpu(header->len)); 1728 goto out_fw; 1729 } 1730 1731 adsp_dbg(dsp, "%s: timestamp %llu\n", file, 1732 le64_to_cpu(footer->timestamp)); 1733 1734 while (pos < firmware->size && 1735 sizeof(*region) < firmware->size - pos) { 1736 region = (void *)&(firmware->data[pos]); 1737 region_name = "Unknown"; 1738 reg = 0; 1739 text = NULL; 1740 offset = le32_to_cpu(region->offset) & 0xffffff; 1741 type = be32_to_cpu(region->type) & 0xff; 1742 mem = wm_adsp_find_region(dsp, type); 1743 1744 switch (type) { 1745 case WMFW_NAME_TEXT: 1746 region_name = "Firmware name"; 1747 text = kzalloc(le32_to_cpu(region->len) + 1, 1748 GFP_KERNEL); 1749 break; 1750 case WMFW_ALGORITHM_DATA: 1751 region_name = "Algorithm"; 1752 ret = wm_adsp_parse_coeff(dsp, region); 1753 if (ret != 0) 1754 goto out_fw; 1755 break; 1756 case WMFW_INFO_TEXT: 1757 region_name = "Information"; 1758 text = kzalloc(le32_to_cpu(region->len) + 1, 1759 GFP_KERNEL); 1760 break; 1761 case WMFW_ABSOLUTE: 1762 region_name = "Absolute"; 1763 reg = offset; 1764 break; 1765 case WMFW_ADSP1_PM: 1766 case WMFW_ADSP1_DM: 1767 case WMFW_ADSP2_XM: 1768 case WMFW_ADSP2_YM: 1769 case WMFW_ADSP1_ZM: 1770 region_name = wm_adsp_mem_region_name(type); 1771 reg = wm_adsp_region_to_reg(mem, offset); 1772 break; 1773 default: 1774 adsp_warn(dsp, 1775 "%s.%d: Unknown region type %x at %d(%x)\n", 1776 file, regions, type, pos, pos); 1777 break; 1778 } 1779 1780 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 1781 regions, le32_to_cpu(region->len), offset, 1782 region_name); 1783 1784 if (le32_to_cpu(region->len) > 1785 firmware->size - pos - sizeof(*region)) { 1786 adsp_err(dsp, 1787 "%s.%d: %s region len %d bytes exceeds file length %zu\n", 1788 file, regions, region_name, 1789 le32_to_cpu(region->len), firmware->size); 1790 ret = -EINVAL; 1791 goto out_fw; 1792 } 1793 1794 if (text) { 1795 memcpy(text, region->data, le32_to_cpu(region->len)); 1796 adsp_info(dsp, "%s: %s\n", file, text); 1797 kfree(text); 1798 text = NULL; 1799 } 1800 1801 if (reg) { 1802 buf = wm_adsp_buf_alloc(region->data, 1803 le32_to_cpu(region->len), 1804 &buf_list); 1805 if (!buf) { 1806 adsp_err(dsp, "Out of memory\n"); 1807 ret = -ENOMEM; 1808 goto out_fw; 1809 } 1810 1811 ret = regmap_raw_write_async(regmap, reg, buf->buf, 1812 le32_to_cpu(region->len)); 1813 if (ret != 0) { 1814 adsp_err(dsp, 1815 "%s.%d: Failed to write %d bytes at %d in %s: %d\n", 1816 file, regions, 1817 le32_to_cpu(region->len), offset, 1818 region_name, ret); 1819 goto out_fw; 1820 } 1821 } 1822 1823 pos += le32_to_cpu(region->len) + sizeof(*region); 1824 regions++; 1825 } 1826 1827 ret = regmap_async_complete(regmap); 1828 if (ret != 0) { 1829 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 1830 goto out_fw; 1831 } 1832 1833 if (pos > firmware->size) 1834 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 1835 file, regions, pos - firmware->size); 1836 1837 wm_adsp_debugfs_save_wmfwname(dsp, file); 1838 1839 out_fw: 1840 regmap_async_complete(regmap); 1841 wm_adsp_buf_free(&buf_list); 1842 release_firmware(firmware); 1843 kfree(text); 1844 out: 1845 kfree(file); 1846 1847 return ret; 1848 } 1849 1850 static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp, 1851 const struct wm_adsp_alg_region *alg_region) 1852 { 1853 struct wm_coeff_ctl *ctl; 1854 1855 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1856 if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] && 1857 alg_region->alg == ctl->alg_region.alg && 1858 alg_region->type == ctl->alg_region.type) { 1859 ctl->alg_region.base = alg_region->base; 1860 } 1861 } 1862 } 1863 1864 static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, 1865 const struct wm_adsp_region *mem, 1866 unsigned int pos, unsigned int len) 1867 { 1868 void *alg; 1869 unsigned int reg; 1870 int ret; 1871 __be32 val; 1872 1873 if (n_algs == 0) { 1874 adsp_err(dsp, "No algorithms\n"); 1875 return ERR_PTR(-EINVAL); 1876 } 1877 1878 if (n_algs > 1024) { 1879 adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs); 1880 return ERR_PTR(-EINVAL); 1881 } 1882 1883 /* Read the terminator first to validate the length */ 1884 reg = wm_adsp_region_to_reg(mem, pos + len); 1885 1886 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 1887 if (ret != 0) { 1888 adsp_err(dsp, "Failed to read algorithm list end: %d\n", 1889 ret); 1890 return ERR_PTR(ret); 1891 } 1892 1893 if (be32_to_cpu(val) != 0xbedead) 1894 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n", 1895 reg, be32_to_cpu(val)); 1896 1897 /* Convert length from DSP words to bytes */ 1898 len *= sizeof(u32); 1899 1900 alg = kzalloc(len, GFP_KERNEL | GFP_DMA); 1901 if (!alg) 1902 return ERR_PTR(-ENOMEM); 1903 1904 reg = wm_adsp_region_to_reg(mem, pos); 1905 1906 ret = regmap_raw_read(dsp->regmap, reg, alg, len); 1907 if (ret != 0) { 1908 adsp_err(dsp, "Failed to read algorithm list: %d\n", ret); 1909 kfree(alg); 1910 return ERR_PTR(ret); 1911 } 1912 1913 return alg; 1914 } 1915 1916 static struct wm_adsp_alg_region * 1917 wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id) 1918 { 1919 struct wm_adsp_alg_region *alg_region; 1920 1921 list_for_each_entry(alg_region, &dsp->alg_regions, list) { 1922 if (id == alg_region->alg && type == alg_region->type) 1923 return alg_region; 1924 } 1925 1926 return NULL; 1927 } 1928 1929 static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp, 1930 int type, __be32 id, 1931 __be32 base) 1932 { 1933 struct wm_adsp_alg_region *alg_region; 1934 1935 alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL); 1936 if (!alg_region) 1937 return ERR_PTR(-ENOMEM); 1938 1939 alg_region->type = type; 1940 alg_region->alg = be32_to_cpu(id); 1941 alg_region->base = be32_to_cpu(base); 1942 1943 list_add_tail(&alg_region->list, &dsp->alg_regions); 1944 1945 if (dsp->fw_ver > 0) 1946 wm_adsp_ctl_fixup_base(dsp, alg_region); 1947 1948 return alg_region; 1949 } 1950 1951 static void wm_adsp_free_alg_regions(struct wm_adsp *dsp) 1952 { 1953 struct wm_adsp_alg_region *alg_region; 1954 1955 while (!list_empty(&dsp->alg_regions)) { 1956 alg_region = list_first_entry(&dsp->alg_regions, 1957 struct wm_adsp_alg_region, 1958 list); 1959 list_del(&alg_region->list); 1960 kfree(alg_region); 1961 } 1962 } 1963 1964 static int wm_adsp1_setup_algs(struct wm_adsp *dsp) 1965 { 1966 struct wmfw_adsp1_id_hdr adsp1_id; 1967 struct wmfw_adsp1_alg_hdr *adsp1_alg; 1968 struct wm_adsp_alg_region *alg_region; 1969 const struct wm_adsp_region *mem; 1970 unsigned int pos, len; 1971 size_t n_algs; 1972 int i, ret; 1973 1974 mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM); 1975 if (WARN_ON(!mem)) 1976 return -EINVAL; 1977 1978 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id, 1979 sizeof(adsp1_id)); 1980 if (ret != 0) { 1981 adsp_err(dsp, "Failed to read algorithm info: %d\n", 1982 ret); 1983 return ret; 1984 } 1985 1986 n_algs = be32_to_cpu(adsp1_id.n_algs); 1987 dsp->fw_id = be32_to_cpu(adsp1_id.fw.id); 1988 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 1989 dsp->fw_id, 1990 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, 1991 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, 1992 be32_to_cpu(adsp1_id.fw.ver) & 0xff, 1993 n_algs); 1994 1995 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, 1996 adsp1_id.fw.id, adsp1_id.zm); 1997 if (IS_ERR(alg_region)) 1998 return PTR_ERR(alg_region); 1999 2000 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, 2001 adsp1_id.fw.id, adsp1_id.dm); 2002 if (IS_ERR(alg_region)) 2003 return PTR_ERR(alg_region); 2004 2005 /* Calculate offset and length in DSP words */ 2006 pos = sizeof(adsp1_id) / sizeof(u32); 2007 len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32); 2008 2009 adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len); 2010 if (IS_ERR(adsp1_alg)) 2011 return PTR_ERR(adsp1_alg); 2012 2013 for (i = 0; i < n_algs; i++) { 2014 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", 2015 i, be32_to_cpu(adsp1_alg[i].alg.id), 2016 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, 2017 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, 2018 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, 2019 be32_to_cpu(adsp1_alg[i].dm), 2020 be32_to_cpu(adsp1_alg[i].zm)); 2021 2022 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, 2023 adsp1_alg[i].alg.id, 2024 adsp1_alg[i].dm); 2025 if (IS_ERR(alg_region)) { 2026 ret = PTR_ERR(alg_region); 2027 goto out; 2028 } 2029 if (dsp->fw_ver == 0) { 2030 if (i + 1 < n_algs) { 2031 len = be32_to_cpu(adsp1_alg[i + 1].dm); 2032 len -= be32_to_cpu(adsp1_alg[i].dm); 2033 len *= 4; 2034 wm_adsp_create_control(dsp, alg_region, 0, 2035 len, NULL, 0, 0, 2036 SNDRV_CTL_ELEM_TYPE_BYTES); 2037 } else { 2038 adsp_warn(dsp, "Missing length info for region DM with ID %x\n", 2039 be32_to_cpu(adsp1_alg[i].alg.id)); 2040 } 2041 } 2042 2043 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, 2044 adsp1_alg[i].alg.id, 2045 adsp1_alg[i].zm); 2046 if (IS_ERR(alg_region)) { 2047 ret = PTR_ERR(alg_region); 2048 goto out; 2049 } 2050 if (dsp->fw_ver == 0) { 2051 if (i + 1 < n_algs) { 2052 len = be32_to_cpu(adsp1_alg[i + 1].zm); 2053 len -= be32_to_cpu(adsp1_alg[i].zm); 2054 len *= 4; 2055 wm_adsp_create_control(dsp, alg_region, 0, 2056 len, NULL, 0, 0, 2057 SNDRV_CTL_ELEM_TYPE_BYTES); 2058 } else { 2059 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 2060 be32_to_cpu(adsp1_alg[i].alg.id)); 2061 } 2062 } 2063 } 2064 2065 out: 2066 kfree(adsp1_alg); 2067 return ret; 2068 } 2069 2070 static int wm_adsp2_setup_algs(struct wm_adsp *dsp) 2071 { 2072 struct wmfw_adsp2_id_hdr adsp2_id; 2073 struct wmfw_adsp2_alg_hdr *adsp2_alg; 2074 struct wm_adsp_alg_region *alg_region; 2075 const struct wm_adsp_region *mem; 2076 unsigned int pos, len; 2077 size_t n_algs; 2078 int i, ret; 2079 2080 mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM); 2081 if (WARN_ON(!mem)) 2082 return -EINVAL; 2083 2084 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id, 2085 sizeof(adsp2_id)); 2086 if (ret != 0) { 2087 adsp_err(dsp, "Failed to read algorithm info: %d\n", 2088 ret); 2089 return ret; 2090 } 2091 2092 n_algs = be32_to_cpu(adsp2_id.n_algs); 2093 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); 2094 dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver); 2095 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 2096 dsp->fw_id, 2097 (dsp->fw_id_version & 0xff0000) >> 16, 2098 (dsp->fw_id_version & 0xff00) >> 8, 2099 dsp->fw_id_version & 0xff, 2100 n_algs); 2101 2102 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, 2103 adsp2_id.fw.id, adsp2_id.xm); 2104 if (IS_ERR(alg_region)) 2105 return PTR_ERR(alg_region); 2106 2107 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, 2108 adsp2_id.fw.id, adsp2_id.ym); 2109 if (IS_ERR(alg_region)) 2110 return PTR_ERR(alg_region); 2111 2112 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, 2113 adsp2_id.fw.id, adsp2_id.zm); 2114 if (IS_ERR(alg_region)) 2115 return PTR_ERR(alg_region); 2116 2117 /* Calculate offset and length in DSP words */ 2118 pos = sizeof(adsp2_id) / sizeof(u32); 2119 len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32); 2120 2121 adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len); 2122 if (IS_ERR(adsp2_alg)) 2123 return PTR_ERR(adsp2_alg); 2124 2125 for (i = 0; i < n_algs; i++) { 2126 adsp_info(dsp, 2127 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", 2128 i, be32_to_cpu(adsp2_alg[i].alg.id), 2129 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, 2130 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, 2131 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, 2132 be32_to_cpu(adsp2_alg[i].xm), 2133 be32_to_cpu(adsp2_alg[i].ym), 2134 be32_to_cpu(adsp2_alg[i].zm)); 2135 2136 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, 2137 adsp2_alg[i].alg.id, 2138 adsp2_alg[i].xm); 2139 if (IS_ERR(alg_region)) { 2140 ret = PTR_ERR(alg_region); 2141 goto out; 2142 } 2143 if (dsp->fw_ver == 0) { 2144 if (i + 1 < n_algs) { 2145 len = be32_to_cpu(adsp2_alg[i + 1].xm); 2146 len -= be32_to_cpu(adsp2_alg[i].xm); 2147 len *= 4; 2148 wm_adsp_create_control(dsp, alg_region, 0, 2149 len, NULL, 0, 0, 2150 SNDRV_CTL_ELEM_TYPE_BYTES); 2151 } else { 2152 adsp_warn(dsp, "Missing length info for region XM with ID %x\n", 2153 be32_to_cpu(adsp2_alg[i].alg.id)); 2154 } 2155 } 2156 2157 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, 2158 adsp2_alg[i].alg.id, 2159 adsp2_alg[i].ym); 2160 if (IS_ERR(alg_region)) { 2161 ret = PTR_ERR(alg_region); 2162 goto out; 2163 } 2164 if (dsp->fw_ver == 0) { 2165 if (i + 1 < n_algs) { 2166 len = be32_to_cpu(adsp2_alg[i + 1].ym); 2167 len -= be32_to_cpu(adsp2_alg[i].ym); 2168 len *= 4; 2169 wm_adsp_create_control(dsp, alg_region, 0, 2170 len, NULL, 0, 0, 2171 SNDRV_CTL_ELEM_TYPE_BYTES); 2172 } else { 2173 adsp_warn(dsp, "Missing length info for region YM with ID %x\n", 2174 be32_to_cpu(adsp2_alg[i].alg.id)); 2175 } 2176 } 2177 2178 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, 2179 adsp2_alg[i].alg.id, 2180 adsp2_alg[i].zm); 2181 if (IS_ERR(alg_region)) { 2182 ret = PTR_ERR(alg_region); 2183 goto out; 2184 } 2185 if (dsp->fw_ver == 0) { 2186 if (i + 1 < n_algs) { 2187 len = be32_to_cpu(adsp2_alg[i + 1].zm); 2188 len -= be32_to_cpu(adsp2_alg[i].zm); 2189 len *= 4; 2190 wm_adsp_create_control(dsp, alg_region, 0, 2191 len, NULL, 0, 0, 2192 SNDRV_CTL_ELEM_TYPE_BYTES); 2193 } else { 2194 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 2195 be32_to_cpu(adsp2_alg[i].alg.id)); 2196 } 2197 } 2198 } 2199 2200 out: 2201 kfree(adsp2_alg); 2202 return ret; 2203 } 2204 2205 static int wm_adsp_load_coeff(struct wm_adsp *dsp) 2206 { 2207 LIST_HEAD(buf_list); 2208 struct regmap *regmap = dsp->regmap; 2209 struct wmfw_coeff_hdr *hdr; 2210 struct wmfw_coeff_item *blk; 2211 const struct firmware *firmware; 2212 const struct wm_adsp_region *mem; 2213 struct wm_adsp_alg_region *alg_region; 2214 const char *region_name; 2215 int ret, pos, blocks, type, offset, reg; 2216 char *file; 2217 struct wm_adsp_buf *buf; 2218 2219 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 2220 if (file == NULL) 2221 return -ENOMEM; 2222 2223 snprintf(file, PAGE_SIZE, "%s-%s-%s.bin", dsp->part, dsp->fwf_name, 2224 wm_adsp_fw[dsp->fw].file); 2225 file[PAGE_SIZE - 1] = '\0'; 2226 2227 ret = request_firmware(&firmware, file, dsp->dev); 2228 if (ret != 0) { 2229 adsp_warn(dsp, "Failed to request '%s'\n", file); 2230 ret = 0; 2231 goto out; 2232 } 2233 ret = -EINVAL; 2234 2235 if (sizeof(*hdr) >= firmware->size) { 2236 adsp_err(dsp, "%s: file too short, %zu bytes\n", 2237 file, firmware->size); 2238 goto out_fw; 2239 } 2240 2241 hdr = (void *)&firmware->data[0]; 2242 if (memcmp(hdr->magic, "WMDR", 4) != 0) { 2243 adsp_err(dsp, "%s: invalid magic\n", file); 2244 goto out_fw; 2245 } 2246 2247 switch (be32_to_cpu(hdr->rev) & 0xff) { 2248 case 1: 2249 break; 2250 default: 2251 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n", 2252 file, be32_to_cpu(hdr->rev) & 0xff); 2253 ret = -EINVAL; 2254 goto out_fw; 2255 } 2256 2257 adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, 2258 (le32_to_cpu(hdr->ver) >> 16) & 0xff, 2259 (le32_to_cpu(hdr->ver) >> 8) & 0xff, 2260 le32_to_cpu(hdr->ver) & 0xff); 2261 2262 pos = le32_to_cpu(hdr->len); 2263 2264 blocks = 0; 2265 while (pos < firmware->size && 2266 sizeof(*blk) < firmware->size - pos) { 2267 blk = (void *)(&firmware->data[pos]); 2268 2269 type = le16_to_cpu(blk->type); 2270 offset = le16_to_cpu(blk->offset); 2271 2272 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", 2273 file, blocks, le32_to_cpu(blk->id), 2274 (le32_to_cpu(blk->ver) >> 16) & 0xff, 2275 (le32_to_cpu(blk->ver) >> 8) & 0xff, 2276 le32_to_cpu(blk->ver) & 0xff); 2277 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", 2278 file, blocks, le32_to_cpu(blk->len), offset, type); 2279 2280 reg = 0; 2281 region_name = "Unknown"; 2282 switch (type) { 2283 case (WMFW_NAME_TEXT << 8): 2284 case (WMFW_INFO_TEXT << 8): 2285 break; 2286 case (WMFW_ABSOLUTE << 8): 2287 /* 2288 * Old files may use this for global 2289 * coefficients. 2290 */ 2291 if (le32_to_cpu(blk->id) == dsp->fw_id && 2292 offset == 0) { 2293 region_name = "global coefficients"; 2294 mem = wm_adsp_find_region(dsp, type); 2295 if (!mem) { 2296 adsp_err(dsp, "No ZM\n"); 2297 break; 2298 } 2299 reg = wm_adsp_region_to_reg(mem, 0); 2300 2301 } else { 2302 region_name = "register"; 2303 reg = offset; 2304 } 2305 break; 2306 2307 case WMFW_ADSP1_DM: 2308 case WMFW_ADSP1_ZM: 2309 case WMFW_ADSP2_XM: 2310 case WMFW_ADSP2_YM: 2311 adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", 2312 file, blocks, le32_to_cpu(blk->len), 2313 type, le32_to_cpu(blk->id)); 2314 2315 mem = wm_adsp_find_region(dsp, type); 2316 if (!mem) { 2317 adsp_err(dsp, "No base for region %x\n", type); 2318 break; 2319 } 2320 2321 alg_region = wm_adsp_find_alg_region(dsp, type, 2322 le32_to_cpu(blk->id)); 2323 if (alg_region) { 2324 reg = alg_region->base; 2325 reg = wm_adsp_region_to_reg(mem, reg); 2326 reg += offset; 2327 } else { 2328 adsp_err(dsp, "No %x for algorithm %x\n", 2329 type, le32_to_cpu(blk->id)); 2330 } 2331 break; 2332 2333 default: 2334 adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n", 2335 file, blocks, type, pos); 2336 break; 2337 } 2338 2339 if (reg) { 2340 if (le32_to_cpu(blk->len) > 2341 firmware->size - pos - sizeof(*blk)) { 2342 adsp_err(dsp, 2343 "%s.%d: %s region len %d bytes exceeds file length %zu\n", 2344 file, blocks, region_name, 2345 le32_to_cpu(blk->len), 2346 firmware->size); 2347 ret = -EINVAL; 2348 goto out_fw; 2349 } 2350 2351 buf = wm_adsp_buf_alloc(blk->data, 2352 le32_to_cpu(blk->len), 2353 &buf_list); 2354 if (!buf) { 2355 adsp_err(dsp, "Out of memory\n"); 2356 ret = -ENOMEM; 2357 goto out_fw; 2358 } 2359 2360 adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", 2361 file, blocks, le32_to_cpu(blk->len), 2362 reg); 2363 ret = regmap_raw_write_async(regmap, reg, buf->buf, 2364 le32_to_cpu(blk->len)); 2365 if (ret != 0) { 2366 adsp_err(dsp, 2367 "%s.%d: Failed to write to %x in %s: %d\n", 2368 file, blocks, reg, region_name, ret); 2369 } 2370 } 2371 2372 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03; 2373 blocks++; 2374 } 2375 2376 ret = regmap_async_complete(regmap); 2377 if (ret != 0) 2378 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 2379 2380 if (pos > firmware->size) 2381 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 2382 file, blocks, pos - firmware->size); 2383 2384 wm_adsp_debugfs_save_binname(dsp, file); 2385 2386 out_fw: 2387 regmap_async_complete(regmap); 2388 release_firmware(firmware); 2389 wm_adsp_buf_free(&buf_list); 2390 out: 2391 kfree(file); 2392 return ret; 2393 } 2394 2395 static int wm_adsp_create_name(struct wm_adsp *dsp) 2396 { 2397 char *p; 2398 2399 if (!dsp->name) { 2400 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d", 2401 dsp->num); 2402 if (!dsp->name) 2403 return -ENOMEM; 2404 } 2405 2406 if (!dsp->fwf_name) { 2407 p = devm_kstrdup(dsp->dev, dsp->name, GFP_KERNEL); 2408 if (!p) 2409 return -ENOMEM; 2410 2411 dsp->fwf_name = p; 2412 for (; *p != 0; ++p) 2413 *p = tolower(*p); 2414 } 2415 2416 return 0; 2417 } 2418 2419 int wm_adsp1_init(struct wm_adsp *dsp) 2420 { 2421 int ret; 2422 2423 ret = wm_adsp_create_name(dsp); 2424 if (ret) 2425 return ret; 2426 2427 INIT_LIST_HEAD(&dsp->alg_regions); 2428 2429 mutex_init(&dsp->pwr_lock); 2430 2431 return 0; 2432 } 2433 EXPORT_SYMBOL_GPL(wm_adsp1_init); 2434 2435 int wm_adsp1_event(struct snd_soc_dapm_widget *w, 2436 struct snd_kcontrol *kcontrol, 2437 int event) 2438 { 2439 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2440 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2441 struct wm_adsp *dsp = &dsps[w->shift]; 2442 struct wm_coeff_ctl *ctl; 2443 int ret; 2444 unsigned int val; 2445 2446 dsp->component = component; 2447 2448 mutex_lock(&dsp->pwr_lock); 2449 2450 switch (event) { 2451 case SND_SOC_DAPM_POST_PMU: 2452 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2453 ADSP1_SYS_ENA, ADSP1_SYS_ENA); 2454 2455 /* 2456 * For simplicity set the DSP clock rate to be the 2457 * SYSCLK rate rather than making it configurable. 2458 */ 2459 if (dsp->sysclk_reg) { 2460 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); 2461 if (ret != 0) { 2462 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", 2463 ret); 2464 goto err_mutex; 2465 } 2466 2467 val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift; 2468 2469 ret = regmap_update_bits(dsp->regmap, 2470 dsp->base + ADSP1_CONTROL_31, 2471 ADSP1_CLK_SEL_MASK, val); 2472 if (ret != 0) { 2473 adsp_err(dsp, "Failed to set clock rate: %d\n", 2474 ret); 2475 goto err_mutex; 2476 } 2477 } 2478 2479 ret = wm_adsp_load(dsp); 2480 if (ret != 0) 2481 goto err_ena; 2482 2483 ret = wm_adsp1_setup_algs(dsp); 2484 if (ret != 0) 2485 goto err_ena; 2486 2487 ret = wm_adsp_load_coeff(dsp); 2488 if (ret != 0) 2489 goto err_ena; 2490 2491 /* Initialize caches for enabled and unset controls */ 2492 ret = wm_coeff_init_control_caches(dsp); 2493 if (ret != 0) 2494 goto err_ena; 2495 2496 /* Sync set controls */ 2497 ret = wm_coeff_sync_controls(dsp); 2498 if (ret != 0) 2499 goto err_ena; 2500 2501 dsp->booted = true; 2502 2503 /* Start the core running */ 2504 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2505 ADSP1_CORE_ENA | ADSP1_START, 2506 ADSP1_CORE_ENA | ADSP1_START); 2507 2508 dsp->running = true; 2509 break; 2510 2511 case SND_SOC_DAPM_PRE_PMD: 2512 dsp->running = false; 2513 dsp->booted = false; 2514 2515 /* Halt the core */ 2516 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2517 ADSP1_CORE_ENA | ADSP1_START, 0); 2518 2519 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, 2520 ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); 2521 2522 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2523 ADSP1_SYS_ENA, 0); 2524 2525 list_for_each_entry(ctl, &dsp->ctl_list, list) 2526 ctl->enabled = 0; 2527 2528 2529 wm_adsp_free_alg_regions(dsp); 2530 break; 2531 2532 default: 2533 break; 2534 } 2535 2536 mutex_unlock(&dsp->pwr_lock); 2537 2538 return 0; 2539 2540 err_ena: 2541 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2542 ADSP1_SYS_ENA, 0); 2543 err_mutex: 2544 mutex_unlock(&dsp->pwr_lock); 2545 2546 return ret; 2547 } 2548 EXPORT_SYMBOL_GPL(wm_adsp1_event); 2549 2550 static int wm_adsp2_ena(struct wm_adsp *dsp) 2551 { 2552 unsigned int val; 2553 int ret, count; 2554 2555 switch (dsp->rev) { 2556 case 0: 2557 ret = regmap_update_bits_async(dsp->regmap, 2558 dsp->base + ADSP2_CONTROL, 2559 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 2560 if (ret != 0) 2561 return ret; 2562 break; 2563 default: 2564 break; 2565 } 2566 2567 /* Wait for the RAM to start, should be near instantaneous */ 2568 for (count = 0; count < 10; ++count) { 2569 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val); 2570 if (ret != 0) 2571 return ret; 2572 2573 if (val & ADSP2_RAM_RDY) 2574 break; 2575 2576 usleep_range(250, 500); 2577 } 2578 2579 if (!(val & ADSP2_RAM_RDY)) { 2580 adsp_err(dsp, "Failed to start DSP RAM\n"); 2581 return -EBUSY; 2582 } 2583 2584 adsp_dbg(dsp, "RAM ready after %d polls\n", count); 2585 2586 return 0; 2587 } 2588 2589 static void wm_adsp2_boot_work(struct work_struct *work) 2590 { 2591 struct wm_adsp *dsp = container_of(work, 2592 struct wm_adsp, 2593 boot_work); 2594 int ret; 2595 2596 mutex_lock(&dsp->pwr_lock); 2597 2598 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2599 ADSP2_MEM_ENA, ADSP2_MEM_ENA); 2600 if (ret != 0) 2601 goto err_mutex; 2602 2603 ret = wm_adsp2_ena(dsp); 2604 if (ret != 0) 2605 goto err_mem; 2606 2607 ret = wm_adsp_load(dsp); 2608 if (ret != 0) 2609 goto err_ena; 2610 2611 ret = wm_adsp2_setup_algs(dsp); 2612 if (ret != 0) 2613 goto err_ena; 2614 2615 ret = wm_adsp_load_coeff(dsp); 2616 if (ret != 0) 2617 goto err_ena; 2618 2619 /* Initialize caches for enabled and unset controls */ 2620 ret = wm_coeff_init_control_caches(dsp); 2621 if (ret != 0) 2622 goto err_ena; 2623 2624 switch (dsp->rev) { 2625 case 0: 2626 /* Turn DSP back off until we are ready to run */ 2627 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2628 ADSP2_SYS_ENA, 0); 2629 if (ret != 0) 2630 goto err_ena; 2631 break; 2632 default: 2633 break; 2634 } 2635 2636 dsp->booted = true; 2637 2638 mutex_unlock(&dsp->pwr_lock); 2639 2640 return; 2641 2642 err_ena: 2643 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2644 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2645 err_mem: 2646 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2647 ADSP2_MEM_ENA, 0); 2648 err_mutex: 2649 mutex_unlock(&dsp->pwr_lock); 2650 } 2651 2652 static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq) 2653 { 2654 int ret; 2655 2656 switch (dsp->rev) { 2657 case 0: 2658 ret = regmap_update_bits_async(dsp->regmap, 2659 dsp->base + ADSP2_CLOCKING, 2660 ADSP2_CLK_SEL_MASK, 2661 freq << ADSP2_CLK_SEL_SHIFT); 2662 if (ret) { 2663 adsp_err(dsp, "Failed to set clock rate: %d\n", ret); 2664 return; 2665 } 2666 break; 2667 default: 2668 /* clock is handled by parent codec driver */ 2669 break; 2670 } 2671 } 2672 2673 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, 2674 struct snd_ctl_elem_value *ucontrol) 2675 { 2676 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2677 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2678 struct soc_mixer_control *mc = 2679 (struct soc_mixer_control *)kcontrol->private_value; 2680 struct wm_adsp *dsp = &dsps[mc->shift - 1]; 2681 2682 ucontrol->value.integer.value[0] = dsp->preloaded; 2683 2684 return 0; 2685 } 2686 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get); 2687 2688 int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, 2689 struct snd_ctl_elem_value *ucontrol) 2690 { 2691 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2692 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2693 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 2694 struct soc_mixer_control *mc = 2695 (struct soc_mixer_control *)kcontrol->private_value; 2696 struct wm_adsp *dsp = &dsps[mc->shift - 1]; 2697 char preload[32]; 2698 2699 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); 2700 2701 dsp->preloaded = ucontrol->value.integer.value[0]; 2702 2703 if (ucontrol->value.integer.value[0]) 2704 snd_soc_component_force_enable_pin(component, preload); 2705 else 2706 snd_soc_component_disable_pin(component, preload); 2707 2708 snd_soc_dapm_sync(dapm); 2709 2710 flush_work(&dsp->boot_work); 2711 2712 return 0; 2713 } 2714 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); 2715 2716 static void wm_adsp_stop_watchdog(struct wm_adsp *dsp) 2717 { 2718 switch (dsp->rev) { 2719 case 0: 2720 case 1: 2721 return; 2722 default: 2723 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG, 2724 ADSP2_WDT_ENA_MASK, 0); 2725 } 2726 } 2727 2728 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 2729 struct snd_kcontrol *kcontrol, int event, 2730 unsigned int freq) 2731 { 2732 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2733 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2734 struct wm_adsp *dsp = &dsps[w->shift]; 2735 struct wm_coeff_ctl *ctl; 2736 2737 switch (event) { 2738 case SND_SOC_DAPM_PRE_PMU: 2739 wm_adsp2_set_dspclk(dsp, freq); 2740 queue_work(system_unbound_wq, &dsp->boot_work); 2741 break; 2742 case SND_SOC_DAPM_PRE_PMD: 2743 mutex_lock(&dsp->pwr_lock); 2744 2745 wm_adsp_debugfs_clear(dsp); 2746 2747 dsp->fw_id = 0; 2748 dsp->fw_id_version = 0; 2749 2750 dsp->booted = false; 2751 2752 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2753 ADSP2_MEM_ENA, 0); 2754 2755 list_for_each_entry(ctl, &dsp->ctl_list, list) 2756 ctl->enabled = 0; 2757 2758 wm_adsp_free_alg_regions(dsp); 2759 2760 mutex_unlock(&dsp->pwr_lock); 2761 2762 adsp_dbg(dsp, "Shutdown complete\n"); 2763 break; 2764 default: 2765 break; 2766 } 2767 2768 return 0; 2769 } 2770 EXPORT_SYMBOL_GPL(wm_adsp2_early_event); 2771 2772 int wm_adsp2_event(struct snd_soc_dapm_widget *w, 2773 struct snd_kcontrol *kcontrol, int event) 2774 { 2775 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2776 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2777 struct wm_adsp *dsp = &dsps[w->shift]; 2778 int ret; 2779 2780 switch (event) { 2781 case SND_SOC_DAPM_POST_PMU: 2782 flush_work(&dsp->boot_work); 2783 2784 mutex_lock(&dsp->pwr_lock); 2785 2786 if (!dsp->booted) { 2787 ret = -EIO; 2788 goto err; 2789 } 2790 2791 ret = wm_adsp2_ena(dsp); 2792 if (ret != 0) 2793 goto err; 2794 2795 /* Sync set controls */ 2796 ret = wm_coeff_sync_controls(dsp); 2797 if (ret != 0) 2798 goto err; 2799 2800 wm_adsp2_lock(dsp, dsp->lock_regions); 2801 2802 ret = regmap_update_bits(dsp->regmap, 2803 dsp->base + ADSP2_CONTROL, 2804 ADSP2_CORE_ENA | ADSP2_START, 2805 ADSP2_CORE_ENA | ADSP2_START); 2806 if (ret != 0) 2807 goto err; 2808 2809 if (wm_adsp_fw[dsp->fw].num_caps != 0) { 2810 ret = wm_adsp_buffer_init(dsp); 2811 if (ret < 0) 2812 goto err; 2813 } 2814 2815 dsp->running = true; 2816 2817 mutex_unlock(&dsp->pwr_lock); 2818 2819 break; 2820 2821 case SND_SOC_DAPM_PRE_PMD: 2822 /* Tell the firmware to cleanup */ 2823 wm_adsp_signal_event_controls(dsp, WM_ADSP_FW_EVENT_SHUTDOWN); 2824 2825 wm_adsp_stop_watchdog(dsp); 2826 2827 /* Log firmware state, it can be useful for analysis */ 2828 switch (dsp->rev) { 2829 case 0: 2830 wm_adsp2_show_fw_status(dsp); 2831 break; 2832 default: 2833 wm_adsp2v2_show_fw_status(dsp); 2834 break; 2835 } 2836 2837 mutex_lock(&dsp->pwr_lock); 2838 2839 dsp->running = false; 2840 2841 regmap_update_bits(dsp->regmap, 2842 dsp->base + ADSP2_CONTROL, 2843 ADSP2_CORE_ENA | ADSP2_START, 0); 2844 2845 /* Make sure DMAs are quiesced */ 2846 switch (dsp->rev) { 2847 case 0: 2848 regmap_write(dsp->regmap, 2849 dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2850 regmap_write(dsp->regmap, 2851 dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2852 regmap_write(dsp->regmap, 2853 dsp->base + ADSP2_WDMA_CONFIG_2, 0); 2854 2855 regmap_update_bits(dsp->regmap, 2856 dsp->base + ADSP2_CONTROL, 2857 ADSP2_SYS_ENA, 0); 2858 break; 2859 default: 2860 regmap_write(dsp->regmap, 2861 dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2862 regmap_write(dsp->regmap, 2863 dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2864 regmap_write(dsp->regmap, 2865 dsp->base + ADSP2V2_WDMA_CONFIG_2, 0); 2866 break; 2867 } 2868 2869 if (wm_adsp_fw[dsp->fw].num_caps != 0) 2870 wm_adsp_buffer_free(dsp); 2871 2872 mutex_unlock(&dsp->pwr_lock); 2873 2874 adsp_dbg(dsp, "Execution stopped\n"); 2875 break; 2876 2877 default: 2878 break; 2879 } 2880 2881 return 0; 2882 err: 2883 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2884 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2885 mutex_unlock(&dsp->pwr_lock); 2886 return ret; 2887 } 2888 EXPORT_SYMBOL_GPL(wm_adsp2_event); 2889 2890 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component) 2891 { 2892 char preload[32]; 2893 2894 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); 2895 snd_soc_component_disable_pin(component, preload); 2896 2897 wm_adsp2_init_debugfs(dsp, component); 2898 2899 dsp->component = component; 2900 2901 return 0; 2902 } 2903 EXPORT_SYMBOL_GPL(wm_adsp2_component_probe); 2904 2905 int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component) 2906 { 2907 wm_adsp2_cleanup_debugfs(dsp); 2908 2909 return 0; 2910 } 2911 EXPORT_SYMBOL_GPL(wm_adsp2_component_remove); 2912 2913 int wm_adsp2_init(struct wm_adsp *dsp) 2914 { 2915 int ret; 2916 2917 ret = wm_adsp_create_name(dsp); 2918 if (ret) 2919 return ret; 2920 2921 switch (dsp->rev) { 2922 case 0: 2923 /* 2924 * Disable the DSP memory by default when in reset for a small 2925 * power saving. 2926 */ 2927 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2928 ADSP2_MEM_ENA, 0); 2929 if (ret) { 2930 adsp_err(dsp, 2931 "Failed to clear memory retention: %d\n", ret); 2932 return ret; 2933 } 2934 break; 2935 default: 2936 break; 2937 } 2938 2939 INIT_LIST_HEAD(&dsp->alg_regions); 2940 INIT_LIST_HEAD(&dsp->ctl_list); 2941 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); 2942 2943 mutex_init(&dsp->pwr_lock); 2944 2945 return 0; 2946 } 2947 EXPORT_SYMBOL_GPL(wm_adsp2_init); 2948 2949 void wm_adsp2_remove(struct wm_adsp *dsp) 2950 { 2951 struct wm_coeff_ctl *ctl; 2952 2953 while (!list_empty(&dsp->ctl_list)) { 2954 ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl, 2955 list); 2956 list_del(&ctl->list); 2957 wm_adsp_free_ctl_blk(ctl); 2958 } 2959 } 2960 EXPORT_SYMBOL_GPL(wm_adsp2_remove); 2961 2962 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr) 2963 { 2964 return compr->buf != NULL; 2965 } 2966 2967 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr) 2968 { 2969 /* 2970 * Note this will be more complex once each DSP can support multiple 2971 * streams 2972 */ 2973 if (!compr->dsp->buffer) 2974 return -EINVAL; 2975 2976 compr->buf = compr->dsp->buffer; 2977 compr->buf->compr = compr; 2978 2979 return 0; 2980 } 2981 2982 static void wm_adsp_compr_detach(struct wm_adsp_compr *compr) 2983 { 2984 if (!compr) 2985 return; 2986 2987 /* Wake the poll so it can see buffer is no longer attached */ 2988 if (compr->stream) 2989 snd_compr_fragment_elapsed(compr->stream); 2990 2991 if (wm_adsp_compr_attached(compr)) { 2992 compr->buf->compr = NULL; 2993 compr->buf = NULL; 2994 } 2995 } 2996 2997 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream) 2998 { 2999 struct wm_adsp_compr *compr; 3000 int ret = 0; 3001 3002 mutex_lock(&dsp->pwr_lock); 3003 3004 if (wm_adsp_fw[dsp->fw].num_caps == 0) { 3005 adsp_err(dsp, "Firmware does not support compressed API\n"); 3006 ret = -ENXIO; 3007 goto out; 3008 } 3009 3010 if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) { 3011 adsp_err(dsp, "Firmware does not support stream direction\n"); 3012 ret = -EINVAL; 3013 goto out; 3014 } 3015 3016 if (dsp->compr) { 3017 /* It is expect this limitation will be removed in future */ 3018 adsp_err(dsp, "Only a single stream supported per DSP\n"); 3019 ret = -EBUSY; 3020 goto out; 3021 } 3022 3023 compr = kzalloc(sizeof(*compr), GFP_KERNEL); 3024 if (!compr) { 3025 ret = -ENOMEM; 3026 goto out; 3027 } 3028 3029 compr->dsp = dsp; 3030 compr->stream = stream; 3031 3032 dsp->compr = compr; 3033 3034 stream->runtime->private_data = compr; 3035 3036 out: 3037 mutex_unlock(&dsp->pwr_lock); 3038 3039 return ret; 3040 } 3041 EXPORT_SYMBOL_GPL(wm_adsp_compr_open); 3042 3043 int wm_adsp_compr_free(struct snd_compr_stream *stream) 3044 { 3045 struct wm_adsp_compr *compr = stream->runtime->private_data; 3046 struct wm_adsp *dsp = compr->dsp; 3047 3048 mutex_lock(&dsp->pwr_lock); 3049 3050 wm_adsp_compr_detach(compr); 3051 dsp->compr = NULL; 3052 3053 kfree(compr->raw_buf); 3054 kfree(compr); 3055 3056 mutex_unlock(&dsp->pwr_lock); 3057 3058 return 0; 3059 } 3060 EXPORT_SYMBOL_GPL(wm_adsp_compr_free); 3061 3062 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream, 3063 struct snd_compr_params *params) 3064 { 3065 struct wm_adsp_compr *compr = stream->runtime->private_data; 3066 struct wm_adsp *dsp = compr->dsp; 3067 const struct wm_adsp_fw_caps *caps; 3068 const struct snd_codec_desc *desc; 3069 int i, j; 3070 3071 if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE || 3072 params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE || 3073 params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS || 3074 params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS || 3075 params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) { 3076 adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n", 3077 params->buffer.fragment_size, 3078 params->buffer.fragments); 3079 3080 return -EINVAL; 3081 } 3082 3083 for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) { 3084 caps = &wm_adsp_fw[dsp->fw].caps[i]; 3085 desc = &caps->desc; 3086 3087 if (caps->id != params->codec.id) 3088 continue; 3089 3090 if (stream->direction == SND_COMPRESS_PLAYBACK) { 3091 if (desc->max_ch < params->codec.ch_out) 3092 continue; 3093 } else { 3094 if (desc->max_ch < params->codec.ch_in) 3095 continue; 3096 } 3097 3098 if (!(desc->formats & (1 << params->codec.format))) 3099 continue; 3100 3101 for (j = 0; j < desc->num_sample_rates; ++j) 3102 if (desc->sample_rates[j] == params->codec.sample_rate) 3103 return 0; 3104 } 3105 3106 adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n", 3107 params->codec.id, params->codec.ch_in, params->codec.ch_out, 3108 params->codec.sample_rate, params->codec.format); 3109 return -EINVAL; 3110 } 3111 3112 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr) 3113 { 3114 return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE; 3115 } 3116 3117 int wm_adsp_compr_set_params(struct snd_compr_stream *stream, 3118 struct snd_compr_params *params) 3119 { 3120 struct wm_adsp_compr *compr = stream->runtime->private_data; 3121 unsigned int size; 3122 int ret; 3123 3124 ret = wm_adsp_compr_check_params(stream, params); 3125 if (ret) 3126 return ret; 3127 3128 compr->size = params->buffer; 3129 3130 adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n", 3131 compr->size.fragment_size, compr->size.fragments); 3132 3133 size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf); 3134 compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); 3135 if (!compr->raw_buf) 3136 return -ENOMEM; 3137 3138 compr->sample_rate = params->codec.sample_rate; 3139 3140 return 0; 3141 } 3142 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); 3143 3144 int wm_adsp_compr_get_caps(struct snd_compr_stream *stream, 3145 struct snd_compr_caps *caps) 3146 { 3147 struct wm_adsp_compr *compr = stream->runtime->private_data; 3148 int fw = compr->dsp->fw; 3149 int i; 3150 3151 if (wm_adsp_fw[fw].caps) { 3152 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++) 3153 caps->codecs[i] = wm_adsp_fw[fw].caps[i].id; 3154 3155 caps->num_codecs = i; 3156 caps->direction = wm_adsp_fw[fw].compr_direction; 3157 3158 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE; 3159 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE; 3160 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS; 3161 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS; 3162 } 3163 3164 return 0; 3165 } 3166 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); 3167 3168 static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, 3169 unsigned int mem_addr, 3170 unsigned int num_words, u32 *data) 3171 { 3172 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 3173 unsigned int i, reg; 3174 int ret; 3175 3176 if (!mem) 3177 return -EINVAL; 3178 3179 reg = wm_adsp_region_to_reg(mem, mem_addr); 3180 3181 ret = regmap_raw_read(dsp->regmap, reg, data, 3182 sizeof(*data) * num_words); 3183 if (ret < 0) 3184 return ret; 3185 3186 for (i = 0; i < num_words; ++i) 3187 data[i] = be32_to_cpu(data[i]) & 0x00ffffffu; 3188 3189 return 0; 3190 } 3191 3192 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type, 3193 unsigned int mem_addr, u32 *data) 3194 { 3195 return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data); 3196 } 3197 3198 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, 3199 unsigned int mem_addr, u32 data) 3200 { 3201 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 3202 unsigned int reg; 3203 3204 if (!mem) 3205 return -EINVAL; 3206 3207 reg = wm_adsp_region_to_reg(mem, mem_addr); 3208 3209 data = cpu_to_be32(data & 0x00ffffffu); 3210 3211 return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data)); 3212 } 3213 3214 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, 3215 unsigned int field_offset, u32 *data) 3216 { 3217 return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM, 3218 buf->host_buf_ptr + field_offset, data); 3219 } 3220 3221 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, 3222 unsigned int field_offset, u32 data) 3223 { 3224 return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM, 3225 buf->host_buf_ptr + field_offset, data); 3226 } 3227 3228 static int wm_adsp_legacy_host_buf_addr(struct wm_adsp_compr_buf *buf) 3229 { 3230 struct wm_adsp_alg_region *alg_region; 3231 struct wm_adsp *dsp = buf->dsp; 3232 u32 xmalg, addr, magic; 3233 int i, ret; 3234 3235 alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id); 3236 xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32); 3237 3238 addr = alg_region->base + xmalg + ALG_XM_FIELD(magic); 3239 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic); 3240 if (ret < 0) 3241 return ret; 3242 3243 if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC) 3244 return -EINVAL; 3245 3246 addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr); 3247 for (i = 0; i < 5; ++i) { 3248 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, 3249 &buf->host_buf_ptr); 3250 if (ret < 0) 3251 return ret; 3252 3253 if (buf->host_buf_ptr) 3254 break; 3255 3256 usleep_range(1000, 2000); 3257 } 3258 3259 if (!buf->host_buf_ptr) 3260 return -EIO; 3261 3262 adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); 3263 3264 return 0; 3265 } 3266 3267 static struct wm_coeff_ctl * 3268 wm_adsp_find_host_buffer_ctrl(struct wm_adsp_compr_buf *buf) 3269 { 3270 struct wm_adsp *dsp = buf->dsp; 3271 struct wm_coeff_ctl *ctl; 3272 3273 list_for_each_entry(ctl, &dsp->ctl_list, list) { 3274 if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER) 3275 continue; 3276 3277 if (!ctl->enabled) 3278 continue; 3279 3280 return ctl; 3281 } 3282 3283 return NULL; 3284 } 3285 3286 static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf) 3287 { 3288 struct wm_adsp *dsp = buf->dsp; 3289 struct wm_coeff_ctl *ctl; 3290 unsigned int reg; 3291 u32 val; 3292 int i, ret; 3293 3294 ctl = wm_adsp_find_host_buffer_ctrl(buf); 3295 if (!ctl) 3296 return wm_adsp_legacy_host_buf_addr(buf); 3297 3298 ret = wm_coeff_base_reg(ctl, ®); 3299 if (ret) 3300 return ret; 3301 3302 for (i = 0; i < 5; ++i) { 3303 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 3304 if (ret < 0) 3305 return ret; 3306 3307 if (val) 3308 break; 3309 3310 usleep_range(1000, 2000); 3311 } 3312 3313 if (!val) 3314 return -EIO; 3315 3316 buf->host_buf_ptr = be32_to_cpu(val); 3317 adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); 3318 3319 return 0; 3320 } 3321 3322 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) 3323 { 3324 const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; 3325 struct wm_adsp_buffer_region *region; 3326 u32 offset = 0; 3327 int i, ret; 3328 3329 for (i = 0; i < caps->num_regions; ++i) { 3330 region = &buf->regions[i]; 3331 3332 region->offset = offset; 3333 region->mem_type = caps->region_defs[i].mem_type; 3334 3335 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset, 3336 ®ion->base_addr); 3337 if (ret < 0) 3338 return ret; 3339 3340 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset, 3341 &offset); 3342 if (ret < 0) 3343 return ret; 3344 3345 region->cumulative_size = offset; 3346 3347 adsp_dbg(buf->dsp, 3348 "region=%d type=%d base=%04x off=%04x size=%04x\n", 3349 i, region->mem_type, region->base_addr, 3350 region->offset, region->cumulative_size); 3351 } 3352 3353 return 0; 3354 } 3355 3356 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf) 3357 { 3358 buf->irq_count = 0xFFFFFFFF; 3359 buf->read_index = -1; 3360 buf->avail = 0; 3361 } 3362 3363 static int wm_adsp_buffer_init(struct wm_adsp *dsp) 3364 { 3365 struct wm_adsp_compr_buf *buf; 3366 int ret; 3367 3368 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 3369 if (!buf) 3370 return -ENOMEM; 3371 3372 buf->dsp = dsp; 3373 3374 wm_adsp_buffer_clear(buf); 3375 3376 ret = wm_adsp_buffer_locate(buf); 3377 if (ret < 0) { 3378 adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret); 3379 goto err_buffer; 3380 } 3381 3382 buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions, 3383 sizeof(*buf->regions), GFP_KERNEL); 3384 if (!buf->regions) { 3385 ret = -ENOMEM; 3386 goto err_buffer; 3387 } 3388 3389 ret = wm_adsp_buffer_populate(buf); 3390 if (ret < 0) { 3391 adsp_err(dsp, "Failed to populate host buffer: %d\n", ret); 3392 goto err_regions; 3393 } 3394 3395 dsp->buffer = buf; 3396 3397 return 0; 3398 3399 err_regions: 3400 kfree(buf->regions); 3401 err_buffer: 3402 kfree(buf); 3403 return ret; 3404 } 3405 3406 static int wm_adsp_buffer_free(struct wm_adsp *dsp) 3407 { 3408 if (dsp->buffer) { 3409 wm_adsp_compr_detach(dsp->buffer->compr); 3410 3411 kfree(dsp->buffer->regions); 3412 kfree(dsp->buffer); 3413 3414 dsp->buffer = NULL; 3415 } 3416 3417 return 0; 3418 } 3419 3420 int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd) 3421 { 3422 struct wm_adsp_compr *compr = stream->runtime->private_data; 3423 struct wm_adsp *dsp = compr->dsp; 3424 int ret = 0; 3425 3426 adsp_dbg(dsp, "Trigger: %d\n", cmd); 3427 3428 mutex_lock(&dsp->pwr_lock); 3429 3430 switch (cmd) { 3431 case SNDRV_PCM_TRIGGER_START: 3432 if (!wm_adsp_compr_attached(compr)) { 3433 ret = wm_adsp_compr_attach(compr); 3434 if (ret < 0) { 3435 adsp_err(dsp, "Failed to link buffer and stream: %d\n", 3436 ret); 3437 break; 3438 } 3439 } 3440 3441 wm_adsp_buffer_clear(compr->buf); 3442 3443 /* Trigger the IRQ at one fragment of data */ 3444 ret = wm_adsp_buffer_write(compr->buf, 3445 HOST_BUFFER_FIELD(high_water_mark), 3446 wm_adsp_compr_frag_words(compr)); 3447 if (ret < 0) { 3448 adsp_err(dsp, "Failed to set high water mark: %d\n", 3449 ret); 3450 break; 3451 } 3452 break; 3453 case SNDRV_PCM_TRIGGER_STOP: 3454 break; 3455 default: 3456 ret = -EINVAL; 3457 break; 3458 } 3459 3460 mutex_unlock(&dsp->pwr_lock); 3461 3462 return ret; 3463 } 3464 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger); 3465 3466 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf) 3467 { 3468 int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1; 3469 3470 return buf->regions[last_region].cumulative_size; 3471 } 3472 3473 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) 3474 { 3475 u32 next_read_index, next_write_index; 3476 int write_index, read_index, avail; 3477 int ret; 3478 3479 /* Only sync read index if we haven't already read a valid index */ 3480 if (buf->read_index < 0) { 3481 ret = wm_adsp_buffer_read(buf, 3482 HOST_BUFFER_FIELD(next_read_index), 3483 &next_read_index); 3484 if (ret < 0) 3485 return ret; 3486 3487 read_index = sign_extend32(next_read_index, 23); 3488 3489 if (read_index < 0) { 3490 adsp_dbg(buf->dsp, "Avail check on unstarted stream\n"); 3491 return 0; 3492 } 3493 3494 buf->read_index = read_index; 3495 } 3496 3497 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index), 3498 &next_write_index); 3499 if (ret < 0) 3500 return ret; 3501 3502 write_index = sign_extend32(next_write_index, 23); 3503 3504 avail = write_index - buf->read_index; 3505 if (avail < 0) 3506 avail += wm_adsp_buffer_size(buf); 3507 3508 adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n", 3509 buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE); 3510 3511 buf->avail = avail; 3512 3513 return 0; 3514 } 3515 3516 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf) 3517 { 3518 int ret; 3519 3520 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error); 3521 if (ret < 0) { 3522 adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret); 3523 return ret; 3524 } 3525 if (buf->error != 0) { 3526 adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error); 3527 return -EIO; 3528 } 3529 3530 return 0; 3531 } 3532 3533 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) 3534 { 3535 struct wm_adsp_compr_buf *buf; 3536 struct wm_adsp_compr *compr; 3537 int ret = 0; 3538 3539 mutex_lock(&dsp->pwr_lock); 3540 3541 buf = dsp->buffer; 3542 compr = dsp->compr; 3543 3544 if (!buf) { 3545 ret = -ENODEV; 3546 goto out; 3547 } 3548 3549 adsp_dbg(dsp, "Handling buffer IRQ\n"); 3550 3551 ret = wm_adsp_buffer_get_error(buf); 3552 if (ret < 0) 3553 goto out_notify; /* Wake poll to report error */ 3554 3555 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count), 3556 &buf->irq_count); 3557 if (ret < 0) { 3558 adsp_err(dsp, "Failed to get irq_count: %d\n", ret); 3559 goto out; 3560 } 3561 3562 ret = wm_adsp_buffer_update_avail(buf); 3563 if (ret < 0) { 3564 adsp_err(dsp, "Error reading avail: %d\n", ret); 3565 goto out; 3566 } 3567 3568 if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2) 3569 ret = WM_ADSP_COMPR_VOICE_TRIGGER; 3570 3571 out_notify: 3572 if (compr && compr->stream) 3573 snd_compr_fragment_elapsed(compr->stream); 3574 3575 out: 3576 mutex_unlock(&dsp->pwr_lock); 3577 3578 return ret; 3579 } 3580 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq); 3581 3582 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf) 3583 { 3584 if (buf->irq_count & 0x01) 3585 return 0; 3586 3587 adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n", 3588 buf->irq_count); 3589 3590 buf->irq_count |= 0x01; 3591 3592 return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack), 3593 buf->irq_count); 3594 } 3595 3596 int wm_adsp_compr_pointer(struct snd_compr_stream *stream, 3597 struct snd_compr_tstamp *tstamp) 3598 { 3599 struct wm_adsp_compr *compr = stream->runtime->private_data; 3600 struct wm_adsp *dsp = compr->dsp; 3601 struct wm_adsp_compr_buf *buf; 3602 int ret = 0; 3603 3604 adsp_dbg(dsp, "Pointer request\n"); 3605 3606 mutex_lock(&dsp->pwr_lock); 3607 3608 buf = compr->buf; 3609 3610 if (!compr->buf || compr->buf->error) { 3611 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN); 3612 ret = -EIO; 3613 goto out; 3614 } 3615 3616 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 3617 ret = wm_adsp_buffer_update_avail(buf); 3618 if (ret < 0) { 3619 adsp_err(dsp, "Error reading avail: %d\n", ret); 3620 goto out; 3621 } 3622 3623 /* 3624 * If we really have less than 1 fragment available tell the 3625 * DSP to inform us once a whole fragment is available. 3626 */ 3627 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 3628 ret = wm_adsp_buffer_get_error(buf); 3629 if (ret < 0) { 3630 if (compr->buf->error) 3631 snd_compr_stop_error(stream, 3632 SNDRV_PCM_STATE_XRUN); 3633 goto out; 3634 } 3635 3636 ret = wm_adsp_buffer_reenable_irq(buf); 3637 if (ret < 0) { 3638 adsp_err(dsp, 3639 "Failed to re-enable buffer IRQ: %d\n", 3640 ret); 3641 goto out; 3642 } 3643 } 3644 } 3645 3646 tstamp->copied_total = compr->copied_total; 3647 tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE; 3648 tstamp->sampling_rate = compr->sample_rate; 3649 3650 out: 3651 mutex_unlock(&dsp->pwr_lock); 3652 3653 return ret; 3654 } 3655 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer); 3656 3657 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) 3658 { 3659 struct wm_adsp_compr_buf *buf = compr->buf; 3660 u8 *pack_in = (u8 *)compr->raw_buf; 3661 u8 *pack_out = (u8 *)compr->raw_buf; 3662 unsigned int adsp_addr; 3663 int mem_type, nwords, max_read; 3664 int i, j, ret; 3665 3666 /* Calculate read parameters */ 3667 for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i) 3668 if (buf->read_index < buf->regions[i].cumulative_size) 3669 break; 3670 3671 if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions) 3672 return -EINVAL; 3673 3674 mem_type = buf->regions[i].mem_type; 3675 adsp_addr = buf->regions[i].base_addr + 3676 (buf->read_index - buf->regions[i].offset); 3677 3678 max_read = wm_adsp_compr_frag_words(compr); 3679 nwords = buf->regions[i].cumulative_size - buf->read_index; 3680 3681 if (nwords > target) 3682 nwords = target; 3683 if (nwords > buf->avail) 3684 nwords = buf->avail; 3685 if (nwords > max_read) 3686 nwords = max_read; 3687 if (!nwords) 3688 return 0; 3689 3690 /* Read data from DSP */ 3691 ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, 3692 nwords, compr->raw_buf); 3693 if (ret < 0) 3694 return ret; 3695 3696 /* Remove the padding bytes from the data read from the DSP */ 3697 for (i = 0; i < nwords; i++) { 3698 for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++) 3699 *pack_out++ = *pack_in++; 3700 3701 pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE; 3702 } 3703 3704 /* update read index to account for words read */ 3705 buf->read_index += nwords; 3706 if (buf->read_index == wm_adsp_buffer_size(buf)) 3707 buf->read_index = 0; 3708 3709 ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index), 3710 buf->read_index); 3711 if (ret < 0) 3712 return ret; 3713 3714 /* update avail to account for words read */ 3715 buf->avail -= nwords; 3716 3717 return nwords; 3718 } 3719 3720 static int wm_adsp_compr_read(struct wm_adsp_compr *compr, 3721 char __user *buf, size_t count) 3722 { 3723 struct wm_adsp *dsp = compr->dsp; 3724 int ntotal = 0; 3725 int nwords, nbytes; 3726 3727 adsp_dbg(dsp, "Requested read of %zu bytes\n", count); 3728 3729 if (!compr->buf || compr->buf->error) { 3730 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN); 3731 return -EIO; 3732 } 3733 3734 count /= WM_ADSP_DATA_WORD_SIZE; 3735 3736 do { 3737 nwords = wm_adsp_buffer_capture_block(compr, count); 3738 if (nwords < 0) { 3739 adsp_err(dsp, "Failed to capture block: %d\n", nwords); 3740 return nwords; 3741 } 3742 3743 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE; 3744 3745 adsp_dbg(dsp, "Read %d bytes\n", nbytes); 3746 3747 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) { 3748 adsp_err(dsp, "Failed to copy data to user: %d, %d\n", 3749 ntotal, nbytes); 3750 return -EFAULT; 3751 } 3752 3753 count -= nwords; 3754 ntotal += nbytes; 3755 } while (nwords > 0 && count > 0); 3756 3757 compr->copied_total += ntotal; 3758 3759 return ntotal; 3760 } 3761 3762 int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf, 3763 size_t count) 3764 { 3765 struct wm_adsp_compr *compr = stream->runtime->private_data; 3766 struct wm_adsp *dsp = compr->dsp; 3767 int ret; 3768 3769 mutex_lock(&dsp->pwr_lock); 3770 3771 if (stream->direction == SND_COMPRESS_CAPTURE) 3772 ret = wm_adsp_compr_read(compr, buf, count); 3773 else 3774 ret = -ENOTSUPP; 3775 3776 mutex_unlock(&dsp->pwr_lock); 3777 3778 return ret; 3779 } 3780 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy); 3781 3782 int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions) 3783 { 3784 struct regmap *regmap = dsp->regmap; 3785 unsigned int code0, code1, lock_reg; 3786 3787 if (!(lock_regions & WM_ADSP2_REGION_ALL)) 3788 return 0; 3789 3790 lock_regions &= WM_ADSP2_REGION_ALL; 3791 lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0; 3792 3793 while (lock_regions) { 3794 code0 = code1 = 0; 3795 if (lock_regions & BIT(0)) { 3796 code0 = ADSP2_LOCK_CODE_0; 3797 code1 = ADSP2_LOCK_CODE_1; 3798 } 3799 if (lock_regions & BIT(1)) { 3800 code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT; 3801 code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT; 3802 } 3803 regmap_write(regmap, lock_reg, code0); 3804 regmap_write(regmap, lock_reg, code1); 3805 lock_regions >>= 2; 3806 lock_reg += 2; 3807 } 3808 3809 return 0; 3810 } 3811 EXPORT_SYMBOL_GPL(wm_adsp2_lock); 3812 3813 irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) 3814 { 3815 unsigned int val; 3816 struct regmap *regmap = dsp->regmap; 3817 int ret = 0; 3818 3819 ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val); 3820 if (ret) { 3821 adsp_err(dsp, 3822 "Failed to read Region Lock Ctrl register: %d\n", ret); 3823 return IRQ_HANDLED; 3824 } 3825 3826 if (val & ADSP2_WDT_TIMEOUT_STS_MASK) { 3827 adsp_err(dsp, "watchdog timeout error\n"); 3828 wm_adsp_stop_watchdog(dsp); 3829 } 3830 3831 if (val & (ADSP2_SLAVE_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) { 3832 if (val & ADSP2_SLAVE_ERR_MASK) 3833 adsp_err(dsp, "bus error: slave error\n"); 3834 else 3835 adsp_err(dsp, "bus error: region lock error\n"); 3836 3837 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val); 3838 if (ret) { 3839 adsp_err(dsp, 3840 "Failed to read Bus Err Addr register: %d\n", 3841 ret); 3842 return IRQ_HANDLED; 3843 } 3844 3845 adsp_err(dsp, "bus error address = 0x%x\n", 3846 val & ADSP2_BUS_ERR_ADDR_MASK); 3847 3848 ret = regmap_read(regmap, 3849 dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR, 3850 &val); 3851 if (ret) { 3852 adsp_err(dsp, 3853 "Failed to read Pmem Xmem Err Addr register: %d\n", 3854 ret); 3855 return IRQ_HANDLED; 3856 } 3857 3858 adsp_err(dsp, "xmem error address = 0x%x\n", 3859 val & ADSP2_XMEM_ERR_ADDR_MASK); 3860 adsp_err(dsp, "pmem error address = 0x%x\n", 3861 (val & ADSP2_PMEM_ERR_ADDR_MASK) >> 3862 ADSP2_PMEM_ERR_ADDR_SHIFT); 3863 } 3864 3865 regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, 3866 ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT); 3867 3868 return IRQ_HANDLED; 3869 } 3870 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); 3871 3872 MODULE_LICENSE("GPL v2"); 3873