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 static int wm_adsp_common_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 INIT_LIST_HEAD(&dsp->ctl_list); 2432 2433 mutex_init(&dsp->pwr_lock); 2434 2435 return 0; 2436 } 2437 2438 int wm_adsp1_init(struct wm_adsp *dsp) 2439 { 2440 return wm_adsp_common_init(dsp); 2441 } 2442 EXPORT_SYMBOL_GPL(wm_adsp1_init); 2443 2444 int wm_adsp1_event(struct snd_soc_dapm_widget *w, 2445 struct snd_kcontrol *kcontrol, 2446 int event) 2447 { 2448 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2449 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2450 struct wm_adsp *dsp = &dsps[w->shift]; 2451 struct wm_coeff_ctl *ctl; 2452 int ret; 2453 unsigned int val; 2454 2455 dsp->component = component; 2456 2457 mutex_lock(&dsp->pwr_lock); 2458 2459 switch (event) { 2460 case SND_SOC_DAPM_POST_PMU: 2461 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2462 ADSP1_SYS_ENA, ADSP1_SYS_ENA); 2463 2464 /* 2465 * For simplicity set the DSP clock rate to be the 2466 * SYSCLK rate rather than making it configurable. 2467 */ 2468 if (dsp->sysclk_reg) { 2469 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); 2470 if (ret != 0) { 2471 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", 2472 ret); 2473 goto err_mutex; 2474 } 2475 2476 val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift; 2477 2478 ret = regmap_update_bits(dsp->regmap, 2479 dsp->base + ADSP1_CONTROL_31, 2480 ADSP1_CLK_SEL_MASK, val); 2481 if (ret != 0) { 2482 adsp_err(dsp, "Failed to set clock rate: %d\n", 2483 ret); 2484 goto err_mutex; 2485 } 2486 } 2487 2488 ret = wm_adsp_load(dsp); 2489 if (ret != 0) 2490 goto err_ena; 2491 2492 ret = wm_adsp1_setup_algs(dsp); 2493 if (ret != 0) 2494 goto err_ena; 2495 2496 ret = wm_adsp_load_coeff(dsp); 2497 if (ret != 0) 2498 goto err_ena; 2499 2500 /* Initialize caches for enabled and unset controls */ 2501 ret = wm_coeff_init_control_caches(dsp); 2502 if (ret != 0) 2503 goto err_ena; 2504 2505 /* Sync set controls */ 2506 ret = wm_coeff_sync_controls(dsp); 2507 if (ret != 0) 2508 goto err_ena; 2509 2510 dsp->booted = true; 2511 2512 /* Start the core running */ 2513 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2514 ADSP1_CORE_ENA | ADSP1_START, 2515 ADSP1_CORE_ENA | ADSP1_START); 2516 2517 dsp->running = true; 2518 break; 2519 2520 case SND_SOC_DAPM_PRE_PMD: 2521 dsp->running = false; 2522 dsp->booted = false; 2523 2524 /* Halt the core */ 2525 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2526 ADSP1_CORE_ENA | ADSP1_START, 0); 2527 2528 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, 2529 ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); 2530 2531 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2532 ADSP1_SYS_ENA, 0); 2533 2534 list_for_each_entry(ctl, &dsp->ctl_list, list) 2535 ctl->enabled = 0; 2536 2537 2538 wm_adsp_free_alg_regions(dsp); 2539 break; 2540 2541 default: 2542 break; 2543 } 2544 2545 mutex_unlock(&dsp->pwr_lock); 2546 2547 return 0; 2548 2549 err_ena: 2550 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2551 ADSP1_SYS_ENA, 0); 2552 err_mutex: 2553 mutex_unlock(&dsp->pwr_lock); 2554 2555 return ret; 2556 } 2557 EXPORT_SYMBOL_GPL(wm_adsp1_event); 2558 2559 static int wm_adsp2_ena(struct wm_adsp *dsp) 2560 { 2561 unsigned int val; 2562 int ret, count; 2563 2564 switch (dsp->rev) { 2565 case 0: 2566 ret = regmap_update_bits_async(dsp->regmap, 2567 dsp->base + ADSP2_CONTROL, 2568 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 2569 if (ret != 0) 2570 return ret; 2571 break; 2572 default: 2573 break; 2574 } 2575 2576 /* Wait for the RAM to start, should be near instantaneous */ 2577 for (count = 0; count < 10; ++count) { 2578 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val); 2579 if (ret != 0) 2580 return ret; 2581 2582 if (val & ADSP2_RAM_RDY) 2583 break; 2584 2585 usleep_range(250, 500); 2586 } 2587 2588 if (!(val & ADSP2_RAM_RDY)) { 2589 adsp_err(dsp, "Failed to start DSP RAM\n"); 2590 return -EBUSY; 2591 } 2592 2593 adsp_dbg(dsp, "RAM ready after %d polls\n", count); 2594 2595 return 0; 2596 } 2597 2598 static void wm_adsp2_boot_work(struct work_struct *work) 2599 { 2600 struct wm_adsp *dsp = container_of(work, 2601 struct wm_adsp, 2602 boot_work); 2603 int ret; 2604 2605 mutex_lock(&dsp->pwr_lock); 2606 2607 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2608 ADSP2_MEM_ENA, ADSP2_MEM_ENA); 2609 if (ret != 0) 2610 goto err_mutex; 2611 2612 ret = wm_adsp2_ena(dsp); 2613 if (ret != 0) 2614 goto err_mem; 2615 2616 ret = wm_adsp_load(dsp); 2617 if (ret != 0) 2618 goto err_ena; 2619 2620 ret = wm_adsp2_setup_algs(dsp); 2621 if (ret != 0) 2622 goto err_ena; 2623 2624 ret = wm_adsp_load_coeff(dsp); 2625 if (ret != 0) 2626 goto err_ena; 2627 2628 /* Initialize caches for enabled and unset controls */ 2629 ret = wm_coeff_init_control_caches(dsp); 2630 if (ret != 0) 2631 goto err_ena; 2632 2633 switch (dsp->rev) { 2634 case 0: 2635 /* Turn DSP back off until we are ready to run */ 2636 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2637 ADSP2_SYS_ENA, 0); 2638 if (ret != 0) 2639 goto err_ena; 2640 break; 2641 default: 2642 break; 2643 } 2644 2645 dsp->booted = true; 2646 2647 mutex_unlock(&dsp->pwr_lock); 2648 2649 return; 2650 2651 err_ena: 2652 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2653 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2654 err_mem: 2655 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2656 ADSP2_MEM_ENA, 0); 2657 err_mutex: 2658 mutex_unlock(&dsp->pwr_lock); 2659 } 2660 2661 static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq) 2662 { 2663 int ret; 2664 2665 switch (dsp->rev) { 2666 case 0: 2667 ret = regmap_update_bits_async(dsp->regmap, 2668 dsp->base + ADSP2_CLOCKING, 2669 ADSP2_CLK_SEL_MASK, 2670 freq << ADSP2_CLK_SEL_SHIFT); 2671 if (ret) { 2672 adsp_err(dsp, "Failed to set clock rate: %d\n", ret); 2673 return; 2674 } 2675 break; 2676 default: 2677 /* clock is handled by parent codec driver */ 2678 break; 2679 } 2680 } 2681 2682 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, 2683 struct snd_ctl_elem_value *ucontrol) 2684 { 2685 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2686 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2687 struct soc_mixer_control *mc = 2688 (struct soc_mixer_control *)kcontrol->private_value; 2689 struct wm_adsp *dsp = &dsps[mc->shift - 1]; 2690 2691 ucontrol->value.integer.value[0] = dsp->preloaded; 2692 2693 return 0; 2694 } 2695 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get); 2696 2697 int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, 2698 struct snd_ctl_elem_value *ucontrol) 2699 { 2700 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2701 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2702 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 2703 struct soc_mixer_control *mc = 2704 (struct soc_mixer_control *)kcontrol->private_value; 2705 struct wm_adsp *dsp = &dsps[mc->shift - 1]; 2706 char preload[32]; 2707 2708 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); 2709 2710 dsp->preloaded = ucontrol->value.integer.value[0]; 2711 2712 if (ucontrol->value.integer.value[0]) 2713 snd_soc_component_force_enable_pin(component, preload); 2714 else 2715 snd_soc_component_disable_pin(component, preload); 2716 2717 snd_soc_dapm_sync(dapm); 2718 2719 flush_work(&dsp->boot_work); 2720 2721 return 0; 2722 } 2723 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); 2724 2725 static void wm_adsp_stop_watchdog(struct wm_adsp *dsp) 2726 { 2727 switch (dsp->rev) { 2728 case 0: 2729 case 1: 2730 return; 2731 default: 2732 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG, 2733 ADSP2_WDT_ENA_MASK, 0); 2734 } 2735 } 2736 2737 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 2738 struct snd_kcontrol *kcontrol, int event, 2739 unsigned int freq) 2740 { 2741 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2742 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2743 struct wm_adsp *dsp = &dsps[w->shift]; 2744 struct wm_coeff_ctl *ctl; 2745 2746 switch (event) { 2747 case SND_SOC_DAPM_PRE_PMU: 2748 wm_adsp2_set_dspclk(dsp, freq); 2749 queue_work(system_unbound_wq, &dsp->boot_work); 2750 break; 2751 case SND_SOC_DAPM_PRE_PMD: 2752 mutex_lock(&dsp->pwr_lock); 2753 2754 wm_adsp_debugfs_clear(dsp); 2755 2756 dsp->fw_id = 0; 2757 dsp->fw_id_version = 0; 2758 2759 dsp->booted = false; 2760 2761 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2762 ADSP2_MEM_ENA, 0); 2763 2764 list_for_each_entry(ctl, &dsp->ctl_list, list) 2765 ctl->enabled = 0; 2766 2767 wm_adsp_free_alg_regions(dsp); 2768 2769 mutex_unlock(&dsp->pwr_lock); 2770 2771 adsp_dbg(dsp, "Shutdown complete\n"); 2772 break; 2773 default: 2774 break; 2775 } 2776 2777 return 0; 2778 } 2779 EXPORT_SYMBOL_GPL(wm_adsp2_early_event); 2780 2781 int wm_adsp2_event(struct snd_soc_dapm_widget *w, 2782 struct snd_kcontrol *kcontrol, int event) 2783 { 2784 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2785 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 2786 struct wm_adsp *dsp = &dsps[w->shift]; 2787 int ret; 2788 2789 switch (event) { 2790 case SND_SOC_DAPM_POST_PMU: 2791 flush_work(&dsp->boot_work); 2792 2793 mutex_lock(&dsp->pwr_lock); 2794 2795 if (!dsp->booted) { 2796 ret = -EIO; 2797 goto err; 2798 } 2799 2800 ret = wm_adsp2_ena(dsp); 2801 if (ret != 0) 2802 goto err; 2803 2804 /* Sync set controls */ 2805 ret = wm_coeff_sync_controls(dsp); 2806 if (ret != 0) 2807 goto err; 2808 2809 wm_adsp2_lock(dsp, dsp->lock_regions); 2810 2811 ret = regmap_update_bits(dsp->regmap, 2812 dsp->base + ADSP2_CONTROL, 2813 ADSP2_CORE_ENA | ADSP2_START, 2814 ADSP2_CORE_ENA | ADSP2_START); 2815 if (ret != 0) 2816 goto err; 2817 2818 if (wm_adsp_fw[dsp->fw].num_caps != 0) { 2819 ret = wm_adsp_buffer_init(dsp); 2820 if (ret < 0) 2821 goto err; 2822 } 2823 2824 dsp->running = true; 2825 2826 mutex_unlock(&dsp->pwr_lock); 2827 2828 break; 2829 2830 case SND_SOC_DAPM_PRE_PMD: 2831 /* Tell the firmware to cleanup */ 2832 wm_adsp_signal_event_controls(dsp, WM_ADSP_FW_EVENT_SHUTDOWN); 2833 2834 wm_adsp_stop_watchdog(dsp); 2835 2836 /* Log firmware state, it can be useful for analysis */ 2837 switch (dsp->rev) { 2838 case 0: 2839 wm_adsp2_show_fw_status(dsp); 2840 break; 2841 default: 2842 wm_adsp2v2_show_fw_status(dsp); 2843 break; 2844 } 2845 2846 mutex_lock(&dsp->pwr_lock); 2847 2848 dsp->running = false; 2849 2850 regmap_update_bits(dsp->regmap, 2851 dsp->base + ADSP2_CONTROL, 2852 ADSP2_CORE_ENA | ADSP2_START, 0); 2853 2854 /* Make sure DMAs are quiesced */ 2855 switch (dsp->rev) { 2856 case 0: 2857 regmap_write(dsp->regmap, 2858 dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2859 regmap_write(dsp->regmap, 2860 dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2861 regmap_write(dsp->regmap, 2862 dsp->base + ADSP2_WDMA_CONFIG_2, 0); 2863 2864 regmap_update_bits(dsp->regmap, 2865 dsp->base + ADSP2_CONTROL, 2866 ADSP2_SYS_ENA, 0); 2867 break; 2868 default: 2869 regmap_write(dsp->regmap, 2870 dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2871 regmap_write(dsp->regmap, 2872 dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2873 regmap_write(dsp->regmap, 2874 dsp->base + ADSP2V2_WDMA_CONFIG_2, 0); 2875 break; 2876 } 2877 2878 if (wm_adsp_fw[dsp->fw].num_caps != 0) 2879 wm_adsp_buffer_free(dsp); 2880 2881 mutex_unlock(&dsp->pwr_lock); 2882 2883 adsp_dbg(dsp, "Execution stopped\n"); 2884 break; 2885 2886 default: 2887 break; 2888 } 2889 2890 return 0; 2891 err: 2892 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2893 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2894 mutex_unlock(&dsp->pwr_lock); 2895 return ret; 2896 } 2897 EXPORT_SYMBOL_GPL(wm_adsp2_event); 2898 2899 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component) 2900 { 2901 char preload[32]; 2902 2903 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); 2904 snd_soc_component_disable_pin(component, preload); 2905 2906 wm_adsp2_init_debugfs(dsp, component); 2907 2908 dsp->component = component; 2909 2910 return 0; 2911 } 2912 EXPORT_SYMBOL_GPL(wm_adsp2_component_probe); 2913 2914 int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component) 2915 { 2916 wm_adsp2_cleanup_debugfs(dsp); 2917 2918 return 0; 2919 } 2920 EXPORT_SYMBOL_GPL(wm_adsp2_component_remove); 2921 2922 int wm_adsp2_init(struct wm_adsp *dsp) 2923 { 2924 int ret; 2925 2926 ret = wm_adsp_common_init(dsp); 2927 if (ret) 2928 return ret; 2929 2930 switch (dsp->rev) { 2931 case 0: 2932 /* 2933 * Disable the DSP memory by default when in reset for a small 2934 * power saving. 2935 */ 2936 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2937 ADSP2_MEM_ENA, 0); 2938 if (ret) { 2939 adsp_err(dsp, 2940 "Failed to clear memory retention: %d\n", ret); 2941 return ret; 2942 } 2943 break; 2944 default: 2945 break; 2946 } 2947 2948 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); 2949 2950 return 0; 2951 } 2952 EXPORT_SYMBOL_GPL(wm_adsp2_init); 2953 2954 void wm_adsp2_remove(struct wm_adsp *dsp) 2955 { 2956 struct wm_coeff_ctl *ctl; 2957 2958 while (!list_empty(&dsp->ctl_list)) { 2959 ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl, 2960 list); 2961 list_del(&ctl->list); 2962 wm_adsp_free_ctl_blk(ctl); 2963 } 2964 } 2965 EXPORT_SYMBOL_GPL(wm_adsp2_remove); 2966 2967 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr) 2968 { 2969 return compr->buf != NULL; 2970 } 2971 2972 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr) 2973 { 2974 /* 2975 * Note this will be more complex once each DSP can support multiple 2976 * streams 2977 */ 2978 if (!compr->dsp->buffer) 2979 return -EINVAL; 2980 2981 compr->buf = compr->dsp->buffer; 2982 compr->buf->compr = compr; 2983 2984 return 0; 2985 } 2986 2987 static void wm_adsp_compr_detach(struct wm_adsp_compr *compr) 2988 { 2989 if (!compr) 2990 return; 2991 2992 /* Wake the poll so it can see buffer is no longer attached */ 2993 if (compr->stream) 2994 snd_compr_fragment_elapsed(compr->stream); 2995 2996 if (wm_adsp_compr_attached(compr)) { 2997 compr->buf->compr = NULL; 2998 compr->buf = NULL; 2999 } 3000 } 3001 3002 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream) 3003 { 3004 struct wm_adsp_compr *compr; 3005 int ret = 0; 3006 3007 mutex_lock(&dsp->pwr_lock); 3008 3009 if (wm_adsp_fw[dsp->fw].num_caps == 0) { 3010 adsp_err(dsp, "Firmware does not support compressed API\n"); 3011 ret = -ENXIO; 3012 goto out; 3013 } 3014 3015 if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) { 3016 adsp_err(dsp, "Firmware does not support stream direction\n"); 3017 ret = -EINVAL; 3018 goto out; 3019 } 3020 3021 if (dsp->compr) { 3022 /* It is expect this limitation will be removed in future */ 3023 adsp_err(dsp, "Only a single stream supported per DSP\n"); 3024 ret = -EBUSY; 3025 goto out; 3026 } 3027 3028 compr = kzalloc(sizeof(*compr), GFP_KERNEL); 3029 if (!compr) { 3030 ret = -ENOMEM; 3031 goto out; 3032 } 3033 3034 compr->dsp = dsp; 3035 compr->stream = stream; 3036 3037 dsp->compr = compr; 3038 3039 stream->runtime->private_data = compr; 3040 3041 out: 3042 mutex_unlock(&dsp->pwr_lock); 3043 3044 return ret; 3045 } 3046 EXPORT_SYMBOL_GPL(wm_adsp_compr_open); 3047 3048 int wm_adsp_compr_free(struct snd_compr_stream *stream) 3049 { 3050 struct wm_adsp_compr *compr = stream->runtime->private_data; 3051 struct wm_adsp *dsp = compr->dsp; 3052 3053 mutex_lock(&dsp->pwr_lock); 3054 3055 wm_adsp_compr_detach(compr); 3056 dsp->compr = NULL; 3057 3058 kfree(compr->raw_buf); 3059 kfree(compr); 3060 3061 mutex_unlock(&dsp->pwr_lock); 3062 3063 return 0; 3064 } 3065 EXPORT_SYMBOL_GPL(wm_adsp_compr_free); 3066 3067 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream, 3068 struct snd_compr_params *params) 3069 { 3070 struct wm_adsp_compr *compr = stream->runtime->private_data; 3071 struct wm_adsp *dsp = compr->dsp; 3072 const struct wm_adsp_fw_caps *caps; 3073 const struct snd_codec_desc *desc; 3074 int i, j; 3075 3076 if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE || 3077 params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE || 3078 params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS || 3079 params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS || 3080 params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) { 3081 adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n", 3082 params->buffer.fragment_size, 3083 params->buffer.fragments); 3084 3085 return -EINVAL; 3086 } 3087 3088 for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) { 3089 caps = &wm_adsp_fw[dsp->fw].caps[i]; 3090 desc = &caps->desc; 3091 3092 if (caps->id != params->codec.id) 3093 continue; 3094 3095 if (stream->direction == SND_COMPRESS_PLAYBACK) { 3096 if (desc->max_ch < params->codec.ch_out) 3097 continue; 3098 } else { 3099 if (desc->max_ch < params->codec.ch_in) 3100 continue; 3101 } 3102 3103 if (!(desc->formats & (1 << params->codec.format))) 3104 continue; 3105 3106 for (j = 0; j < desc->num_sample_rates; ++j) 3107 if (desc->sample_rates[j] == params->codec.sample_rate) 3108 return 0; 3109 } 3110 3111 adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n", 3112 params->codec.id, params->codec.ch_in, params->codec.ch_out, 3113 params->codec.sample_rate, params->codec.format); 3114 return -EINVAL; 3115 } 3116 3117 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr) 3118 { 3119 return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE; 3120 } 3121 3122 int wm_adsp_compr_set_params(struct snd_compr_stream *stream, 3123 struct snd_compr_params *params) 3124 { 3125 struct wm_adsp_compr *compr = stream->runtime->private_data; 3126 unsigned int size; 3127 int ret; 3128 3129 ret = wm_adsp_compr_check_params(stream, params); 3130 if (ret) 3131 return ret; 3132 3133 compr->size = params->buffer; 3134 3135 adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n", 3136 compr->size.fragment_size, compr->size.fragments); 3137 3138 size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf); 3139 compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); 3140 if (!compr->raw_buf) 3141 return -ENOMEM; 3142 3143 compr->sample_rate = params->codec.sample_rate; 3144 3145 return 0; 3146 } 3147 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); 3148 3149 int wm_adsp_compr_get_caps(struct snd_compr_stream *stream, 3150 struct snd_compr_caps *caps) 3151 { 3152 struct wm_adsp_compr *compr = stream->runtime->private_data; 3153 int fw = compr->dsp->fw; 3154 int i; 3155 3156 if (wm_adsp_fw[fw].caps) { 3157 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++) 3158 caps->codecs[i] = wm_adsp_fw[fw].caps[i].id; 3159 3160 caps->num_codecs = i; 3161 caps->direction = wm_adsp_fw[fw].compr_direction; 3162 3163 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE; 3164 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE; 3165 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS; 3166 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS; 3167 } 3168 3169 return 0; 3170 } 3171 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); 3172 3173 static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, 3174 unsigned int mem_addr, 3175 unsigned int num_words, u32 *data) 3176 { 3177 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 3178 unsigned int i, reg; 3179 int ret; 3180 3181 if (!mem) 3182 return -EINVAL; 3183 3184 reg = wm_adsp_region_to_reg(mem, mem_addr); 3185 3186 ret = regmap_raw_read(dsp->regmap, reg, data, 3187 sizeof(*data) * num_words); 3188 if (ret < 0) 3189 return ret; 3190 3191 for (i = 0; i < num_words; ++i) 3192 data[i] = be32_to_cpu(data[i]) & 0x00ffffffu; 3193 3194 return 0; 3195 } 3196 3197 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type, 3198 unsigned int mem_addr, u32 *data) 3199 { 3200 return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data); 3201 } 3202 3203 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, 3204 unsigned int mem_addr, u32 data) 3205 { 3206 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 3207 unsigned int reg; 3208 3209 if (!mem) 3210 return -EINVAL; 3211 3212 reg = wm_adsp_region_to_reg(mem, mem_addr); 3213 3214 data = cpu_to_be32(data & 0x00ffffffu); 3215 3216 return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data)); 3217 } 3218 3219 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, 3220 unsigned int field_offset, u32 *data) 3221 { 3222 return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM, 3223 buf->host_buf_ptr + field_offset, data); 3224 } 3225 3226 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, 3227 unsigned int field_offset, u32 data) 3228 { 3229 return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM, 3230 buf->host_buf_ptr + field_offset, data); 3231 } 3232 3233 static int wm_adsp_legacy_host_buf_addr(struct wm_adsp_compr_buf *buf) 3234 { 3235 struct wm_adsp_alg_region *alg_region; 3236 struct wm_adsp *dsp = buf->dsp; 3237 u32 xmalg, addr, magic; 3238 int i, ret; 3239 3240 alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id); 3241 xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32); 3242 3243 addr = alg_region->base + xmalg + ALG_XM_FIELD(magic); 3244 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic); 3245 if (ret < 0) 3246 return ret; 3247 3248 if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC) 3249 return -EINVAL; 3250 3251 addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr); 3252 for (i = 0; i < 5; ++i) { 3253 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, 3254 &buf->host_buf_ptr); 3255 if (ret < 0) 3256 return ret; 3257 3258 if (buf->host_buf_ptr) 3259 break; 3260 3261 usleep_range(1000, 2000); 3262 } 3263 3264 if (!buf->host_buf_ptr) 3265 return -EIO; 3266 3267 adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); 3268 3269 return 0; 3270 } 3271 3272 static struct wm_coeff_ctl * 3273 wm_adsp_find_host_buffer_ctrl(struct wm_adsp_compr_buf *buf) 3274 { 3275 struct wm_adsp *dsp = buf->dsp; 3276 struct wm_coeff_ctl *ctl; 3277 3278 list_for_each_entry(ctl, &dsp->ctl_list, list) { 3279 if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER) 3280 continue; 3281 3282 if (!ctl->enabled) 3283 continue; 3284 3285 return ctl; 3286 } 3287 3288 return NULL; 3289 } 3290 3291 static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf) 3292 { 3293 struct wm_adsp *dsp = buf->dsp; 3294 struct wm_coeff_ctl *ctl; 3295 unsigned int reg; 3296 u32 val; 3297 int i, ret; 3298 3299 ctl = wm_adsp_find_host_buffer_ctrl(buf); 3300 if (!ctl) 3301 return wm_adsp_legacy_host_buf_addr(buf); 3302 3303 ret = wm_coeff_base_reg(ctl, ®); 3304 if (ret) 3305 return ret; 3306 3307 for (i = 0; i < 5; ++i) { 3308 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); 3309 if (ret < 0) 3310 return ret; 3311 3312 if (val) 3313 break; 3314 3315 usleep_range(1000, 2000); 3316 } 3317 3318 if (!val) 3319 return -EIO; 3320 3321 buf->host_buf_ptr = be32_to_cpu(val); 3322 adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); 3323 3324 return 0; 3325 } 3326 3327 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) 3328 { 3329 const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; 3330 struct wm_adsp_buffer_region *region; 3331 u32 offset = 0; 3332 int i, ret; 3333 3334 for (i = 0; i < caps->num_regions; ++i) { 3335 region = &buf->regions[i]; 3336 3337 region->offset = offset; 3338 region->mem_type = caps->region_defs[i].mem_type; 3339 3340 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset, 3341 ®ion->base_addr); 3342 if (ret < 0) 3343 return ret; 3344 3345 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset, 3346 &offset); 3347 if (ret < 0) 3348 return ret; 3349 3350 region->cumulative_size = offset; 3351 3352 adsp_dbg(buf->dsp, 3353 "region=%d type=%d base=%08x off=%08x size=%08x\n", 3354 i, region->mem_type, region->base_addr, 3355 region->offset, region->cumulative_size); 3356 } 3357 3358 return 0; 3359 } 3360 3361 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf) 3362 { 3363 buf->irq_count = 0xFFFFFFFF; 3364 buf->read_index = -1; 3365 buf->avail = 0; 3366 } 3367 3368 static int wm_adsp_buffer_init(struct wm_adsp *dsp) 3369 { 3370 struct wm_adsp_compr_buf *buf; 3371 int ret; 3372 3373 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 3374 if (!buf) 3375 return -ENOMEM; 3376 3377 buf->dsp = dsp; 3378 3379 wm_adsp_buffer_clear(buf); 3380 3381 ret = wm_adsp_buffer_locate(buf); 3382 if (ret < 0) { 3383 adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret); 3384 goto err_buffer; 3385 } 3386 3387 buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions, 3388 sizeof(*buf->regions), GFP_KERNEL); 3389 if (!buf->regions) { 3390 ret = -ENOMEM; 3391 goto err_buffer; 3392 } 3393 3394 ret = wm_adsp_buffer_populate(buf); 3395 if (ret < 0) { 3396 adsp_err(dsp, "Failed to populate host buffer: %d\n", ret); 3397 goto err_regions; 3398 } 3399 3400 dsp->buffer = buf; 3401 3402 return 0; 3403 3404 err_regions: 3405 kfree(buf->regions); 3406 err_buffer: 3407 kfree(buf); 3408 return ret; 3409 } 3410 3411 static int wm_adsp_buffer_free(struct wm_adsp *dsp) 3412 { 3413 if (dsp->buffer) { 3414 wm_adsp_compr_detach(dsp->buffer->compr); 3415 3416 kfree(dsp->buffer->regions); 3417 kfree(dsp->buffer); 3418 3419 dsp->buffer = NULL; 3420 } 3421 3422 return 0; 3423 } 3424 3425 int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd) 3426 { 3427 struct wm_adsp_compr *compr = stream->runtime->private_data; 3428 struct wm_adsp *dsp = compr->dsp; 3429 int ret = 0; 3430 3431 adsp_dbg(dsp, "Trigger: %d\n", cmd); 3432 3433 mutex_lock(&dsp->pwr_lock); 3434 3435 switch (cmd) { 3436 case SNDRV_PCM_TRIGGER_START: 3437 if (!wm_adsp_compr_attached(compr)) { 3438 ret = wm_adsp_compr_attach(compr); 3439 if (ret < 0) { 3440 adsp_err(dsp, "Failed to link buffer and stream: %d\n", 3441 ret); 3442 break; 3443 } 3444 } 3445 3446 wm_adsp_buffer_clear(compr->buf); 3447 3448 /* Trigger the IRQ at one fragment of data */ 3449 ret = wm_adsp_buffer_write(compr->buf, 3450 HOST_BUFFER_FIELD(high_water_mark), 3451 wm_adsp_compr_frag_words(compr)); 3452 if (ret < 0) { 3453 adsp_err(dsp, "Failed to set high water mark: %d\n", 3454 ret); 3455 break; 3456 } 3457 break; 3458 case SNDRV_PCM_TRIGGER_STOP: 3459 break; 3460 default: 3461 ret = -EINVAL; 3462 break; 3463 } 3464 3465 mutex_unlock(&dsp->pwr_lock); 3466 3467 return ret; 3468 } 3469 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger); 3470 3471 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf) 3472 { 3473 int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1; 3474 3475 return buf->regions[last_region].cumulative_size; 3476 } 3477 3478 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) 3479 { 3480 u32 next_read_index, next_write_index; 3481 int write_index, read_index, avail; 3482 int ret; 3483 3484 /* Only sync read index if we haven't already read a valid index */ 3485 if (buf->read_index < 0) { 3486 ret = wm_adsp_buffer_read(buf, 3487 HOST_BUFFER_FIELD(next_read_index), 3488 &next_read_index); 3489 if (ret < 0) 3490 return ret; 3491 3492 read_index = sign_extend32(next_read_index, 23); 3493 3494 if (read_index < 0) { 3495 adsp_dbg(buf->dsp, "Avail check on unstarted stream\n"); 3496 return 0; 3497 } 3498 3499 buf->read_index = read_index; 3500 } 3501 3502 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index), 3503 &next_write_index); 3504 if (ret < 0) 3505 return ret; 3506 3507 write_index = sign_extend32(next_write_index, 23); 3508 3509 avail = write_index - buf->read_index; 3510 if (avail < 0) 3511 avail += wm_adsp_buffer_size(buf); 3512 3513 adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n", 3514 buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE); 3515 3516 buf->avail = avail; 3517 3518 return 0; 3519 } 3520 3521 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf) 3522 { 3523 int ret; 3524 3525 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error); 3526 if (ret < 0) { 3527 adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret); 3528 return ret; 3529 } 3530 if (buf->error != 0) { 3531 adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error); 3532 return -EIO; 3533 } 3534 3535 return 0; 3536 } 3537 3538 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) 3539 { 3540 struct wm_adsp_compr_buf *buf; 3541 struct wm_adsp_compr *compr; 3542 int ret = 0; 3543 3544 mutex_lock(&dsp->pwr_lock); 3545 3546 buf = dsp->buffer; 3547 compr = dsp->compr; 3548 3549 if (!buf) { 3550 ret = -ENODEV; 3551 goto out; 3552 } 3553 3554 adsp_dbg(dsp, "Handling buffer IRQ\n"); 3555 3556 ret = wm_adsp_buffer_get_error(buf); 3557 if (ret < 0) 3558 goto out_notify; /* Wake poll to report error */ 3559 3560 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count), 3561 &buf->irq_count); 3562 if (ret < 0) { 3563 adsp_err(dsp, "Failed to get irq_count: %d\n", ret); 3564 goto out; 3565 } 3566 3567 ret = wm_adsp_buffer_update_avail(buf); 3568 if (ret < 0) { 3569 adsp_err(dsp, "Error reading avail: %d\n", ret); 3570 goto out; 3571 } 3572 3573 if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2) 3574 ret = WM_ADSP_COMPR_VOICE_TRIGGER; 3575 3576 out_notify: 3577 if (compr && compr->stream) 3578 snd_compr_fragment_elapsed(compr->stream); 3579 3580 out: 3581 mutex_unlock(&dsp->pwr_lock); 3582 3583 return ret; 3584 } 3585 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq); 3586 3587 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf) 3588 { 3589 if (buf->irq_count & 0x01) 3590 return 0; 3591 3592 adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n", 3593 buf->irq_count); 3594 3595 buf->irq_count |= 0x01; 3596 3597 return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack), 3598 buf->irq_count); 3599 } 3600 3601 int wm_adsp_compr_pointer(struct snd_compr_stream *stream, 3602 struct snd_compr_tstamp *tstamp) 3603 { 3604 struct wm_adsp_compr *compr = stream->runtime->private_data; 3605 struct wm_adsp *dsp = compr->dsp; 3606 struct wm_adsp_compr_buf *buf; 3607 int ret = 0; 3608 3609 adsp_dbg(dsp, "Pointer request\n"); 3610 3611 mutex_lock(&dsp->pwr_lock); 3612 3613 buf = compr->buf; 3614 3615 if (!compr->buf || compr->buf->error) { 3616 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN); 3617 ret = -EIO; 3618 goto out; 3619 } 3620 3621 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 3622 ret = wm_adsp_buffer_update_avail(buf); 3623 if (ret < 0) { 3624 adsp_err(dsp, "Error reading avail: %d\n", ret); 3625 goto out; 3626 } 3627 3628 /* 3629 * If we really have less than 1 fragment available tell the 3630 * DSP to inform us once a whole fragment is available. 3631 */ 3632 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 3633 ret = wm_adsp_buffer_get_error(buf); 3634 if (ret < 0) { 3635 if (compr->buf->error) 3636 snd_compr_stop_error(stream, 3637 SNDRV_PCM_STATE_XRUN); 3638 goto out; 3639 } 3640 3641 ret = wm_adsp_buffer_reenable_irq(buf); 3642 if (ret < 0) { 3643 adsp_err(dsp, 3644 "Failed to re-enable buffer IRQ: %d\n", 3645 ret); 3646 goto out; 3647 } 3648 } 3649 } 3650 3651 tstamp->copied_total = compr->copied_total; 3652 tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE; 3653 tstamp->sampling_rate = compr->sample_rate; 3654 3655 out: 3656 mutex_unlock(&dsp->pwr_lock); 3657 3658 return ret; 3659 } 3660 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer); 3661 3662 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) 3663 { 3664 struct wm_adsp_compr_buf *buf = compr->buf; 3665 u8 *pack_in = (u8 *)compr->raw_buf; 3666 u8 *pack_out = (u8 *)compr->raw_buf; 3667 unsigned int adsp_addr; 3668 int mem_type, nwords, max_read; 3669 int i, j, ret; 3670 3671 /* Calculate read parameters */ 3672 for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i) 3673 if (buf->read_index < buf->regions[i].cumulative_size) 3674 break; 3675 3676 if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions) 3677 return -EINVAL; 3678 3679 mem_type = buf->regions[i].mem_type; 3680 adsp_addr = buf->regions[i].base_addr + 3681 (buf->read_index - buf->regions[i].offset); 3682 3683 max_read = wm_adsp_compr_frag_words(compr); 3684 nwords = buf->regions[i].cumulative_size - buf->read_index; 3685 3686 if (nwords > target) 3687 nwords = target; 3688 if (nwords > buf->avail) 3689 nwords = buf->avail; 3690 if (nwords > max_read) 3691 nwords = max_read; 3692 if (!nwords) 3693 return 0; 3694 3695 /* Read data from DSP */ 3696 ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, 3697 nwords, compr->raw_buf); 3698 if (ret < 0) 3699 return ret; 3700 3701 /* Remove the padding bytes from the data read from the DSP */ 3702 for (i = 0; i < nwords; i++) { 3703 for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++) 3704 *pack_out++ = *pack_in++; 3705 3706 pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE; 3707 } 3708 3709 /* update read index to account for words read */ 3710 buf->read_index += nwords; 3711 if (buf->read_index == wm_adsp_buffer_size(buf)) 3712 buf->read_index = 0; 3713 3714 ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index), 3715 buf->read_index); 3716 if (ret < 0) 3717 return ret; 3718 3719 /* update avail to account for words read */ 3720 buf->avail -= nwords; 3721 3722 return nwords; 3723 } 3724 3725 static int wm_adsp_compr_read(struct wm_adsp_compr *compr, 3726 char __user *buf, size_t count) 3727 { 3728 struct wm_adsp *dsp = compr->dsp; 3729 int ntotal = 0; 3730 int nwords, nbytes; 3731 3732 adsp_dbg(dsp, "Requested read of %zu bytes\n", count); 3733 3734 if (!compr->buf || compr->buf->error) { 3735 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN); 3736 return -EIO; 3737 } 3738 3739 count /= WM_ADSP_DATA_WORD_SIZE; 3740 3741 do { 3742 nwords = wm_adsp_buffer_capture_block(compr, count); 3743 if (nwords < 0) { 3744 adsp_err(dsp, "Failed to capture block: %d\n", nwords); 3745 return nwords; 3746 } 3747 3748 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE; 3749 3750 adsp_dbg(dsp, "Read %d bytes\n", nbytes); 3751 3752 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) { 3753 adsp_err(dsp, "Failed to copy data to user: %d, %d\n", 3754 ntotal, nbytes); 3755 return -EFAULT; 3756 } 3757 3758 count -= nwords; 3759 ntotal += nbytes; 3760 } while (nwords > 0 && count > 0); 3761 3762 compr->copied_total += ntotal; 3763 3764 return ntotal; 3765 } 3766 3767 int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf, 3768 size_t count) 3769 { 3770 struct wm_adsp_compr *compr = stream->runtime->private_data; 3771 struct wm_adsp *dsp = compr->dsp; 3772 int ret; 3773 3774 mutex_lock(&dsp->pwr_lock); 3775 3776 if (stream->direction == SND_COMPRESS_CAPTURE) 3777 ret = wm_adsp_compr_read(compr, buf, count); 3778 else 3779 ret = -ENOTSUPP; 3780 3781 mutex_unlock(&dsp->pwr_lock); 3782 3783 return ret; 3784 } 3785 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy); 3786 3787 int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions) 3788 { 3789 struct regmap *regmap = dsp->regmap; 3790 unsigned int code0, code1, lock_reg; 3791 3792 if (!(lock_regions & WM_ADSP2_REGION_ALL)) 3793 return 0; 3794 3795 lock_regions &= WM_ADSP2_REGION_ALL; 3796 lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0; 3797 3798 while (lock_regions) { 3799 code0 = code1 = 0; 3800 if (lock_regions & BIT(0)) { 3801 code0 = ADSP2_LOCK_CODE_0; 3802 code1 = ADSP2_LOCK_CODE_1; 3803 } 3804 if (lock_regions & BIT(1)) { 3805 code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT; 3806 code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT; 3807 } 3808 regmap_write(regmap, lock_reg, code0); 3809 regmap_write(regmap, lock_reg, code1); 3810 lock_regions >>= 2; 3811 lock_reg += 2; 3812 } 3813 3814 return 0; 3815 } 3816 EXPORT_SYMBOL_GPL(wm_adsp2_lock); 3817 3818 irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) 3819 { 3820 unsigned int val; 3821 struct regmap *regmap = dsp->regmap; 3822 int ret = 0; 3823 3824 ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val); 3825 if (ret) { 3826 adsp_err(dsp, 3827 "Failed to read Region Lock Ctrl register: %d\n", ret); 3828 return IRQ_HANDLED; 3829 } 3830 3831 if (val & ADSP2_WDT_TIMEOUT_STS_MASK) { 3832 adsp_err(dsp, "watchdog timeout error\n"); 3833 wm_adsp_stop_watchdog(dsp); 3834 } 3835 3836 if (val & (ADSP2_SLAVE_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) { 3837 if (val & ADSP2_SLAVE_ERR_MASK) 3838 adsp_err(dsp, "bus error: slave error\n"); 3839 else 3840 adsp_err(dsp, "bus error: region lock error\n"); 3841 3842 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val); 3843 if (ret) { 3844 adsp_err(dsp, 3845 "Failed to read Bus Err Addr register: %d\n", 3846 ret); 3847 return IRQ_HANDLED; 3848 } 3849 3850 adsp_err(dsp, "bus error address = 0x%x\n", 3851 val & ADSP2_BUS_ERR_ADDR_MASK); 3852 3853 ret = regmap_read(regmap, 3854 dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR, 3855 &val); 3856 if (ret) { 3857 adsp_err(dsp, 3858 "Failed to read Pmem Xmem Err Addr register: %d\n", 3859 ret); 3860 return IRQ_HANDLED; 3861 } 3862 3863 adsp_err(dsp, "xmem error address = 0x%x\n", 3864 val & ADSP2_XMEM_ERR_ADDR_MASK); 3865 adsp_err(dsp, "pmem error address = 0x%x\n", 3866 (val & ADSP2_PMEM_ERR_ADDR_MASK) >> 3867 ADSP2_PMEM_ERR_ADDR_SHIFT); 3868 } 3869 3870 regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, 3871 ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT); 3872 3873 return IRQ_HANDLED; 3874 } 3875 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); 3876 3877 MODULE_LICENSE("GPL v2"); 3878