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 buf1_base; /* Base addr of first buffer area */ 315 __be32 buf1_size; /* Size of buf1 area in DSP words */ 316 __be32 buf2_base; /* Base addr of 2nd buffer area */ 317 __be32 buf1_buf2_size; /* Size of buf1+buf2 in DSP words */ 318 __be32 buf3_base; /* Base addr of buf3 area */ 319 __be32 buf_total_size; /* Size of buf1+buf2+buf3 in DSP 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(buf1_base), 397 .size_offset = HOST_BUFFER_FIELD(buf1_size), 398 }, 399 { 400 .mem_type = WMFW_ADSP2_XM, 401 .base_offset = HOST_BUFFER_FIELD(buf2_base), 402 .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size), 403 }, 404 { 405 .mem_type = WMFW_ADSP2_YM, 406 .base_offset = HOST_BUFFER_FIELD(buf3_base), 407 .size_offset = HOST_BUFFER_FIELD(buf_total_size), 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 unsigned int scratch[4]; 769 unsigned int addr = dsp->base + ADSP2_SCRATCH0; 770 unsigned int i; 771 int ret; 772 773 for (i = 0; i < ARRAY_SIZE(scratch); ++i) { 774 ret = regmap_read(dsp->regmap, addr + i, &scratch[i]); 775 if (ret) { 776 adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret); 777 return; 778 } 779 } 780 781 adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 782 scratch[0], scratch[1], scratch[2], scratch[3]); 783 } 784 785 static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp) 786 { 787 unsigned int scratch[2]; 788 int ret; 789 790 ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1, 791 &scratch[0]); 792 if (ret) { 793 adsp_err(dsp, "Failed to read SCRATCH0_1: %d\n", ret); 794 return; 795 } 796 797 ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH2_3, 798 &scratch[1]); 799 if (ret) { 800 adsp_err(dsp, "Failed to read SCRATCH2_3: %d\n", ret); 801 return; 802 } 803 804 adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 805 scratch[0] & 0xFFFF, 806 scratch[0] >> 16, 807 scratch[1] & 0xFFFF, 808 scratch[1] >> 16); 809 } 810 811 static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext) 812 { 813 return container_of(ext, struct wm_coeff_ctl, bytes_ext); 814 } 815 816 static int wm_coeff_base_reg(struct wm_coeff_ctl *ctl, unsigned int *reg) 817 { 818 const struct wm_adsp_alg_region *alg_region = &ctl->alg_region; 819 struct wm_adsp *dsp = ctl->dsp; 820 const struct wm_adsp_region *mem; 821 822 mem = wm_adsp_find_region(dsp, alg_region->type); 823 if (!mem) { 824 adsp_err(dsp, "No base for region %x\n", 825 alg_region->type); 826 return -EINVAL; 827 } 828 829 *reg = wm_adsp_region_to_reg(mem, ctl->alg_region.base + ctl->offset); 830 831 return 0; 832 } 833 834 static int wm_coeff_info(struct snd_kcontrol *kctl, 835 struct snd_ctl_elem_info *uinfo) 836 { 837 struct soc_bytes_ext *bytes_ext = 838 (struct soc_bytes_ext *)kctl->private_value; 839 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 840 841 switch (ctl->type) { 842 case WMFW_CTL_TYPE_ACKED: 843 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 844 uinfo->value.integer.min = WM_ADSP_ACKED_CTL_MIN_VALUE; 845 uinfo->value.integer.max = WM_ADSP_ACKED_CTL_MAX_VALUE; 846 uinfo->value.integer.step = 1; 847 uinfo->count = 1; 848 break; 849 default: 850 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 851 uinfo->count = ctl->len; 852 break; 853 } 854 855 return 0; 856 } 857 858 static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl, 859 unsigned int event_id) 860 { 861 struct wm_adsp *dsp = ctl->dsp; 862 u32 val = cpu_to_be32(event_id); 863 unsigned int reg; 864 int i, ret; 865 866 ret = wm_coeff_base_reg(ctl, ®); 867 if (ret) 868 return ret; 869 870 adsp_dbg(dsp, "Sending 0x%x to acked control alg 0x%x %s:0x%x\n", 871 event_id, ctl->alg_region.alg, 872 wm_adsp_mem_region_name(ctl->alg_region.type), ctl->offset); 873 874 ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); 875 if (ret) { 876 adsp_err(dsp, "Failed to write %x: %d\n", reg, ret); 877 return ret; 878 } 879 880 /* 881 * Poll for ack, we initially poll at ~1ms intervals for firmwares 882 * that respond quickly, then go to ~10ms polls. A firmware is unlikely 883 * to ack instantly so we do the first 1ms delay before reading the 884 * control to avoid a pointless bus transaction 885 */ 886 for (i = 0; i < WM_ADSP_ACKED_CTL_TIMEOUT_MS;) { 887 switch (i) { 888 case 0 ... WM_ADSP_ACKED_CTL_N_QUICKPOLLS - 1: 889 usleep_range(1000, 2000); 890 i++; 891 break; 892 default: 893 usleep_range(10000, 20000); 894 i += 10; 895 break; 896 } 897 898 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 899 if (ret) { 900 adsp_err(dsp, "Failed to read %x: %d\n", reg, ret); 901 return ret; 902 } 903 904 if (val == 0) { 905 adsp_dbg(dsp, "Acked control ACKED at poll %u\n", i); 906 return 0; 907 } 908 } 909 910 adsp_warn(dsp, "Acked control @0x%x alg:0x%x %s:0x%x timed out\n", 911 reg, ctl->alg_region.alg, 912 wm_adsp_mem_region_name(ctl->alg_region.type), 913 ctl->offset); 914 915 return -ETIMEDOUT; 916 } 917 918 static int wm_coeff_write_control(struct wm_coeff_ctl *ctl, 919 const void *buf, size_t len) 920 { 921 struct wm_adsp *dsp = ctl->dsp; 922 void *scratch; 923 int ret; 924 unsigned int reg; 925 926 ret = wm_coeff_base_reg(ctl, ®); 927 if (ret) 928 return ret; 929 930 scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA); 931 if (!scratch) 932 return -ENOMEM; 933 934 ret = regmap_raw_write(dsp->regmap, reg, scratch, 935 len); 936 if (ret) { 937 adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n", 938 len, reg, ret); 939 kfree(scratch); 940 return ret; 941 } 942 adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg); 943 944 kfree(scratch); 945 946 return 0; 947 } 948 949 static int wm_coeff_put(struct snd_kcontrol *kctl, 950 struct snd_ctl_elem_value *ucontrol) 951 { 952 struct soc_bytes_ext *bytes_ext = 953 (struct soc_bytes_ext *)kctl->private_value; 954 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 955 char *p = ucontrol->value.bytes.data; 956 int ret = 0; 957 958 mutex_lock(&ctl->dsp->pwr_lock); 959 960 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 961 ret = -EPERM; 962 else 963 memcpy(ctl->cache, p, ctl->len); 964 965 ctl->set = 1; 966 if (ctl->enabled && ctl->dsp->running) 967 ret = wm_coeff_write_control(ctl, p, ctl->len); 968 969 mutex_unlock(&ctl->dsp->pwr_lock); 970 971 return ret; 972 } 973 974 static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, 975 const unsigned int __user *bytes, unsigned int size) 976 { 977 struct soc_bytes_ext *bytes_ext = 978 (struct soc_bytes_ext *)kctl->private_value; 979 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 980 int ret = 0; 981 982 mutex_lock(&ctl->dsp->pwr_lock); 983 984 if (copy_from_user(ctl->cache, bytes, size)) { 985 ret = -EFAULT; 986 } else { 987 ctl->set = 1; 988 if (ctl->enabled && ctl->dsp->running) 989 ret = wm_coeff_write_control(ctl, ctl->cache, size); 990 else if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 991 ret = -EPERM; 992 } 993 994 mutex_unlock(&ctl->dsp->pwr_lock); 995 996 return ret; 997 } 998 999 static int wm_coeff_put_acked(struct snd_kcontrol *kctl, 1000 struct snd_ctl_elem_value *ucontrol) 1001 { 1002 struct soc_bytes_ext *bytes_ext = 1003 (struct soc_bytes_ext *)kctl->private_value; 1004 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1005 unsigned int val = ucontrol->value.integer.value[0]; 1006 int ret; 1007 1008 if (val == 0) 1009 return 0; /* 0 means no event */ 1010 1011 mutex_lock(&ctl->dsp->pwr_lock); 1012 1013 if (ctl->enabled && ctl->dsp->running) 1014 ret = wm_coeff_write_acked_control(ctl, val); 1015 else 1016 ret = -EPERM; 1017 1018 mutex_unlock(&ctl->dsp->pwr_lock); 1019 1020 return ret; 1021 } 1022 1023 static int wm_coeff_read_control(struct wm_coeff_ctl *ctl, 1024 void *buf, size_t len) 1025 { 1026 struct wm_adsp *dsp = ctl->dsp; 1027 void *scratch; 1028 int ret; 1029 unsigned int reg; 1030 1031 ret = wm_coeff_base_reg(ctl, ®); 1032 if (ret) 1033 return ret; 1034 1035 scratch = kmalloc(len, GFP_KERNEL | GFP_DMA); 1036 if (!scratch) 1037 return -ENOMEM; 1038 1039 ret = regmap_raw_read(dsp->regmap, reg, scratch, len); 1040 if (ret) { 1041 adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n", 1042 len, reg, ret); 1043 kfree(scratch); 1044 return ret; 1045 } 1046 adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg); 1047 1048 memcpy(buf, scratch, len); 1049 kfree(scratch); 1050 1051 return 0; 1052 } 1053 1054 static int wm_coeff_get(struct snd_kcontrol *kctl, 1055 struct snd_ctl_elem_value *ucontrol) 1056 { 1057 struct soc_bytes_ext *bytes_ext = 1058 (struct soc_bytes_ext *)kctl->private_value; 1059 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1060 char *p = ucontrol->value.bytes.data; 1061 int ret = 0; 1062 1063 mutex_lock(&ctl->dsp->pwr_lock); 1064 1065 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { 1066 if (ctl->enabled && ctl->dsp->running) 1067 ret = wm_coeff_read_control(ctl, p, ctl->len); 1068 else 1069 ret = -EPERM; 1070 } else { 1071 if (!ctl->flags && ctl->enabled && ctl->dsp->running) 1072 ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); 1073 1074 memcpy(p, ctl->cache, ctl->len); 1075 } 1076 1077 mutex_unlock(&ctl->dsp->pwr_lock); 1078 1079 return ret; 1080 } 1081 1082 static int wm_coeff_tlv_get(struct snd_kcontrol *kctl, 1083 unsigned int __user *bytes, unsigned int size) 1084 { 1085 struct soc_bytes_ext *bytes_ext = 1086 (struct soc_bytes_ext *)kctl->private_value; 1087 struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); 1088 int ret = 0; 1089 1090 mutex_lock(&ctl->dsp->pwr_lock); 1091 1092 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { 1093 if (ctl->enabled && ctl->dsp->running) 1094 ret = wm_coeff_read_control(ctl, ctl->cache, size); 1095 else 1096 ret = -EPERM; 1097 } else { 1098 if (!ctl->flags && ctl->enabled && ctl->dsp->running) 1099 ret = wm_coeff_read_control(ctl, ctl->cache, size); 1100 } 1101 1102 if (!ret && copy_to_user(bytes, ctl->cache, size)) 1103 ret = -EFAULT; 1104 1105 mutex_unlock(&ctl->dsp->pwr_lock); 1106 1107 return ret; 1108 } 1109 1110 static int wm_coeff_get_acked(struct snd_kcontrol *kcontrol, 1111 struct snd_ctl_elem_value *ucontrol) 1112 { 1113 /* 1114 * Although it's not useful to read an acked control, we must satisfy 1115 * user-side assumptions that all controls are readable and that a 1116 * write of the same value should be filtered out (it's valid to send 1117 * the same event number again to the firmware). We therefore return 0, 1118 * meaning "no event" so valid event numbers will always be a change 1119 */ 1120 ucontrol->value.integer.value[0] = 0; 1121 1122 return 0; 1123 } 1124 1125 struct wmfw_ctl_work { 1126 struct wm_adsp *dsp; 1127 struct wm_coeff_ctl *ctl; 1128 struct work_struct work; 1129 }; 1130 1131 static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len) 1132 { 1133 unsigned int out, rd, wr, vol; 1134 1135 if (len > ADSP_MAX_STD_CTRL_SIZE) { 1136 rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ; 1137 wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE; 1138 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE; 1139 1140 out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; 1141 } else { 1142 rd = SNDRV_CTL_ELEM_ACCESS_READ; 1143 wr = SNDRV_CTL_ELEM_ACCESS_WRITE; 1144 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE; 1145 1146 out = 0; 1147 } 1148 1149 if (in) { 1150 if (in & WMFW_CTL_FLAG_READABLE) 1151 out |= rd; 1152 if (in & WMFW_CTL_FLAG_WRITEABLE) 1153 out |= wr; 1154 if (in & WMFW_CTL_FLAG_VOLATILE) 1155 out |= vol; 1156 } else { 1157 out |= rd | wr | vol; 1158 } 1159 1160 return out; 1161 } 1162 1163 static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl) 1164 { 1165 struct snd_kcontrol_new *kcontrol; 1166 int ret; 1167 1168 if (!ctl || !ctl->name) 1169 return -EINVAL; 1170 1171 kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); 1172 if (!kcontrol) 1173 return -ENOMEM; 1174 1175 kcontrol->name = ctl->name; 1176 kcontrol->info = wm_coeff_info; 1177 kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1178 kcontrol->tlv.c = snd_soc_bytes_tlv_callback; 1179 kcontrol->private_value = (unsigned long)&ctl->bytes_ext; 1180 kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len); 1181 1182 switch (ctl->type) { 1183 case WMFW_CTL_TYPE_ACKED: 1184 kcontrol->get = wm_coeff_get_acked; 1185 kcontrol->put = wm_coeff_put_acked; 1186 break; 1187 default: 1188 if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 1189 ctl->bytes_ext.max = ctl->len; 1190 ctl->bytes_ext.get = wm_coeff_tlv_get; 1191 ctl->bytes_ext.put = wm_coeff_tlv_put; 1192 } else { 1193 kcontrol->get = wm_coeff_get; 1194 kcontrol->put = wm_coeff_put; 1195 } 1196 break; 1197 } 1198 1199 ret = snd_soc_add_component_controls(dsp->component, kcontrol, 1); 1200 if (ret < 0) 1201 goto err_kcontrol; 1202 1203 kfree(kcontrol); 1204 1205 return 0; 1206 1207 err_kcontrol: 1208 kfree(kcontrol); 1209 return ret; 1210 } 1211 1212 static int wm_coeff_init_control_caches(struct wm_adsp *dsp) 1213 { 1214 struct wm_coeff_ctl *ctl; 1215 int ret; 1216 1217 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1218 if (!ctl->enabled || ctl->set) 1219 continue; 1220 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 1221 continue; 1222 1223 /* 1224 * For readable controls populate the cache from the DSP memory. 1225 * For non-readable controls the cache was zero-filled when 1226 * created so we don't need to do anything. 1227 */ 1228 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) { 1229 ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); 1230 if (ret < 0) 1231 return ret; 1232 } 1233 } 1234 1235 return 0; 1236 } 1237 1238 static int wm_coeff_sync_controls(struct wm_adsp *dsp) 1239 { 1240 struct wm_coeff_ctl *ctl; 1241 int ret; 1242 1243 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1244 if (!ctl->enabled) 1245 continue; 1246 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) { 1247 ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len); 1248 if (ret < 0) 1249 return ret; 1250 } 1251 } 1252 1253 return 0; 1254 } 1255 1256 static void wm_adsp_signal_event_controls(struct wm_adsp *dsp, 1257 unsigned int event) 1258 { 1259 struct wm_coeff_ctl *ctl; 1260 int ret; 1261 1262 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1263 if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT) 1264 continue; 1265 1266 if (!ctl->enabled) 1267 continue; 1268 1269 ret = wm_coeff_write_acked_control(ctl, event); 1270 if (ret) 1271 adsp_warn(dsp, 1272 "Failed to send 0x%x event to alg 0x%x (%d)\n", 1273 event, ctl->alg_region.alg, ret); 1274 } 1275 } 1276 1277 static void wm_adsp_ctl_work(struct work_struct *work) 1278 { 1279 struct wmfw_ctl_work *ctl_work = container_of(work, 1280 struct wmfw_ctl_work, 1281 work); 1282 1283 wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl); 1284 kfree(ctl_work); 1285 } 1286 1287 static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl) 1288 { 1289 kfree(ctl->cache); 1290 kfree(ctl->name); 1291 kfree(ctl); 1292 } 1293 1294 static int wm_adsp_create_control(struct wm_adsp *dsp, 1295 const struct wm_adsp_alg_region *alg_region, 1296 unsigned int offset, unsigned int len, 1297 const char *subname, unsigned int subname_len, 1298 unsigned int flags, unsigned int type) 1299 { 1300 struct wm_coeff_ctl *ctl; 1301 struct wmfw_ctl_work *ctl_work; 1302 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 1303 const char *region_name; 1304 int ret; 1305 1306 region_name = wm_adsp_mem_region_name(alg_region->type); 1307 if (!region_name) { 1308 adsp_err(dsp, "Unknown region type: %d\n", alg_region->type); 1309 return -EINVAL; 1310 } 1311 1312 switch (dsp->fw_ver) { 1313 case 0: 1314 case 1: 1315 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x", 1316 dsp->name, region_name, alg_region->alg); 1317 break; 1318 default: 1319 ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1320 "%s%c %.12s %x", dsp->name, *region_name, 1321 wm_adsp_fw_text[dsp->fw], alg_region->alg); 1322 1323 /* Truncate the subname from the start if it is too long */ 1324 if (subname) { 1325 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2; 1326 int skip = 0; 1327 1328 if (dsp->component->name_prefix) 1329 avail -= strlen(dsp->component->name_prefix) + 1; 1330 1331 if (subname_len > avail) 1332 skip = subname_len - avail; 1333 1334 snprintf(name + ret, 1335 SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s", 1336 subname_len - skip, subname + skip); 1337 } 1338 break; 1339 } 1340 1341 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1342 if (!strcmp(ctl->name, name)) { 1343 if (!ctl->enabled) 1344 ctl->enabled = 1; 1345 return 0; 1346 } 1347 } 1348 1349 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); 1350 if (!ctl) 1351 return -ENOMEM; 1352 ctl->fw_name = wm_adsp_fw_text[dsp->fw]; 1353 ctl->alg_region = *alg_region; 1354 ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); 1355 if (!ctl->name) { 1356 ret = -ENOMEM; 1357 goto err_ctl; 1358 } 1359 ctl->enabled = 1; 1360 ctl->set = 0; 1361 ctl->ops.xget = wm_coeff_get; 1362 ctl->ops.xput = wm_coeff_put; 1363 ctl->dsp = dsp; 1364 1365 ctl->flags = flags; 1366 ctl->type = type; 1367 ctl->offset = offset; 1368 ctl->len = len; 1369 ctl->cache = kzalloc(ctl->len, GFP_KERNEL); 1370 if (!ctl->cache) { 1371 ret = -ENOMEM; 1372 goto err_ctl_name; 1373 } 1374 1375 list_add(&ctl->list, &dsp->ctl_list); 1376 1377 if (flags & WMFW_CTL_FLAG_SYS) 1378 return 0; 1379 1380 ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); 1381 if (!ctl_work) { 1382 ret = -ENOMEM; 1383 goto err_ctl_cache; 1384 } 1385 1386 ctl_work->dsp = dsp; 1387 ctl_work->ctl = ctl; 1388 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); 1389 schedule_work(&ctl_work->work); 1390 1391 return 0; 1392 1393 err_ctl_cache: 1394 kfree(ctl->cache); 1395 err_ctl_name: 1396 kfree(ctl->name); 1397 err_ctl: 1398 kfree(ctl); 1399 1400 return ret; 1401 } 1402 1403 struct wm_coeff_parsed_alg { 1404 int id; 1405 const u8 *name; 1406 int name_len; 1407 int ncoeff; 1408 }; 1409 1410 struct wm_coeff_parsed_coeff { 1411 int offset; 1412 int mem_type; 1413 const u8 *name; 1414 int name_len; 1415 int ctl_type; 1416 int flags; 1417 int len; 1418 }; 1419 1420 static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str) 1421 { 1422 int length; 1423 1424 switch (bytes) { 1425 case 1: 1426 length = **pos; 1427 break; 1428 case 2: 1429 length = le16_to_cpu(*((__le16 *)*pos)); 1430 break; 1431 default: 1432 return 0; 1433 } 1434 1435 if (str) 1436 *str = *pos + bytes; 1437 1438 *pos += ((length + bytes) + 3) & ~0x03; 1439 1440 return length; 1441 } 1442 1443 static int wm_coeff_parse_int(int bytes, const u8 **pos) 1444 { 1445 int val = 0; 1446 1447 switch (bytes) { 1448 case 2: 1449 val = le16_to_cpu(*((__le16 *)*pos)); 1450 break; 1451 case 4: 1452 val = le32_to_cpu(*((__le32 *)*pos)); 1453 break; 1454 default: 1455 break; 1456 } 1457 1458 *pos += bytes; 1459 1460 return val; 1461 } 1462 1463 static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data, 1464 struct wm_coeff_parsed_alg *blk) 1465 { 1466 const struct wmfw_adsp_alg_data *raw; 1467 1468 switch (dsp->fw_ver) { 1469 case 0: 1470 case 1: 1471 raw = (const struct wmfw_adsp_alg_data *)*data; 1472 *data = raw->data; 1473 1474 blk->id = le32_to_cpu(raw->id); 1475 blk->name = raw->name; 1476 blk->name_len = strlen(raw->name); 1477 blk->ncoeff = le32_to_cpu(raw->ncoeff); 1478 break; 1479 default: 1480 blk->id = wm_coeff_parse_int(sizeof(raw->id), data); 1481 blk->name_len = wm_coeff_parse_string(sizeof(u8), data, 1482 &blk->name); 1483 wm_coeff_parse_string(sizeof(u16), data, NULL); 1484 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data); 1485 break; 1486 } 1487 1488 adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); 1489 adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); 1490 adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); 1491 } 1492 1493 static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, 1494 struct wm_coeff_parsed_coeff *blk) 1495 { 1496 const struct wmfw_adsp_coeff_data *raw; 1497 const u8 *tmp; 1498 int length; 1499 1500 switch (dsp->fw_ver) { 1501 case 0: 1502 case 1: 1503 raw = (const struct wmfw_adsp_coeff_data *)*data; 1504 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); 1505 1506 blk->offset = le16_to_cpu(raw->hdr.offset); 1507 blk->mem_type = le16_to_cpu(raw->hdr.type); 1508 blk->name = raw->name; 1509 blk->name_len = strlen(raw->name); 1510 blk->ctl_type = le16_to_cpu(raw->ctl_type); 1511 blk->flags = le16_to_cpu(raw->flags); 1512 blk->len = le32_to_cpu(raw->len); 1513 break; 1514 default: 1515 tmp = *data; 1516 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp); 1517 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp); 1518 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp); 1519 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp, 1520 &blk->name); 1521 wm_coeff_parse_string(sizeof(u8), &tmp, NULL); 1522 wm_coeff_parse_string(sizeof(u16), &tmp, NULL); 1523 blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp); 1524 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp); 1525 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp); 1526 1527 *data = *data + sizeof(raw->hdr) + length; 1528 break; 1529 } 1530 1531 adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); 1532 adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); 1533 adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name); 1534 adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); 1535 adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); 1536 adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); 1537 } 1538 1539 static int wm_adsp_check_coeff_flags(struct wm_adsp *dsp, 1540 const struct wm_coeff_parsed_coeff *coeff_blk, 1541 unsigned int f_required, 1542 unsigned int f_illegal) 1543 { 1544 if ((coeff_blk->flags & f_illegal) || 1545 ((coeff_blk->flags & f_required) != f_required)) { 1546 adsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n", 1547 coeff_blk->flags, coeff_blk->ctl_type); 1548 return -EINVAL; 1549 } 1550 1551 return 0; 1552 } 1553 1554 static int wm_adsp_parse_coeff(struct wm_adsp *dsp, 1555 const struct wmfw_region *region) 1556 { 1557 struct wm_adsp_alg_region alg_region = {}; 1558 struct wm_coeff_parsed_alg alg_blk; 1559 struct wm_coeff_parsed_coeff coeff_blk; 1560 const u8 *data = region->data; 1561 int i, ret; 1562 1563 wm_coeff_parse_alg(dsp, &data, &alg_blk); 1564 for (i = 0; i < alg_blk.ncoeff; i++) { 1565 wm_coeff_parse_coeff(dsp, &data, &coeff_blk); 1566 1567 switch (coeff_blk.ctl_type) { 1568 case SNDRV_CTL_ELEM_TYPE_BYTES: 1569 break; 1570 case WMFW_CTL_TYPE_ACKED: 1571 if (coeff_blk.flags & WMFW_CTL_FLAG_SYS) 1572 continue; /* ignore */ 1573 1574 ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk, 1575 WMFW_CTL_FLAG_VOLATILE | 1576 WMFW_CTL_FLAG_WRITEABLE | 1577 WMFW_CTL_FLAG_READABLE, 1578 0); 1579 if (ret) 1580 return -EINVAL; 1581 break; 1582 case WMFW_CTL_TYPE_HOSTEVENT: 1583 ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk, 1584 WMFW_CTL_FLAG_SYS | 1585 WMFW_CTL_FLAG_VOLATILE | 1586 WMFW_CTL_FLAG_WRITEABLE | 1587 WMFW_CTL_FLAG_READABLE, 1588 0); 1589 if (ret) 1590 return -EINVAL; 1591 break; 1592 case WMFW_CTL_TYPE_HOST_BUFFER: 1593 ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk, 1594 WMFW_CTL_FLAG_SYS | 1595 WMFW_CTL_FLAG_VOLATILE | 1596 WMFW_CTL_FLAG_READABLE, 1597 0); 1598 if (ret) 1599 return -EINVAL; 1600 break; 1601 default: 1602 adsp_err(dsp, "Unknown control type: %d\n", 1603 coeff_blk.ctl_type); 1604 return -EINVAL; 1605 } 1606 1607 alg_region.type = coeff_blk.mem_type; 1608 alg_region.alg = alg_blk.id; 1609 1610 ret = wm_adsp_create_control(dsp, &alg_region, 1611 coeff_blk.offset, 1612 coeff_blk.len, 1613 coeff_blk.name, 1614 coeff_blk.name_len, 1615 coeff_blk.flags, 1616 coeff_blk.ctl_type); 1617 if (ret < 0) 1618 adsp_err(dsp, "Failed to create control: %.*s, %d\n", 1619 coeff_blk.name_len, coeff_blk.name, ret); 1620 } 1621 1622 return 0; 1623 } 1624 1625 static int wm_adsp_load(struct wm_adsp *dsp) 1626 { 1627 LIST_HEAD(buf_list); 1628 const struct firmware *firmware; 1629 struct regmap *regmap = dsp->regmap; 1630 unsigned int pos = 0; 1631 const struct wmfw_header *header; 1632 const struct wmfw_adsp1_sizes *adsp1_sizes; 1633 const struct wmfw_adsp2_sizes *adsp2_sizes; 1634 const struct wmfw_footer *footer; 1635 const struct wmfw_region *region; 1636 const struct wm_adsp_region *mem; 1637 const char *region_name; 1638 char *file, *text = NULL; 1639 struct wm_adsp_buf *buf; 1640 unsigned int reg; 1641 int regions = 0; 1642 int ret, offset, type, sizes; 1643 1644 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 1645 if (file == NULL) 1646 return -ENOMEM; 1647 1648 snprintf(file, PAGE_SIZE, "%s-%s-%s.wmfw", dsp->part, dsp->fwf_name, 1649 wm_adsp_fw[dsp->fw].file); 1650 file[PAGE_SIZE - 1] = '\0'; 1651 1652 ret = request_firmware(&firmware, file, dsp->dev); 1653 if (ret != 0) { 1654 adsp_err(dsp, "Failed to request '%s'\n", file); 1655 goto out; 1656 } 1657 ret = -EINVAL; 1658 1659 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1660 if (pos >= firmware->size) { 1661 adsp_err(dsp, "%s: file too short, %zu bytes\n", 1662 file, firmware->size); 1663 goto out_fw; 1664 } 1665 1666 header = (void *)&firmware->data[0]; 1667 1668 if (memcmp(&header->magic[0], "WMFW", 4) != 0) { 1669 adsp_err(dsp, "%s: invalid magic\n", file); 1670 goto out_fw; 1671 } 1672 1673 switch (header->ver) { 1674 case 0: 1675 adsp_warn(dsp, "%s: Depreciated file format %d\n", 1676 file, header->ver); 1677 break; 1678 case 1: 1679 case 2: 1680 break; 1681 default: 1682 adsp_err(dsp, "%s: unknown file format %d\n", 1683 file, header->ver); 1684 goto out_fw; 1685 } 1686 1687 adsp_info(dsp, "Firmware version: %d\n", header->ver); 1688 dsp->fw_ver = header->ver; 1689 1690 if (header->core != dsp->type) { 1691 adsp_err(dsp, "%s: invalid core %d != %d\n", 1692 file, header->core, dsp->type); 1693 goto out_fw; 1694 } 1695 1696 switch (dsp->type) { 1697 case WMFW_ADSP1: 1698 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1699 adsp1_sizes = (void *)&(header[1]); 1700 footer = (void *)&(adsp1_sizes[1]); 1701 sizes = sizeof(*adsp1_sizes); 1702 1703 adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", 1704 file, le32_to_cpu(adsp1_sizes->dm), 1705 le32_to_cpu(adsp1_sizes->pm), 1706 le32_to_cpu(adsp1_sizes->zm)); 1707 break; 1708 1709 case WMFW_ADSP2: 1710 pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer); 1711 adsp2_sizes = (void *)&(header[1]); 1712 footer = (void *)&(adsp2_sizes[1]); 1713 sizes = sizeof(*adsp2_sizes); 1714 1715 adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", 1716 file, le32_to_cpu(adsp2_sizes->xm), 1717 le32_to_cpu(adsp2_sizes->ym), 1718 le32_to_cpu(adsp2_sizes->pm), 1719 le32_to_cpu(adsp2_sizes->zm)); 1720 break; 1721 1722 default: 1723 WARN(1, "Unknown DSP type"); 1724 goto out_fw; 1725 } 1726 1727 if (le32_to_cpu(header->len) != sizeof(*header) + 1728 sizes + sizeof(*footer)) { 1729 adsp_err(dsp, "%s: unexpected header length %d\n", 1730 file, le32_to_cpu(header->len)); 1731 goto out_fw; 1732 } 1733 1734 adsp_dbg(dsp, "%s: timestamp %llu\n", file, 1735 le64_to_cpu(footer->timestamp)); 1736 1737 while (pos < firmware->size && 1738 sizeof(*region) < firmware->size - pos) { 1739 region = (void *)&(firmware->data[pos]); 1740 region_name = "Unknown"; 1741 reg = 0; 1742 text = NULL; 1743 offset = le32_to_cpu(region->offset) & 0xffffff; 1744 type = be32_to_cpu(region->type) & 0xff; 1745 mem = wm_adsp_find_region(dsp, type); 1746 1747 switch (type) { 1748 case WMFW_NAME_TEXT: 1749 region_name = "Firmware name"; 1750 text = kzalloc(le32_to_cpu(region->len) + 1, 1751 GFP_KERNEL); 1752 break; 1753 case WMFW_ALGORITHM_DATA: 1754 region_name = "Algorithm"; 1755 ret = wm_adsp_parse_coeff(dsp, region); 1756 if (ret != 0) 1757 goto out_fw; 1758 break; 1759 case WMFW_INFO_TEXT: 1760 region_name = "Information"; 1761 text = kzalloc(le32_to_cpu(region->len) + 1, 1762 GFP_KERNEL); 1763 break; 1764 case WMFW_ABSOLUTE: 1765 region_name = "Absolute"; 1766 reg = offset; 1767 break; 1768 case WMFW_ADSP1_PM: 1769 case WMFW_ADSP1_DM: 1770 case WMFW_ADSP2_XM: 1771 case WMFW_ADSP2_YM: 1772 case WMFW_ADSP1_ZM: 1773 region_name = wm_adsp_mem_region_name(type); 1774 reg = wm_adsp_region_to_reg(mem, offset); 1775 break; 1776 default: 1777 adsp_warn(dsp, 1778 "%s.%d: Unknown region type %x at %d(%x)\n", 1779 file, regions, type, pos, pos); 1780 break; 1781 } 1782 1783 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 1784 regions, le32_to_cpu(region->len), offset, 1785 region_name); 1786 1787 if (le32_to_cpu(region->len) > 1788 firmware->size - pos - sizeof(*region)) { 1789 adsp_err(dsp, 1790 "%s.%d: %s region len %d bytes exceeds file length %zu\n", 1791 file, regions, region_name, 1792 le32_to_cpu(region->len), firmware->size); 1793 ret = -EINVAL; 1794 goto out_fw; 1795 } 1796 1797 if (text) { 1798 memcpy(text, region->data, le32_to_cpu(region->len)); 1799 adsp_info(dsp, "%s: %s\n", file, text); 1800 kfree(text); 1801 text = NULL; 1802 } 1803 1804 if (reg) { 1805 buf = wm_adsp_buf_alloc(region->data, 1806 le32_to_cpu(region->len), 1807 &buf_list); 1808 if (!buf) { 1809 adsp_err(dsp, "Out of memory\n"); 1810 ret = -ENOMEM; 1811 goto out_fw; 1812 } 1813 1814 ret = regmap_raw_write_async(regmap, reg, buf->buf, 1815 le32_to_cpu(region->len)); 1816 if (ret != 0) { 1817 adsp_err(dsp, 1818 "%s.%d: Failed to write %d bytes at %d in %s: %d\n", 1819 file, regions, 1820 le32_to_cpu(region->len), offset, 1821 region_name, ret); 1822 goto out_fw; 1823 } 1824 } 1825 1826 pos += le32_to_cpu(region->len) + sizeof(*region); 1827 regions++; 1828 } 1829 1830 ret = regmap_async_complete(regmap); 1831 if (ret != 0) { 1832 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 1833 goto out_fw; 1834 } 1835 1836 if (pos > firmware->size) 1837 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 1838 file, regions, pos - firmware->size); 1839 1840 wm_adsp_debugfs_save_wmfwname(dsp, file); 1841 1842 out_fw: 1843 regmap_async_complete(regmap); 1844 wm_adsp_buf_free(&buf_list); 1845 release_firmware(firmware); 1846 kfree(text); 1847 out: 1848 kfree(file); 1849 1850 return ret; 1851 } 1852 1853 static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp, 1854 const struct wm_adsp_alg_region *alg_region) 1855 { 1856 struct wm_coeff_ctl *ctl; 1857 1858 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1859 if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] && 1860 alg_region->alg == ctl->alg_region.alg && 1861 alg_region->type == ctl->alg_region.type) { 1862 ctl->alg_region.base = alg_region->base; 1863 } 1864 } 1865 } 1866 1867 static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, 1868 const struct wm_adsp_region *mem, 1869 unsigned int pos, unsigned int len) 1870 { 1871 void *alg; 1872 unsigned int reg; 1873 int ret; 1874 __be32 val; 1875 1876 if (n_algs == 0) { 1877 adsp_err(dsp, "No algorithms\n"); 1878 return ERR_PTR(-EINVAL); 1879 } 1880 1881 if (n_algs > 1024) { 1882 adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs); 1883 return ERR_PTR(-EINVAL); 1884 } 1885 1886 /* Read the terminator first to validate the length */ 1887 reg = wm_adsp_region_to_reg(mem, pos + len); 1888 1889 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 1890 if (ret != 0) { 1891 adsp_err(dsp, "Failed to read algorithm list end: %d\n", 1892 ret); 1893 return ERR_PTR(ret); 1894 } 1895 1896 if (be32_to_cpu(val) != 0xbedead) 1897 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n", 1898 reg, be32_to_cpu(val)); 1899 1900 /* Convert length from DSP words to bytes */ 1901 len *= sizeof(u32); 1902 1903 alg = kzalloc(len, GFP_KERNEL | GFP_DMA); 1904 if (!alg) 1905 return ERR_PTR(-ENOMEM); 1906 1907 reg = wm_adsp_region_to_reg(mem, pos); 1908 1909 ret = regmap_raw_read(dsp->regmap, reg, alg, len); 1910 if (ret != 0) { 1911 adsp_err(dsp, "Failed to read algorithm list: %d\n", ret); 1912 kfree(alg); 1913 return ERR_PTR(ret); 1914 } 1915 1916 return alg; 1917 } 1918 1919 static struct wm_adsp_alg_region * 1920 wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id) 1921 { 1922 struct wm_adsp_alg_region *alg_region; 1923 1924 list_for_each_entry(alg_region, &dsp->alg_regions, list) { 1925 if (id == alg_region->alg && type == alg_region->type) 1926 return alg_region; 1927 } 1928 1929 return NULL; 1930 } 1931 1932 static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp, 1933 int type, __be32 id, 1934 __be32 base) 1935 { 1936 struct wm_adsp_alg_region *alg_region; 1937 1938 alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL); 1939 if (!alg_region) 1940 return ERR_PTR(-ENOMEM); 1941 1942 alg_region->type = type; 1943 alg_region->alg = be32_to_cpu(id); 1944 alg_region->base = be32_to_cpu(base); 1945 1946 list_add_tail(&alg_region->list, &dsp->alg_regions); 1947 1948 if (dsp->fw_ver > 0) 1949 wm_adsp_ctl_fixup_base(dsp, alg_region); 1950 1951 return alg_region; 1952 } 1953 1954 static void wm_adsp_free_alg_regions(struct wm_adsp *dsp) 1955 { 1956 struct wm_adsp_alg_region *alg_region; 1957 1958 while (!list_empty(&dsp->alg_regions)) { 1959 alg_region = list_first_entry(&dsp->alg_regions, 1960 struct wm_adsp_alg_region, 1961 list); 1962 list_del(&alg_region->list); 1963 kfree(alg_region); 1964 } 1965 } 1966 1967 static int wm_adsp1_setup_algs(struct wm_adsp *dsp) 1968 { 1969 struct wmfw_adsp1_id_hdr adsp1_id; 1970 struct wmfw_adsp1_alg_hdr *adsp1_alg; 1971 struct wm_adsp_alg_region *alg_region; 1972 const struct wm_adsp_region *mem; 1973 unsigned int pos, len; 1974 size_t n_algs; 1975 int i, ret; 1976 1977 mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM); 1978 if (WARN_ON(!mem)) 1979 return -EINVAL; 1980 1981 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id, 1982 sizeof(adsp1_id)); 1983 if (ret != 0) { 1984 adsp_err(dsp, "Failed to read algorithm info: %d\n", 1985 ret); 1986 return ret; 1987 } 1988 1989 n_algs = be32_to_cpu(adsp1_id.n_algs); 1990 dsp->fw_id = be32_to_cpu(adsp1_id.fw.id); 1991 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 1992 dsp->fw_id, 1993 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, 1994 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, 1995 be32_to_cpu(adsp1_id.fw.ver) & 0xff, 1996 n_algs); 1997 1998 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, 1999 adsp1_id.fw.id, adsp1_id.zm); 2000 if (IS_ERR(alg_region)) 2001 return PTR_ERR(alg_region); 2002 2003 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, 2004 adsp1_id.fw.id, adsp1_id.dm); 2005 if (IS_ERR(alg_region)) 2006 return PTR_ERR(alg_region); 2007 2008 /* Calculate offset and length in DSP words */ 2009 pos = sizeof(adsp1_id) / sizeof(u32); 2010 len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32); 2011 2012 adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len); 2013 if (IS_ERR(adsp1_alg)) 2014 return PTR_ERR(adsp1_alg); 2015 2016 for (i = 0; i < n_algs; i++) { 2017 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", 2018 i, be32_to_cpu(adsp1_alg[i].alg.id), 2019 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, 2020 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, 2021 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, 2022 be32_to_cpu(adsp1_alg[i].dm), 2023 be32_to_cpu(adsp1_alg[i].zm)); 2024 2025 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, 2026 adsp1_alg[i].alg.id, 2027 adsp1_alg[i].dm); 2028 if (IS_ERR(alg_region)) { 2029 ret = PTR_ERR(alg_region); 2030 goto out; 2031 } 2032 if (dsp->fw_ver == 0) { 2033 if (i + 1 < n_algs) { 2034 len = be32_to_cpu(adsp1_alg[i + 1].dm); 2035 len -= be32_to_cpu(adsp1_alg[i].dm); 2036 len *= 4; 2037 wm_adsp_create_control(dsp, alg_region, 0, 2038 len, NULL, 0, 0, 2039 SNDRV_CTL_ELEM_TYPE_BYTES); 2040 } else { 2041 adsp_warn(dsp, "Missing length info for region DM with ID %x\n", 2042 be32_to_cpu(adsp1_alg[i].alg.id)); 2043 } 2044 } 2045 2046 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, 2047 adsp1_alg[i].alg.id, 2048 adsp1_alg[i].zm); 2049 if (IS_ERR(alg_region)) { 2050 ret = PTR_ERR(alg_region); 2051 goto out; 2052 } 2053 if (dsp->fw_ver == 0) { 2054 if (i + 1 < n_algs) { 2055 len = be32_to_cpu(adsp1_alg[i + 1].zm); 2056 len -= be32_to_cpu(adsp1_alg[i].zm); 2057 len *= 4; 2058 wm_adsp_create_control(dsp, alg_region, 0, 2059 len, NULL, 0, 0, 2060 SNDRV_CTL_ELEM_TYPE_BYTES); 2061 } else { 2062 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 2063 be32_to_cpu(adsp1_alg[i].alg.id)); 2064 } 2065 } 2066 } 2067 2068 out: 2069 kfree(adsp1_alg); 2070 return ret; 2071 } 2072 2073 static int wm_adsp2_setup_algs(struct wm_adsp *dsp) 2074 { 2075 struct wmfw_adsp2_id_hdr adsp2_id; 2076 struct wmfw_adsp2_alg_hdr *adsp2_alg; 2077 struct wm_adsp_alg_region *alg_region; 2078 const struct wm_adsp_region *mem; 2079 unsigned int pos, len; 2080 size_t n_algs; 2081 int i, ret; 2082 2083 mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM); 2084 if (WARN_ON(!mem)) 2085 return -EINVAL; 2086 2087 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id, 2088 sizeof(adsp2_id)); 2089 if (ret != 0) { 2090 adsp_err(dsp, "Failed to read algorithm info: %d\n", 2091 ret); 2092 return ret; 2093 } 2094 2095 n_algs = be32_to_cpu(adsp2_id.n_algs); 2096 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); 2097 dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver); 2098 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 2099 dsp->fw_id, 2100 (dsp->fw_id_version & 0xff0000) >> 16, 2101 (dsp->fw_id_version & 0xff00) >> 8, 2102 dsp->fw_id_version & 0xff, 2103 n_algs); 2104 2105 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, 2106 adsp2_id.fw.id, adsp2_id.xm); 2107 if (IS_ERR(alg_region)) 2108 return PTR_ERR(alg_region); 2109 2110 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, 2111 adsp2_id.fw.id, adsp2_id.ym); 2112 if (IS_ERR(alg_region)) 2113 return PTR_ERR(alg_region); 2114 2115 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, 2116 adsp2_id.fw.id, adsp2_id.zm); 2117 if (IS_ERR(alg_region)) 2118 return PTR_ERR(alg_region); 2119 2120 /* Calculate offset and length in DSP words */ 2121 pos = sizeof(adsp2_id) / sizeof(u32); 2122 len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32); 2123 2124 adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len); 2125 if (IS_ERR(adsp2_alg)) 2126 return PTR_ERR(adsp2_alg); 2127 2128 for (i = 0; i < n_algs; i++) { 2129 adsp_info(dsp, 2130 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", 2131 i, be32_to_cpu(adsp2_alg[i].alg.id), 2132 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, 2133 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, 2134 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, 2135 be32_to_cpu(adsp2_alg[i].xm), 2136 be32_to_cpu(adsp2_alg[i].ym), 2137 be32_to_cpu(adsp2_alg[i].zm)); 2138 2139 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, 2140 adsp2_alg[i].alg.id, 2141 adsp2_alg[i].xm); 2142 if (IS_ERR(alg_region)) { 2143 ret = PTR_ERR(alg_region); 2144 goto out; 2145 } 2146 if (dsp->fw_ver == 0) { 2147 if (i + 1 < n_algs) { 2148 len = be32_to_cpu(adsp2_alg[i + 1].xm); 2149 len -= be32_to_cpu(adsp2_alg[i].xm); 2150 len *= 4; 2151 wm_adsp_create_control(dsp, alg_region, 0, 2152 len, NULL, 0, 0, 2153 SNDRV_CTL_ELEM_TYPE_BYTES); 2154 } else { 2155 adsp_warn(dsp, "Missing length info for region XM with ID %x\n", 2156 be32_to_cpu(adsp2_alg[i].alg.id)); 2157 } 2158 } 2159 2160 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, 2161 adsp2_alg[i].alg.id, 2162 adsp2_alg[i].ym); 2163 if (IS_ERR(alg_region)) { 2164 ret = PTR_ERR(alg_region); 2165 goto out; 2166 } 2167 if (dsp->fw_ver == 0) { 2168 if (i + 1 < n_algs) { 2169 len = be32_to_cpu(adsp2_alg[i + 1].ym); 2170 len -= be32_to_cpu(adsp2_alg[i].ym); 2171 len *= 4; 2172 wm_adsp_create_control(dsp, alg_region, 0, 2173 len, NULL, 0, 0, 2174 SNDRV_CTL_ELEM_TYPE_BYTES); 2175 } else { 2176 adsp_warn(dsp, "Missing length info for region YM with ID %x\n", 2177 be32_to_cpu(adsp2_alg[i].alg.id)); 2178 } 2179 } 2180 2181 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, 2182 adsp2_alg[i].alg.id, 2183 adsp2_alg[i].zm); 2184 if (IS_ERR(alg_region)) { 2185 ret = PTR_ERR(alg_region); 2186 goto out; 2187 } 2188 if (dsp->fw_ver == 0) { 2189 if (i + 1 < n_algs) { 2190 len = be32_to_cpu(adsp2_alg[i + 1].zm); 2191 len -= be32_to_cpu(adsp2_alg[i].zm); 2192 len *= 4; 2193 wm_adsp_create_control(dsp, alg_region, 0, 2194 len, NULL, 0, 0, 2195 SNDRV_CTL_ELEM_TYPE_BYTES); 2196 } else { 2197 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 2198 be32_to_cpu(adsp2_alg[i].alg.id)); 2199 } 2200 } 2201 } 2202 2203 out: 2204 kfree(adsp2_alg); 2205 return ret; 2206 } 2207 2208 static int wm_adsp_load_coeff(struct wm_adsp *dsp) 2209 { 2210 LIST_HEAD(buf_list); 2211 struct regmap *regmap = dsp->regmap; 2212 struct wmfw_coeff_hdr *hdr; 2213 struct wmfw_coeff_item *blk; 2214 const struct firmware *firmware; 2215 const struct wm_adsp_region *mem; 2216 struct wm_adsp_alg_region *alg_region; 2217 const char *region_name; 2218 int ret, pos, blocks, type, offset, reg; 2219 char *file; 2220 struct wm_adsp_buf *buf; 2221 2222 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 2223 if (file == NULL) 2224 return -ENOMEM; 2225 2226 snprintf(file, PAGE_SIZE, "%s-%s-%s.bin", dsp->part, dsp->fwf_name, 2227 wm_adsp_fw[dsp->fw].file); 2228 file[PAGE_SIZE - 1] = '\0'; 2229 2230 ret = request_firmware(&firmware, file, dsp->dev); 2231 if (ret != 0) { 2232 adsp_warn(dsp, "Failed to request '%s'\n", file); 2233 ret = 0; 2234 goto out; 2235 } 2236 ret = -EINVAL; 2237 2238 if (sizeof(*hdr) >= firmware->size) { 2239 adsp_err(dsp, "%s: file too short, %zu bytes\n", 2240 file, firmware->size); 2241 goto out_fw; 2242 } 2243 2244 hdr = (void *)&firmware->data[0]; 2245 if (memcmp(hdr->magic, "WMDR", 4) != 0) { 2246 adsp_err(dsp, "%s: invalid magic\n", file); 2247 goto out_fw; 2248 } 2249 2250 switch (be32_to_cpu(hdr->rev) & 0xff) { 2251 case 1: 2252 break; 2253 default: 2254 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n", 2255 file, be32_to_cpu(hdr->rev) & 0xff); 2256 ret = -EINVAL; 2257 goto out_fw; 2258 } 2259 2260 adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, 2261 (le32_to_cpu(hdr->ver) >> 16) & 0xff, 2262 (le32_to_cpu(hdr->ver) >> 8) & 0xff, 2263 le32_to_cpu(hdr->ver) & 0xff); 2264 2265 pos = le32_to_cpu(hdr->len); 2266 2267 blocks = 0; 2268 while (pos < firmware->size && 2269 sizeof(*blk) < firmware->size - pos) { 2270 blk = (void *)(&firmware->data[pos]); 2271 2272 type = le16_to_cpu(blk->type); 2273 offset = le16_to_cpu(blk->offset); 2274 2275 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", 2276 file, blocks, le32_to_cpu(blk->id), 2277 (le32_to_cpu(blk->ver) >> 16) & 0xff, 2278 (le32_to_cpu(blk->ver) >> 8) & 0xff, 2279 le32_to_cpu(blk->ver) & 0xff); 2280 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", 2281 file, blocks, le32_to_cpu(blk->len), offset, type); 2282 2283 reg = 0; 2284 region_name = "Unknown"; 2285 switch (type) { 2286 case (WMFW_NAME_TEXT << 8): 2287 case (WMFW_INFO_TEXT << 8): 2288 break; 2289 case (WMFW_ABSOLUTE << 8): 2290 /* 2291 * Old files may use this for global 2292 * coefficients. 2293 */ 2294 if (le32_to_cpu(blk->id) == dsp->fw_id && 2295 offset == 0) { 2296 region_name = "global coefficients"; 2297 mem = wm_adsp_find_region(dsp, type); 2298 if (!mem) { 2299 adsp_err(dsp, "No ZM\n"); 2300 break; 2301 } 2302 reg = wm_adsp_region_to_reg(mem, 0); 2303 2304 } else { 2305 region_name = "register"; 2306 reg = offset; 2307 } 2308 break; 2309 2310 case WMFW_ADSP1_DM: 2311 case WMFW_ADSP1_ZM: 2312 case WMFW_ADSP2_XM: 2313 case WMFW_ADSP2_YM: 2314 adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", 2315 file, blocks, le32_to_cpu(blk->len), 2316 type, le32_to_cpu(blk->id)); 2317 2318 mem = wm_adsp_find_region(dsp, type); 2319 if (!mem) { 2320 adsp_err(dsp, "No base for region %x\n", type); 2321 break; 2322 } 2323 2324 alg_region = wm_adsp_find_alg_region(dsp, type, 2325 le32_to_cpu(blk->id)); 2326 if (alg_region) { 2327 reg = alg_region->base; 2328 reg = wm_adsp_region_to_reg(mem, reg); 2329 reg += offset; 2330 } else { 2331 adsp_err(dsp, "No %x for algorithm %x\n", 2332 type, le32_to_cpu(blk->id)); 2333 } 2334 break; 2335 2336 default: 2337 adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n", 2338 file, blocks, type, pos); 2339 break; 2340 } 2341 2342 if (reg) { 2343 if (le32_to_cpu(blk->len) > 2344 firmware->size - pos - sizeof(*blk)) { 2345 adsp_err(dsp, 2346 "%s.%d: %s region len %d bytes exceeds file length %zu\n", 2347 file, blocks, region_name, 2348 le32_to_cpu(blk->len), 2349 firmware->size); 2350 ret = -EINVAL; 2351 goto out_fw; 2352 } 2353 2354 buf = wm_adsp_buf_alloc(blk->data, 2355 le32_to_cpu(blk->len), 2356 &buf_list); 2357 if (!buf) { 2358 adsp_err(dsp, "Out of memory\n"); 2359 ret = -ENOMEM; 2360 goto out_fw; 2361 } 2362 2363 adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", 2364 file, blocks, le32_to_cpu(blk->len), 2365 reg); 2366 ret = regmap_raw_write_async(regmap, reg, buf->buf, 2367 le32_to_cpu(blk->len)); 2368 if (ret != 0) { 2369 adsp_err(dsp, 2370 "%s.%d: Failed to write to %x in %s: %d\n", 2371 file, blocks, reg, region_name, ret); 2372 } 2373 } 2374 2375 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03; 2376 blocks++; 2377 } 2378 2379 ret = regmap_async_complete(regmap); 2380 if (ret != 0) 2381 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 2382 2383 if (pos > firmware->size) 2384 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 2385 file, blocks, pos - firmware->size); 2386 2387 wm_adsp_debugfs_save_binname(dsp, file); 2388 2389 out_fw: 2390 regmap_async_complete(regmap); 2391 release_firmware(firmware); 2392 wm_adsp_buf_free(&buf_list); 2393 out: 2394 kfree(file); 2395 return ret; 2396 } 2397 2398 static int wm_adsp_create_name(struct wm_adsp *dsp) 2399 { 2400 char *p; 2401 2402 if (!dsp->name) { 2403 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d", 2404 dsp->num); 2405 if (!dsp->name) 2406 return -ENOMEM; 2407 } 2408 2409 if (!dsp->fwf_name) { 2410 p = devm_kstrdup(dsp->dev, dsp->name, GFP_KERNEL); 2411 if (!p) 2412 return -ENOMEM; 2413 2414 dsp->fwf_name = p; 2415 for (; *p != 0; ++p) 2416 *p = tolower(*p); 2417 } 2418 2419 return 0; 2420 } 2421 2422 int wm_adsp1_init(struct wm_adsp *dsp) 2423 { 2424 int ret; 2425 2426 ret = wm_adsp_create_name(dsp); 2427 if (ret) 2428 return ret; 2429 2430 INIT_LIST_HEAD(&dsp->alg_regions); 2431 2432 mutex_init(&dsp->pwr_lock); 2433 2434 return 0; 2435 } 2436 EXPORT_SYMBOL_GPL(wm_adsp1_init); 2437 2438 int wm_adsp1_event(struct snd_soc_dapm_widget *w, 2439 struct snd_kcontrol *kcontrol, 2440 int event) 2441 { 2442 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2443 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2444 struct wm_adsp *dsp = &dsps[w->shift]; 2445 struct wm_coeff_ctl *ctl; 2446 int ret; 2447 unsigned int val; 2448 2449 dsp->component = component; 2450 2451 mutex_lock(&dsp->pwr_lock); 2452 2453 switch (event) { 2454 case SND_SOC_DAPM_POST_PMU: 2455 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2456 ADSP1_SYS_ENA, ADSP1_SYS_ENA); 2457 2458 /* 2459 * For simplicity set the DSP clock rate to be the 2460 * SYSCLK rate rather than making it configurable. 2461 */ 2462 if (dsp->sysclk_reg) { 2463 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); 2464 if (ret != 0) { 2465 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", 2466 ret); 2467 goto err_mutex; 2468 } 2469 2470 val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift; 2471 2472 ret = regmap_update_bits(dsp->regmap, 2473 dsp->base + ADSP1_CONTROL_31, 2474 ADSP1_CLK_SEL_MASK, val); 2475 if (ret != 0) { 2476 adsp_err(dsp, "Failed to set clock rate: %d\n", 2477 ret); 2478 goto err_mutex; 2479 } 2480 } 2481 2482 ret = wm_adsp_load(dsp); 2483 if (ret != 0) 2484 goto err_ena; 2485 2486 ret = wm_adsp1_setup_algs(dsp); 2487 if (ret != 0) 2488 goto err_ena; 2489 2490 ret = wm_adsp_load_coeff(dsp); 2491 if (ret != 0) 2492 goto err_ena; 2493 2494 /* Initialize caches for enabled and unset controls */ 2495 ret = wm_coeff_init_control_caches(dsp); 2496 if (ret != 0) 2497 goto err_ena; 2498 2499 /* Sync set controls */ 2500 ret = wm_coeff_sync_controls(dsp); 2501 if (ret != 0) 2502 goto err_ena; 2503 2504 dsp->booted = true; 2505 2506 /* Start the core running */ 2507 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2508 ADSP1_CORE_ENA | ADSP1_START, 2509 ADSP1_CORE_ENA | ADSP1_START); 2510 2511 dsp->running = true; 2512 break; 2513 2514 case SND_SOC_DAPM_PRE_PMD: 2515 dsp->running = false; 2516 dsp->booted = false; 2517 2518 /* Halt the core */ 2519 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2520 ADSP1_CORE_ENA | ADSP1_START, 0); 2521 2522 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, 2523 ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); 2524 2525 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2526 ADSP1_SYS_ENA, 0); 2527 2528 list_for_each_entry(ctl, &dsp->ctl_list, list) 2529 ctl->enabled = 0; 2530 2531 2532 wm_adsp_free_alg_regions(dsp); 2533 break; 2534 2535 default: 2536 break; 2537 } 2538 2539 mutex_unlock(&dsp->pwr_lock); 2540 2541 return 0; 2542 2543 err_ena: 2544 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2545 ADSP1_SYS_ENA, 0); 2546 err_mutex: 2547 mutex_unlock(&dsp->pwr_lock); 2548 2549 return ret; 2550 } 2551 EXPORT_SYMBOL_GPL(wm_adsp1_event); 2552 2553 static int wm_adsp2_ena(struct wm_adsp *dsp) 2554 { 2555 unsigned int val; 2556 int ret, count; 2557 2558 switch (dsp->rev) { 2559 case 0: 2560 ret = regmap_update_bits_async(dsp->regmap, 2561 dsp->base + ADSP2_CONTROL, 2562 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 2563 if (ret != 0) 2564 return ret; 2565 break; 2566 default: 2567 break; 2568 } 2569 2570 /* Wait for the RAM to start, should be near instantaneous */ 2571 for (count = 0; count < 10; ++count) { 2572 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val); 2573 if (ret != 0) 2574 return ret; 2575 2576 if (val & ADSP2_RAM_RDY) 2577 break; 2578 2579 usleep_range(250, 500); 2580 } 2581 2582 if (!(val & ADSP2_RAM_RDY)) { 2583 adsp_err(dsp, "Failed to start DSP RAM\n"); 2584 return -EBUSY; 2585 } 2586 2587 adsp_dbg(dsp, "RAM ready after %d polls\n", count); 2588 2589 return 0; 2590 } 2591 2592 static void wm_adsp2_boot_work(struct work_struct *work) 2593 { 2594 struct wm_adsp *dsp = container_of(work, 2595 struct wm_adsp, 2596 boot_work); 2597 int ret; 2598 2599 mutex_lock(&dsp->pwr_lock); 2600 2601 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2602 ADSP2_MEM_ENA, ADSP2_MEM_ENA); 2603 if (ret != 0) 2604 goto err_mutex; 2605 2606 ret = wm_adsp2_ena(dsp); 2607 if (ret != 0) 2608 goto err_mem; 2609 2610 ret = wm_adsp_load(dsp); 2611 if (ret != 0) 2612 goto err_ena; 2613 2614 ret = wm_adsp2_setup_algs(dsp); 2615 if (ret != 0) 2616 goto err_ena; 2617 2618 ret = wm_adsp_load_coeff(dsp); 2619 if (ret != 0) 2620 goto err_ena; 2621 2622 /* Initialize caches for enabled and unset controls */ 2623 ret = wm_coeff_init_control_caches(dsp); 2624 if (ret != 0) 2625 goto err_ena; 2626 2627 switch (dsp->rev) { 2628 case 0: 2629 /* Turn DSP back off until we are ready to run */ 2630 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2631 ADSP2_SYS_ENA, 0); 2632 if (ret != 0) 2633 goto err_ena; 2634 break; 2635 default: 2636 break; 2637 } 2638 2639 dsp->booted = true; 2640 2641 mutex_unlock(&dsp->pwr_lock); 2642 2643 return; 2644 2645 err_ena: 2646 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2647 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2648 err_mem: 2649 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2650 ADSP2_MEM_ENA, 0); 2651 err_mutex: 2652 mutex_unlock(&dsp->pwr_lock); 2653 } 2654 2655 static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq) 2656 { 2657 int ret; 2658 2659 switch (dsp->rev) { 2660 case 0: 2661 ret = regmap_update_bits_async(dsp->regmap, 2662 dsp->base + ADSP2_CLOCKING, 2663 ADSP2_CLK_SEL_MASK, 2664 freq << ADSP2_CLK_SEL_SHIFT); 2665 if (ret) { 2666 adsp_err(dsp, "Failed to set clock rate: %d\n", ret); 2667 return; 2668 } 2669 break; 2670 default: 2671 /* clock is handled by parent codec driver */ 2672 break; 2673 } 2674 } 2675 2676 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, 2677 struct snd_ctl_elem_value *ucontrol) 2678 { 2679 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2680 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2681 struct soc_mixer_control *mc = 2682 (struct soc_mixer_control *)kcontrol->private_value; 2683 struct wm_adsp *dsp = &dsps[mc->shift - 1]; 2684 2685 ucontrol->value.integer.value[0] = dsp->preloaded; 2686 2687 return 0; 2688 } 2689 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get); 2690 2691 int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, 2692 struct snd_ctl_elem_value *ucontrol) 2693 { 2694 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2695 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2696 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 2697 struct soc_mixer_control *mc = 2698 (struct soc_mixer_control *)kcontrol->private_value; 2699 struct wm_adsp *dsp = &dsps[mc->shift - 1]; 2700 char preload[32]; 2701 2702 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); 2703 2704 dsp->preloaded = ucontrol->value.integer.value[0]; 2705 2706 if (ucontrol->value.integer.value[0]) 2707 snd_soc_component_force_enable_pin(component, preload); 2708 else 2709 snd_soc_component_disable_pin(component, preload); 2710 2711 snd_soc_dapm_sync(dapm); 2712 2713 flush_work(&dsp->boot_work); 2714 2715 return 0; 2716 } 2717 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); 2718 2719 static void wm_adsp_stop_watchdog(struct wm_adsp *dsp) 2720 { 2721 switch (dsp->rev) { 2722 case 0: 2723 case 1: 2724 return; 2725 default: 2726 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG, 2727 ADSP2_WDT_ENA_MASK, 0); 2728 } 2729 } 2730 2731 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 2732 struct snd_kcontrol *kcontrol, int event, 2733 unsigned int freq) 2734 { 2735 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2736 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2737 struct wm_adsp *dsp = &dsps[w->shift]; 2738 struct wm_coeff_ctl *ctl; 2739 2740 switch (event) { 2741 case SND_SOC_DAPM_PRE_PMU: 2742 wm_adsp2_set_dspclk(dsp, freq); 2743 queue_work(system_unbound_wq, &dsp->boot_work); 2744 break; 2745 case SND_SOC_DAPM_PRE_PMD: 2746 mutex_lock(&dsp->pwr_lock); 2747 2748 wm_adsp_debugfs_clear(dsp); 2749 2750 dsp->fw_id = 0; 2751 dsp->fw_id_version = 0; 2752 2753 dsp->booted = false; 2754 2755 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2756 ADSP2_MEM_ENA, 0); 2757 2758 list_for_each_entry(ctl, &dsp->ctl_list, list) 2759 ctl->enabled = 0; 2760 2761 wm_adsp_free_alg_regions(dsp); 2762 2763 mutex_unlock(&dsp->pwr_lock); 2764 2765 adsp_dbg(dsp, "Shutdown complete\n"); 2766 break; 2767 default: 2768 break; 2769 } 2770 2771 return 0; 2772 } 2773 EXPORT_SYMBOL_GPL(wm_adsp2_early_event); 2774 2775 int wm_adsp2_event(struct snd_soc_dapm_widget *w, 2776 struct snd_kcontrol *kcontrol, int event) 2777 { 2778 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2779 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2780 struct wm_adsp *dsp = &dsps[w->shift]; 2781 int ret; 2782 2783 switch (event) { 2784 case SND_SOC_DAPM_POST_PMU: 2785 flush_work(&dsp->boot_work); 2786 2787 mutex_lock(&dsp->pwr_lock); 2788 2789 if (!dsp->booted) { 2790 ret = -EIO; 2791 goto err; 2792 } 2793 2794 ret = wm_adsp2_ena(dsp); 2795 if (ret != 0) 2796 goto err; 2797 2798 /* Sync set controls */ 2799 ret = wm_coeff_sync_controls(dsp); 2800 if (ret != 0) 2801 goto err; 2802 2803 wm_adsp2_lock(dsp, dsp->lock_regions); 2804 2805 ret = regmap_update_bits(dsp->regmap, 2806 dsp->base + ADSP2_CONTROL, 2807 ADSP2_CORE_ENA | ADSP2_START, 2808 ADSP2_CORE_ENA | ADSP2_START); 2809 if (ret != 0) 2810 goto err; 2811 2812 if (wm_adsp_fw[dsp->fw].num_caps != 0) { 2813 ret = wm_adsp_buffer_init(dsp); 2814 if (ret < 0) 2815 goto err; 2816 } 2817 2818 dsp->running = true; 2819 2820 mutex_unlock(&dsp->pwr_lock); 2821 2822 break; 2823 2824 case SND_SOC_DAPM_PRE_PMD: 2825 /* Tell the firmware to cleanup */ 2826 wm_adsp_signal_event_controls(dsp, WM_ADSP_FW_EVENT_SHUTDOWN); 2827 2828 wm_adsp_stop_watchdog(dsp); 2829 2830 /* Log firmware state, it can be useful for analysis */ 2831 switch (dsp->rev) { 2832 case 0: 2833 wm_adsp2_show_fw_status(dsp); 2834 break; 2835 default: 2836 wm_adsp2v2_show_fw_status(dsp); 2837 break; 2838 } 2839 2840 mutex_lock(&dsp->pwr_lock); 2841 2842 dsp->running = false; 2843 2844 regmap_update_bits(dsp->regmap, 2845 dsp->base + ADSP2_CONTROL, 2846 ADSP2_CORE_ENA | ADSP2_START, 0); 2847 2848 /* Make sure DMAs are quiesced */ 2849 switch (dsp->rev) { 2850 case 0: 2851 regmap_write(dsp->regmap, 2852 dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2853 regmap_write(dsp->regmap, 2854 dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2855 regmap_write(dsp->regmap, 2856 dsp->base + ADSP2_WDMA_CONFIG_2, 0); 2857 2858 regmap_update_bits(dsp->regmap, 2859 dsp->base + ADSP2_CONTROL, 2860 ADSP2_SYS_ENA, 0); 2861 break; 2862 default: 2863 regmap_write(dsp->regmap, 2864 dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2865 regmap_write(dsp->regmap, 2866 dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2867 regmap_write(dsp->regmap, 2868 dsp->base + ADSP2V2_WDMA_CONFIG_2, 0); 2869 break; 2870 } 2871 2872 if (wm_adsp_fw[dsp->fw].num_caps != 0) 2873 wm_adsp_buffer_free(dsp); 2874 2875 mutex_unlock(&dsp->pwr_lock); 2876 2877 adsp_dbg(dsp, "Execution stopped\n"); 2878 break; 2879 2880 default: 2881 break; 2882 } 2883 2884 return 0; 2885 err: 2886 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2887 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2888 mutex_unlock(&dsp->pwr_lock); 2889 return ret; 2890 } 2891 EXPORT_SYMBOL_GPL(wm_adsp2_event); 2892 2893 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component) 2894 { 2895 char preload[32]; 2896 2897 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); 2898 snd_soc_component_disable_pin(component, preload); 2899 2900 wm_adsp2_init_debugfs(dsp, component); 2901 2902 dsp->component = component; 2903 2904 return 0; 2905 } 2906 EXPORT_SYMBOL_GPL(wm_adsp2_component_probe); 2907 2908 int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component) 2909 { 2910 wm_adsp2_cleanup_debugfs(dsp); 2911 2912 return 0; 2913 } 2914 EXPORT_SYMBOL_GPL(wm_adsp2_component_remove); 2915 2916 int wm_adsp2_init(struct wm_adsp *dsp) 2917 { 2918 int ret; 2919 2920 ret = wm_adsp_create_name(dsp); 2921 if (ret) 2922 return ret; 2923 2924 switch (dsp->rev) { 2925 case 0: 2926 /* 2927 * Disable the DSP memory by default when in reset for a small 2928 * power saving. 2929 */ 2930 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2931 ADSP2_MEM_ENA, 0); 2932 if (ret) { 2933 adsp_err(dsp, 2934 "Failed to clear memory retention: %d\n", ret); 2935 return ret; 2936 } 2937 break; 2938 default: 2939 break; 2940 } 2941 2942 INIT_LIST_HEAD(&dsp->alg_regions); 2943 INIT_LIST_HEAD(&dsp->ctl_list); 2944 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); 2945 2946 mutex_init(&dsp->pwr_lock); 2947 2948 return 0; 2949 } 2950 EXPORT_SYMBOL_GPL(wm_adsp2_init); 2951 2952 void wm_adsp2_remove(struct wm_adsp *dsp) 2953 { 2954 struct wm_coeff_ctl *ctl; 2955 2956 while (!list_empty(&dsp->ctl_list)) { 2957 ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl, 2958 list); 2959 list_del(&ctl->list); 2960 wm_adsp_free_ctl_blk(ctl); 2961 } 2962 } 2963 EXPORT_SYMBOL_GPL(wm_adsp2_remove); 2964 2965 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr) 2966 { 2967 return compr->buf != NULL; 2968 } 2969 2970 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr) 2971 { 2972 /* 2973 * Note this will be more complex once each DSP can support multiple 2974 * streams 2975 */ 2976 if (!compr->dsp->buffer) 2977 return -EINVAL; 2978 2979 compr->buf = compr->dsp->buffer; 2980 compr->buf->compr = compr; 2981 2982 return 0; 2983 } 2984 2985 static void wm_adsp_compr_detach(struct wm_adsp_compr *compr) 2986 { 2987 if (!compr) 2988 return; 2989 2990 /* Wake the poll so it can see buffer is no longer attached */ 2991 if (compr->stream) 2992 snd_compr_fragment_elapsed(compr->stream); 2993 2994 if (wm_adsp_compr_attached(compr)) { 2995 compr->buf->compr = NULL; 2996 compr->buf = NULL; 2997 } 2998 } 2999 3000 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream) 3001 { 3002 struct wm_adsp_compr *compr; 3003 int ret = 0; 3004 3005 mutex_lock(&dsp->pwr_lock); 3006 3007 if (wm_adsp_fw[dsp->fw].num_caps == 0) { 3008 adsp_err(dsp, "Firmware does not support compressed API\n"); 3009 ret = -ENXIO; 3010 goto out; 3011 } 3012 3013 if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) { 3014 adsp_err(dsp, "Firmware does not support stream direction\n"); 3015 ret = -EINVAL; 3016 goto out; 3017 } 3018 3019 if (dsp->compr) { 3020 /* It is expect this limitation will be removed in future */ 3021 adsp_err(dsp, "Only a single stream supported per DSP\n"); 3022 ret = -EBUSY; 3023 goto out; 3024 } 3025 3026 compr = kzalloc(sizeof(*compr), GFP_KERNEL); 3027 if (!compr) { 3028 ret = -ENOMEM; 3029 goto out; 3030 } 3031 3032 compr->dsp = dsp; 3033 compr->stream = stream; 3034 3035 dsp->compr = compr; 3036 3037 stream->runtime->private_data = compr; 3038 3039 out: 3040 mutex_unlock(&dsp->pwr_lock); 3041 3042 return ret; 3043 } 3044 EXPORT_SYMBOL_GPL(wm_adsp_compr_open); 3045 3046 int wm_adsp_compr_free(struct snd_compr_stream *stream) 3047 { 3048 struct wm_adsp_compr *compr = stream->runtime->private_data; 3049 struct wm_adsp *dsp = compr->dsp; 3050 3051 mutex_lock(&dsp->pwr_lock); 3052 3053 wm_adsp_compr_detach(compr); 3054 dsp->compr = NULL; 3055 3056 kfree(compr->raw_buf); 3057 kfree(compr); 3058 3059 mutex_unlock(&dsp->pwr_lock); 3060 3061 return 0; 3062 } 3063 EXPORT_SYMBOL_GPL(wm_adsp_compr_free); 3064 3065 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream, 3066 struct snd_compr_params *params) 3067 { 3068 struct wm_adsp_compr *compr = stream->runtime->private_data; 3069 struct wm_adsp *dsp = compr->dsp; 3070 const struct wm_adsp_fw_caps *caps; 3071 const struct snd_codec_desc *desc; 3072 int i, j; 3073 3074 if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE || 3075 params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE || 3076 params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS || 3077 params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS || 3078 params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) { 3079 adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n", 3080 params->buffer.fragment_size, 3081 params->buffer.fragments); 3082 3083 return -EINVAL; 3084 } 3085 3086 for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) { 3087 caps = &wm_adsp_fw[dsp->fw].caps[i]; 3088 desc = &caps->desc; 3089 3090 if (caps->id != params->codec.id) 3091 continue; 3092 3093 if (stream->direction == SND_COMPRESS_PLAYBACK) { 3094 if (desc->max_ch < params->codec.ch_out) 3095 continue; 3096 } else { 3097 if (desc->max_ch < params->codec.ch_in) 3098 continue; 3099 } 3100 3101 if (!(desc->formats & (1 << params->codec.format))) 3102 continue; 3103 3104 for (j = 0; j < desc->num_sample_rates; ++j) 3105 if (desc->sample_rates[j] == params->codec.sample_rate) 3106 return 0; 3107 } 3108 3109 adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n", 3110 params->codec.id, params->codec.ch_in, params->codec.ch_out, 3111 params->codec.sample_rate, params->codec.format); 3112 return -EINVAL; 3113 } 3114 3115 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr) 3116 { 3117 return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE; 3118 } 3119 3120 int wm_adsp_compr_set_params(struct snd_compr_stream *stream, 3121 struct snd_compr_params *params) 3122 { 3123 struct wm_adsp_compr *compr = stream->runtime->private_data; 3124 unsigned int size; 3125 int ret; 3126 3127 ret = wm_adsp_compr_check_params(stream, params); 3128 if (ret) 3129 return ret; 3130 3131 compr->size = params->buffer; 3132 3133 adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n", 3134 compr->size.fragment_size, compr->size.fragments); 3135 3136 size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf); 3137 compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); 3138 if (!compr->raw_buf) 3139 return -ENOMEM; 3140 3141 compr->sample_rate = params->codec.sample_rate; 3142 3143 return 0; 3144 } 3145 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); 3146 3147 int wm_adsp_compr_get_caps(struct snd_compr_stream *stream, 3148 struct snd_compr_caps *caps) 3149 { 3150 struct wm_adsp_compr *compr = stream->runtime->private_data; 3151 int fw = compr->dsp->fw; 3152 int i; 3153 3154 if (wm_adsp_fw[fw].caps) { 3155 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++) 3156 caps->codecs[i] = wm_adsp_fw[fw].caps[i].id; 3157 3158 caps->num_codecs = i; 3159 caps->direction = wm_adsp_fw[fw].compr_direction; 3160 3161 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE; 3162 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE; 3163 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS; 3164 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS; 3165 } 3166 3167 return 0; 3168 } 3169 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); 3170 3171 static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, 3172 unsigned int mem_addr, 3173 unsigned int num_words, u32 *data) 3174 { 3175 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 3176 unsigned int i, reg; 3177 int ret; 3178 3179 if (!mem) 3180 return -EINVAL; 3181 3182 reg = wm_adsp_region_to_reg(mem, mem_addr); 3183 3184 ret = regmap_raw_read(dsp->regmap, reg, data, 3185 sizeof(*data) * num_words); 3186 if (ret < 0) 3187 return ret; 3188 3189 for (i = 0; i < num_words; ++i) 3190 data[i] = be32_to_cpu(data[i]) & 0x00ffffffu; 3191 3192 return 0; 3193 } 3194 3195 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type, 3196 unsigned int mem_addr, u32 *data) 3197 { 3198 return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data); 3199 } 3200 3201 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, 3202 unsigned int mem_addr, u32 data) 3203 { 3204 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 3205 unsigned int reg; 3206 3207 if (!mem) 3208 return -EINVAL; 3209 3210 reg = wm_adsp_region_to_reg(mem, mem_addr); 3211 3212 data = cpu_to_be32(data & 0x00ffffffu); 3213 3214 return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data)); 3215 } 3216 3217 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, 3218 unsigned int field_offset, u32 *data) 3219 { 3220 return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM, 3221 buf->host_buf_ptr + field_offset, data); 3222 } 3223 3224 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, 3225 unsigned int field_offset, u32 data) 3226 { 3227 return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM, 3228 buf->host_buf_ptr + field_offset, data); 3229 } 3230 3231 static int wm_adsp_legacy_host_buf_addr(struct wm_adsp_compr_buf *buf) 3232 { 3233 struct wm_adsp_alg_region *alg_region; 3234 struct wm_adsp *dsp = buf->dsp; 3235 u32 xmalg, addr, magic; 3236 int i, ret; 3237 3238 alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id); 3239 xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32); 3240 3241 addr = alg_region->base + xmalg + ALG_XM_FIELD(magic); 3242 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic); 3243 if (ret < 0) 3244 return ret; 3245 3246 if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC) 3247 return -EINVAL; 3248 3249 addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr); 3250 for (i = 0; i < 5; ++i) { 3251 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, 3252 &buf->host_buf_ptr); 3253 if (ret < 0) 3254 return ret; 3255 3256 if (buf->host_buf_ptr) 3257 break; 3258 3259 usleep_range(1000, 2000); 3260 } 3261 3262 if (!buf->host_buf_ptr) 3263 return -EIO; 3264 3265 adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); 3266 3267 return 0; 3268 } 3269 3270 static struct wm_coeff_ctl * 3271 wm_adsp_find_host_buffer_ctrl(struct wm_adsp_compr_buf *buf) 3272 { 3273 struct wm_adsp *dsp = buf->dsp; 3274 struct wm_coeff_ctl *ctl; 3275 3276 list_for_each_entry(ctl, &dsp->ctl_list, list) { 3277 if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER) 3278 continue; 3279 3280 if (!ctl->enabled) 3281 continue; 3282 3283 return ctl; 3284 } 3285 3286 return NULL; 3287 } 3288 3289 static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf) 3290 { 3291 struct wm_adsp *dsp = buf->dsp; 3292 struct wm_coeff_ctl *ctl; 3293 unsigned int reg; 3294 u32 val; 3295 int i, ret; 3296 3297 ctl = wm_adsp_find_host_buffer_ctrl(buf); 3298 if (!ctl) 3299 return wm_adsp_legacy_host_buf_addr(buf); 3300 3301 ret = wm_coeff_base_reg(ctl, ®); 3302 if (ret) 3303 return ret; 3304 3305 for (i = 0; i < 5; ++i) { 3306 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 3307 if (ret < 0) 3308 return ret; 3309 3310 if (val) 3311 break; 3312 3313 usleep_range(1000, 2000); 3314 } 3315 3316 if (!val) 3317 return -EIO; 3318 3319 buf->host_buf_ptr = be32_to_cpu(val); 3320 adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); 3321 3322 return 0; 3323 } 3324 3325 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) 3326 { 3327 const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; 3328 struct wm_adsp_buffer_region *region; 3329 u32 offset = 0; 3330 int i, ret; 3331 3332 for (i = 0; i < caps->num_regions; ++i) { 3333 region = &buf->regions[i]; 3334 3335 region->offset = offset; 3336 region->mem_type = caps->region_defs[i].mem_type; 3337 3338 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset, 3339 ®ion->base_addr); 3340 if (ret < 0) 3341 return ret; 3342 3343 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset, 3344 &offset); 3345 if (ret < 0) 3346 return ret; 3347 3348 region->cumulative_size = offset; 3349 3350 adsp_dbg(buf->dsp, 3351 "region=%d type=%d base=%08x off=%08x size=%08x\n", 3352 i, region->mem_type, region->base_addr, 3353 region->offset, region->cumulative_size); 3354 } 3355 3356 return 0; 3357 } 3358 3359 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf) 3360 { 3361 buf->irq_count = 0xFFFFFFFF; 3362 buf->read_index = -1; 3363 buf->avail = 0; 3364 } 3365 3366 static int wm_adsp_buffer_init(struct wm_adsp *dsp) 3367 { 3368 struct wm_adsp_compr_buf *buf; 3369 int ret; 3370 3371 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 3372 if (!buf) 3373 return -ENOMEM; 3374 3375 buf->dsp = dsp; 3376 3377 wm_adsp_buffer_clear(buf); 3378 3379 ret = wm_adsp_buffer_locate(buf); 3380 if (ret < 0) { 3381 adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret); 3382 goto err_buffer; 3383 } 3384 3385 buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions, 3386 sizeof(*buf->regions), GFP_KERNEL); 3387 if (!buf->regions) { 3388 ret = -ENOMEM; 3389 goto err_buffer; 3390 } 3391 3392 ret = wm_adsp_buffer_populate(buf); 3393 if (ret < 0) { 3394 adsp_err(dsp, "Failed to populate host buffer: %d\n", ret); 3395 goto err_regions; 3396 } 3397 3398 dsp->buffer = buf; 3399 3400 return 0; 3401 3402 err_regions: 3403 kfree(buf->regions); 3404 err_buffer: 3405 kfree(buf); 3406 return ret; 3407 } 3408 3409 static int wm_adsp_buffer_free(struct wm_adsp *dsp) 3410 { 3411 if (dsp->buffer) { 3412 wm_adsp_compr_detach(dsp->buffer->compr); 3413 3414 kfree(dsp->buffer->regions); 3415 kfree(dsp->buffer); 3416 3417 dsp->buffer = NULL; 3418 } 3419 3420 return 0; 3421 } 3422 3423 int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd) 3424 { 3425 struct wm_adsp_compr *compr = stream->runtime->private_data; 3426 struct wm_adsp *dsp = compr->dsp; 3427 int ret = 0; 3428 3429 adsp_dbg(dsp, "Trigger: %d\n", cmd); 3430 3431 mutex_lock(&dsp->pwr_lock); 3432 3433 switch (cmd) { 3434 case SNDRV_PCM_TRIGGER_START: 3435 if (!wm_adsp_compr_attached(compr)) { 3436 ret = wm_adsp_compr_attach(compr); 3437 if (ret < 0) { 3438 adsp_err(dsp, "Failed to link buffer and stream: %d\n", 3439 ret); 3440 break; 3441 } 3442 } 3443 3444 wm_adsp_buffer_clear(compr->buf); 3445 3446 /* Trigger the IRQ at one fragment of data */ 3447 ret = wm_adsp_buffer_write(compr->buf, 3448 HOST_BUFFER_FIELD(high_water_mark), 3449 wm_adsp_compr_frag_words(compr)); 3450 if (ret < 0) { 3451 adsp_err(dsp, "Failed to set high water mark: %d\n", 3452 ret); 3453 break; 3454 } 3455 break; 3456 case SNDRV_PCM_TRIGGER_STOP: 3457 break; 3458 default: 3459 ret = -EINVAL; 3460 break; 3461 } 3462 3463 mutex_unlock(&dsp->pwr_lock); 3464 3465 return ret; 3466 } 3467 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger); 3468 3469 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf) 3470 { 3471 int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1; 3472 3473 return buf->regions[last_region].cumulative_size; 3474 } 3475 3476 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) 3477 { 3478 u32 next_read_index, next_write_index; 3479 int write_index, read_index, avail; 3480 int ret; 3481 3482 /* Only sync read index if we haven't already read a valid index */ 3483 if (buf->read_index < 0) { 3484 ret = wm_adsp_buffer_read(buf, 3485 HOST_BUFFER_FIELD(next_read_index), 3486 &next_read_index); 3487 if (ret < 0) 3488 return ret; 3489 3490 read_index = sign_extend32(next_read_index, 23); 3491 3492 if (read_index < 0) { 3493 adsp_dbg(buf->dsp, "Avail check on unstarted stream\n"); 3494 return 0; 3495 } 3496 3497 buf->read_index = read_index; 3498 } 3499 3500 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index), 3501 &next_write_index); 3502 if (ret < 0) 3503 return ret; 3504 3505 write_index = sign_extend32(next_write_index, 23); 3506 3507 avail = write_index - buf->read_index; 3508 if (avail < 0) 3509 avail += wm_adsp_buffer_size(buf); 3510 3511 adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n", 3512 buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE); 3513 3514 buf->avail = avail; 3515 3516 return 0; 3517 } 3518 3519 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf) 3520 { 3521 int ret; 3522 3523 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error); 3524 if (ret < 0) { 3525 adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret); 3526 return ret; 3527 } 3528 if (buf->error != 0) { 3529 adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error); 3530 return -EIO; 3531 } 3532 3533 return 0; 3534 } 3535 3536 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) 3537 { 3538 struct wm_adsp_compr_buf *buf; 3539 struct wm_adsp_compr *compr; 3540 int ret = 0; 3541 3542 mutex_lock(&dsp->pwr_lock); 3543 3544 buf = dsp->buffer; 3545 compr = dsp->compr; 3546 3547 if (!buf) { 3548 ret = -ENODEV; 3549 goto out; 3550 } 3551 3552 adsp_dbg(dsp, "Handling buffer IRQ\n"); 3553 3554 ret = wm_adsp_buffer_get_error(buf); 3555 if (ret < 0) 3556 goto out_notify; /* Wake poll to report error */ 3557 3558 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count), 3559 &buf->irq_count); 3560 if (ret < 0) { 3561 adsp_err(dsp, "Failed to get irq_count: %d\n", ret); 3562 goto out; 3563 } 3564 3565 ret = wm_adsp_buffer_update_avail(buf); 3566 if (ret < 0) { 3567 adsp_err(dsp, "Error reading avail: %d\n", ret); 3568 goto out; 3569 } 3570 3571 if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2) 3572 ret = WM_ADSP_COMPR_VOICE_TRIGGER; 3573 3574 out_notify: 3575 if (compr && compr->stream) 3576 snd_compr_fragment_elapsed(compr->stream); 3577 3578 out: 3579 mutex_unlock(&dsp->pwr_lock); 3580 3581 return ret; 3582 } 3583 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq); 3584 3585 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf) 3586 { 3587 if (buf->irq_count & 0x01) 3588 return 0; 3589 3590 adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n", 3591 buf->irq_count); 3592 3593 buf->irq_count |= 0x01; 3594 3595 return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack), 3596 buf->irq_count); 3597 } 3598 3599 int wm_adsp_compr_pointer(struct snd_compr_stream *stream, 3600 struct snd_compr_tstamp *tstamp) 3601 { 3602 struct wm_adsp_compr *compr = stream->runtime->private_data; 3603 struct wm_adsp *dsp = compr->dsp; 3604 struct wm_adsp_compr_buf *buf; 3605 int ret = 0; 3606 3607 adsp_dbg(dsp, "Pointer request\n"); 3608 3609 mutex_lock(&dsp->pwr_lock); 3610 3611 buf = compr->buf; 3612 3613 if (!compr->buf || compr->buf->error) { 3614 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN); 3615 ret = -EIO; 3616 goto out; 3617 } 3618 3619 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 3620 ret = wm_adsp_buffer_update_avail(buf); 3621 if (ret < 0) { 3622 adsp_err(dsp, "Error reading avail: %d\n", ret); 3623 goto out; 3624 } 3625 3626 /* 3627 * If we really have less than 1 fragment available tell the 3628 * DSP to inform us once a whole fragment is available. 3629 */ 3630 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 3631 ret = wm_adsp_buffer_get_error(buf); 3632 if (ret < 0) { 3633 if (compr->buf->error) 3634 snd_compr_stop_error(stream, 3635 SNDRV_PCM_STATE_XRUN); 3636 goto out; 3637 } 3638 3639 ret = wm_adsp_buffer_reenable_irq(buf); 3640 if (ret < 0) { 3641 adsp_err(dsp, 3642 "Failed to re-enable buffer IRQ: %d\n", 3643 ret); 3644 goto out; 3645 } 3646 } 3647 } 3648 3649 tstamp->copied_total = compr->copied_total; 3650 tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE; 3651 tstamp->sampling_rate = compr->sample_rate; 3652 3653 out: 3654 mutex_unlock(&dsp->pwr_lock); 3655 3656 return ret; 3657 } 3658 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer); 3659 3660 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) 3661 { 3662 struct wm_adsp_compr_buf *buf = compr->buf; 3663 u8 *pack_in = (u8 *)compr->raw_buf; 3664 u8 *pack_out = (u8 *)compr->raw_buf; 3665 unsigned int adsp_addr; 3666 int mem_type, nwords, max_read; 3667 int i, j, ret; 3668 3669 /* Calculate read parameters */ 3670 for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i) 3671 if (buf->read_index < buf->regions[i].cumulative_size) 3672 break; 3673 3674 if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions) 3675 return -EINVAL; 3676 3677 mem_type = buf->regions[i].mem_type; 3678 adsp_addr = buf->regions[i].base_addr + 3679 (buf->read_index - buf->regions[i].offset); 3680 3681 max_read = wm_adsp_compr_frag_words(compr); 3682 nwords = buf->regions[i].cumulative_size - buf->read_index; 3683 3684 if (nwords > target) 3685 nwords = target; 3686 if (nwords > buf->avail) 3687 nwords = buf->avail; 3688 if (nwords > max_read) 3689 nwords = max_read; 3690 if (!nwords) 3691 return 0; 3692 3693 /* Read data from DSP */ 3694 ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, 3695 nwords, compr->raw_buf); 3696 if (ret < 0) 3697 return ret; 3698 3699 /* Remove the padding bytes from the data read from the DSP */ 3700 for (i = 0; i < nwords; i++) { 3701 for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++) 3702 *pack_out++ = *pack_in++; 3703 3704 pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE; 3705 } 3706 3707 /* update read index to account for words read */ 3708 buf->read_index += nwords; 3709 if (buf->read_index == wm_adsp_buffer_size(buf)) 3710 buf->read_index = 0; 3711 3712 ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index), 3713 buf->read_index); 3714 if (ret < 0) 3715 return ret; 3716 3717 /* update avail to account for words read */ 3718 buf->avail -= nwords; 3719 3720 return nwords; 3721 } 3722 3723 static int wm_adsp_compr_read(struct wm_adsp_compr *compr, 3724 char __user *buf, size_t count) 3725 { 3726 struct wm_adsp *dsp = compr->dsp; 3727 int ntotal = 0; 3728 int nwords, nbytes; 3729 3730 adsp_dbg(dsp, "Requested read of %zu bytes\n", count); 3731 3732 if (!compr->buf || compr->buf->error) { 3733 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN); 3734 return -EIO; 3735 } 3736 3737 count /= WM_ADSP_DATA_WORD_SIZE; 3738 3739 do { 3740 nwords = wm_adsp_buffer_capture_block(compr, count); 3741 if (nwords < 0) { 3742 adsp_err(dsp, "Failed to capture block: %d\n", nwords); 3743 return nwords; 3744 } 3745 3746 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE; 3747 3748 adsp_dbg(dsp, "Read %d bytes\n", nbytes); 3749 3750 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) { 3751 adsp_err(dsp, "Failed to copy data to user: %d, %d\n", 3752 ntotal, nbytes); 3753 return -EFAULT; 3754 } 3755 3756 count -= nwords; 3757 ntotal += nbytes; 3758 } while (nwords > 0 && count > 0); 3759 3760 compr->copied_total += ntotal; 3761 3762 return ntotal; 3763 } 3764 3765 int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf, 3766 size_t count) 3767 { 3768 struct wm_adsp_compr *compr = stream->runtime->private_data; 3769 struct wm_adsp *dsp = compr->dsp; 3770 int ret; 3771 3772 mutex_lock(&dsp->pwr_lock); 3773 3774 if (stream->direction == SND_COMPRESS_CAPTURE) 3775 ret = wm_adsp_compr_read(compr, buf, count); 3776 else 3777 ret = -ENOTSUPP; 3778 3779 mutex_unlock(&dsp->pwr_lock); 3780 3781 return ret; 3782 } 3783 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy); 3784 3785 int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions) 3786 { 3787 struct regmap *regmap = dsp->regmap; 3788 unsigned int code0, code1, lock_reg; 3789 3790 if (!(lock_regions & WM_ADSP2_REGION_ALL)) 3791 return 0; 3792 3793 lock_regions &= WM_ADSP2_REGION_ALL; 3794 lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0; 3795 3796 while (lock_regions) { 3797 code0 = code1 = 0; 3798 if (lock_regions & BIT(0)) { 3799 code0 = ADSP2_LOCK_CODE_0; 3800 code1 = ADSP2_LOCK_CODE_1; 3801 } 3802 if (lock_regions & BIT(1)) { 3803 code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT; 3804 code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT; 3805 } 3806 regmap_write(regmap, lock_reg, code0); 3807 regmap_write(regmap, lock_reg, code1); 3808 lock_regions >>= 2; 3809 lock_reg += 2; 3810 } 3811 3812 return 0; 3813 } 3814 EXPORT_SYMBOL_GPL(wm_adsp2_lock); 3815 3816 irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) 3817 { 3818 unsigned int val; 3819 struct regmap *regmap = dsp->regmap; 3820 int ret = 0; 3821 3822 ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val); 3823 if (ret) { 3824 adsp_err(dsp, 3825 "Failed to read Region Lock Ctrl register: %d\n", ret); 3826 return IRQ_HANDLED; 3827 } 3828 3829 if (val & ADSP2_WDT_TIMEOUT_STS_MASK) { 3830 adsp_err(dsp, "watchdog timeout error\n"); 3831 wm_adsp_stop_watchdog(dsp); 3832 } 3833 3834 if (val & (ADSP2_SLAVE_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) { 3835 if (val & ADSP2_SLAVE_ERR_MASK) 3836 adsp_err(dsp, "bus error: slave error\n"); 3837 else 3838 adsp_err(dsp, "bus error: region lock error\n"); 3839 3840 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val); 3841 if (ret) { 3842 adsp_err(dsp, 3843 "Failed to read Bus Err Addr register: %d\n", 3844 ret); 3845 return IRQ_HANDLED; 3846 } 3847 3848 adsp_err(dsp, "bus error address = 0x%x\n", 3849 val & ADSP2_BUS_ERR_ADDR_MASK); 3850 3851 ret = regmap_read(regmap, 3852 dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR, 3853 &val); 3854 if (ret) { 3855 adsp_err(dsp, 3856 "Failed to read Pmem Xmem Err Addr register: %d\n", 3857 ret); 3858 return IRQ_HANDLED; 3859 } 3860 3861 adsp_err(dsp, "xmem error address = 0x%x\n", 3862 val & ADSP2_XMEM_ERR_ADDR_MASK); 3863 adsp_err(dsp, "pmem error address = 0x%x\n", 3864 (val & ADSP2_PMEM_ERR_ADDR_MASK) >> 3865 ADSP2_PMEM_ERR_ADDR_SHIFT); 3866 } 3867 3868 regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, 3869 ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT); 3870 3871 return IRQ_HANDLED; 3872 } 3873 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); 3874 3875 MODULE_LICENSE("GPL v2"); 3876