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/module.h> 14 #include <linux/moduleparam.h> 15 #include <linux/init.h> 16 #include <linux/delay.h> 17 #include <linux/firmware.h> 18 #include <linux/list.h> 19 #include <linux/pm.h> 20 #include <linux/pm_runtime.h> 21 #include <linux/regmap.h> 22 #include <linux/regulator/consumer.h> 23 #include <linux/slab.h> 24 #include <linux/vmalloc.h> 25 #include <linux/workqueue.h> 26 #include <linux/debugfs.h> 27 #include <sound/core.h> 28 #include <sound/pcm.h> 29 #include <sound/pcm_params.h> 30 #include <sound/soc.h> 31 #include <sound/jack.h> 32 #include <sound/initval.h> 33 #include <sound/tlv.h> 34 35 #include <linux/mfd/arizona/registers.h> 36 37 #include "arizona.h" 38 #include "wm_adsp.h" 39 40 #define adsp_crit(_dsp, fmt, ...) \ 41 dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 42 #define adsp_err(_dsp, fmt, ...) \ 43 dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 44 #define adsp_warn(_dsp, fmt, ...) \ 45 dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 46 #define adsp_info(_dsp, fmt, ...) \ 47 dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 48 #define adsp_dbg(_dsp, fmt, ...) \ 49 dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 50 51 #define ADSP1_CONTROL_1 0x00 52 #define ADSP1_CONTROL_2 0x02 53 #define ADSP1_CONTROL_3 0x03 54 #define ADSP1_CONTROL_4 0x04 55 #define ADSP1_CONTROL_5 0x06 56 #define ADSP1_CONTROL_6 0x07 57 #define ADSP1_CONTROL_7 0x08 58 #define ADSP1_CONTROL_8 0x09 59 #define ADSP1_CONTROL_9 0x0A 60 #define ADSP1_CONTROL_10 0x0B 61 #define ADSP1_CONTROL_11 0x0C 62 #define ADSP1_CONTROL_12 0x0D 63 #define ADSP1_CONTROL_13 0x0F 64 #define ADSP1_CONTROL_14 0x10 65 #define ADSP1_CONTROL_15 0x11 66 #define ADSP1_CONTROL_16 0x12 67 #define ADSP1_CONTROL_17 0x13 68 #define ADSP1_CONTROL_18 0x14 69 #define ADSP1_CONTROL_19 0x16 70 #define ADSP1_CONTROL_20 0x17 71 #define ADSP1_CONTROL_21 0x18 72 #define ADSP1_CONTROL_22 0x1A 73 #define ADSP1_CONTROL_23 0x1B 74 #define ADSP1_CONTROL_24 0x1C 75 #define ADSP1_CONTROL_25 0x1E 76 #define ADSP1_CONTROL_26 0x20 77 #define ADSP1_CONTROL_27 0x21 78 #define ADSP1_CONTROL_28 0x22 79 #define ADSP1_CONTROL_29 0x23 80 #define ADSP1_CONTROL_30 0x24 81 #define ADSP1_CONTROL_31 0x26 82 83 /* 84 * ADSP1 Control 19 85 */ 86 #define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 87 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 88 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 89 90 91 /* 92 * ADSP1 Control 30 93 */ 94 #define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */ 95 #define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */ 96 #define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */ 97 #define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */ 98 #define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 99 #define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 100 #define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 101 #define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 102 #define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 103 #define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 104 #define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 105 #define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 106 #define ADSP1_START 0x0001 /* DSP1_START */ 107 #define ADSP1_START_MASK 0x0001 /* DSP1_START */ 108 #define ADSP1_START_SHIFT 0 /* DSP1_START */ 109 #define ADSP1_START_WIDTH 1 /* DSP1_START */ 110 111 /* 112 * ADSP1 Control 31 113 */ 114 #define ADSP1_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 115 #define ADSP1_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 116 #define ADSP1_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 117 118 #define ADSP2_CONTROL 0x0 119 #define ADSP2_CLOCKING 0x1 120 #define ADSP2_STATUS1 0x4 121 #define ADSP2_WDMA_CONFIG_1 0x30 122 #define ADSP2_WDMA_CONFIG_2 0x31 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 /* 131 * ADSP2 Control 132 */ 133 134 #define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */ 135 #define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */ 136 #define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */ 137 #define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */ 138 #define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 139 #define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 140 #define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 141 #define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 142 #define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 143 #define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 144 #define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 145 #define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 146 #define ADSP2_START 0x0001 /* DSP1_START */ 147 #define ADSP2_START_MASK 0x0001 /* DSP1_START */ 148 #define ADSP2_START_SHIFT 0 /* DSP1_START */ 149 #define ADSP2_START_WIDTH 1 /* DSP1_START */ 150 151 /* 152 * ADSP2 clocking 153 */ 154 #define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 155 #define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 156 #define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 157 158 /* 159 * ADSP2 Status 1 160 */ 161 #define ADSP2_RAM_RDY 0x0001 162 #define ADSP2_RAM_RDY_MASK 0x0001 163 #define ADSP2_RAM_RDY_SHIFT 0 164 #define ADSP2_RAM_RDY_WIDTH 1 165 166 struct wm_adsp_buf { 167 struct list_head list; 168 void *buf; 169 }; 170 171 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len, 172 struct list_head *list) 173 { 174 struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL); 175 176 if (buf == NULL) 177 return NULL; 178 179 buf->buf = vmalloc(len); 180 if (!buf->buf) { 181 vfree(buf); 182 return NULL; 183 } 184 memcpy(buf->buf, src, len); 185 186 if (list) 187 list_add_tail(&buf->list, list); 188 189 return buf; 190 } 191 192 static void wm_adsp_buf_free(struct list_head *list) 193 { 194 while (!list_empty(list)) { 195 struct wm_adsp_buf *buf = list_first_entry(list, 196 struct wm_adsp_buf, 197 list); 198 list_del(&buf->list); 199 vfree(buf->buf); 200 kfree(buf); 201 } 202 } 203 204 #define WM_ADSP_FW_MBC_VSS 0 205 #define WM_ADSP_FW_HIFI 1 206 #define WM_ADSP_FW_TX 2 207 #define WM_ADSP_FW_TX_SPK 3 208 #define WM_ADSP_FW_RX 4 209 #define WM_ADSP_FW_RX_ANC 5 210 #define WM_ADSP_FW_CTRL 6 211 #define WM_ADSP_FW_ASR 7 212 #define WM_ADSP_FW_TRACE 8 213 #define WM_ADSP_FW_SPK_PROT 9 214 #define WM_ADSP_FW_MISC 10 215 216 #define WM_ADSP_NUM_FW 11 217 218 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { 219 [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", 220 [WM_ADSP_FW_HIFI] = "MasterHiFi", 221 [WM_ADSP_FW_TX] = "Tx", 222 [WM_ADSP_FW_TX_SPK] = "Tx Speaker", 223 [WM_ADSP_FW_RX] = "Rx", 224 [WM_ADSP_FW_RX_ANC] = "Rx ANC", 225 [WM_ADSP_FW_CTRL] = "Voice Ctrl", 226 [WM_ADSP_FW_ASR] = "ASR Assist", 227 [WM_ADSP_FW_TRACE] = "Dbg Trace", 228 [WM_ADSP_FW_SPK_PROT] = "Protection", 229 [WM_ADSP_FW_MISC] = "Misc", 230 }; 231 232 struct wm_adsp_system_config_xm_hdr { 233 __be32 sys_enable; 234 __be32 fw_id; 235 __be32 fw_rev; 236 __be32 boot_status; 237 __be32 watchdog; 238 __be32 dma_buffer_size; 239 __be32 rdma[6]; 240 __be32 wdma[8]; 241 __be32 build_job_name[3]; 242 __be32 build_job_number; 243 }; 244 245 struct wm_adsp_alg_xm_struct { 246 __be32 magic; 247 __be32 smoothing; 248 __be32 threshold; 249 __be32 host_buf_ptr; 250 __be32 start_seq; 251 __be32 high_water_mark; 252 __be32 low_water_mark; 253 __be64 smoothed_power; 254 }; 255 256 struct wm_adsp_buffer { 257 __be32 X_buf_base; /* XM base addr of first X area */ 258 __be32 X_buf_size; /* Size of 1st X area in words */ 259 __be32 X_buf_base2; /* XM base addr of 2nd X area */ 260 __be32 X_buf_brk; /* Total X size in words */ 261 __be32 Y_buf_base; /* YM base addr of Y area */ 262 __be32 wrap; /* Total size X and Y in words */ 263 __be32 high_water_mark; /* Point at which IRQ is asserted */ 264 __be32 irq_count; /* bits 1-31 count IRQ assertions */ 265 __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */ 266 __be32 next_write_index; /* word index of next write */ 267 __be32 next_read_index; /* word index of next read */ 268 __be32 error; /* error if any */ 269 __be32 oldest_block_index; /* word index of oldest surviving */ 270 __be32 requested_rewind; /* how many blocks rewind was done */ 271 __be32 reserved_space; /* internal */ 272 __be32 min_free; /* min free space since stream start */ 273 __be32 blocks_written[2]; /* total blocks written (64 bit) */ 274 __be32 words_written[2]; /* total words written (64 bit) */ 275 }; 276 277 struct wm_adsp_compr_buf { 278 struct wm_adsp *dsp; 279 280 struct wm_adsp_buffer_region *regions; 281 u32 host_buf_ptr; 282 283 u32 error; 284 u32 irq_count; 285 int read_index; 286 int avail; 287 }; 288 289 struct wm_adsp_compr { 290 struct wm_adsp *dsp; 291 struct wm_adsp_compr_buf *buf; 292 293 struct snd_compr_stream *stream; 294 struct snd_compressed_buffer size; 295 296 u32 *raw_buf; 297 unsigned int copied_total; 298 }; 299 300 #define WM_ADSP_DATA_WORD_SIZE 3 301 302 #define WM_ADSP_MIN_FRAGMENTS 1 303 #define WM_ADSP_MAX_FRAGMENTS 256 304 #define WM_ADSP_MIN_FRAGMENT_SIZE (64 * WM_ADSP_DATA_WORD_SIZE) 305 #define WM_ADSP_MAX_FRAGMENT_SIZE (4096 * WM_ADSP_DATA_WORD_SIZE) 306 307 #define WM_ADSP_ALG_XM_STRUCT_MAGIC 0x49aec7 308 309 #define HOST_BUFFER_FIELD(field) \ 310 (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32)) 311 312 #define ALG_XM_FIELD(field) \ 313 (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32)) 314 315 static int wm_adsp_buffer_init(struct wm_adsp *dsp); 316 static int wm_adsp_buffer_free(struct wm_adsp *dsp); 317 318 struct wm_adsp_buffer_region { 319 unsigned int offset; 320 unsigned int cumulative_size; 321 unsigned int mem_type; 322 unsigned int base_addr; 323 }; 324 325 struct wm_adsp_buffer_region_def { 326 unsigned int mem_type; 327 unsigned int base_offset; 328 unsigned int size_offset; 329 }; 330 331 static struct wm_adsp_buffer_region_def ez2control_regions[] = { 332 { 333 .mem_type = WMFW_ADSP2_XM, 334 .base_offset = HOST_BUFFER_FIELD(X_buf_base), 335 .size_offset = HOST_BUFFER_FIELD(X_buf_size), 336 }, 337 { 338 .mem_type = WMFW_ADSP2_XM, 339 .base_offset = HOST_BUFFER_FIELD(X_buf_base2), 340 .size_offset = HOST_BUFFER_FIELD(X_buf_brk), 341 }, 342 { 343 .mem_type = WMFW_ADSP2_YM, 344 .base_offset = HOST_BUFFER_FIELD(Y_buf_base), 345 .size_offset = HOST_BUFFER_FIELD(wrap), 346 }, 347 }; 348 349 struct wm_adsp_fw_caps { 350 u32 id; 351 struct snd_codec_desc desc; 352 int num_regions; 353 struct wm_adsp_buffer_region_def *region_defs; 354 }; 355 356 static const struct wm_adsp_fw_caps ez2control_caps[] = { 357 { 358 .id = SND_AUDIOCODEC_BESPOKE, 359 .desc = { 360 .max_ch = 1, 361 .sample_rates = { 16000 }, 362 .num_sample_rates = 1, 363 .formats = SNDRV_PCM_FMTBIT_S16_LE, 364 }, 365 .num_regions = ARRAY_SIZE(ez2control_regions), 366 .region_defs = ez2control_regions, 367 }, 368 }; 369 370 static const struct { 371 const char *file; 372 int compr_direction; 373 int num_caps; 374 const struct wm_adsp_fw_caps *caps; 375 } wm_adsp_fw[WM_ADSP_NUM_FW] = { 376 [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" }, 377 [WM_ADSP_FW_HIFI] = { .file = "hifi" }, 378 [WM_ADSP_FW_TX] = { .file = "tx" }, 379 [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" }, 380 [WM_ADSP_FW_RX] = { .file = "rx" }, 381 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, 382 [WM_ADSP_FW_CTRL] = { 383 .file = "ctrl", 384 .compr_direction = SND_COMPRESS_CAPTURE, 385 .num_caps = ARRAY_SIZE(ez2control_caps), 386 .caps = ez2control_caps, 387 }, 388 [WM_ADSP_FW_ASR] = { .file = "asr" }, 389 [WM_ADSP_FW_TRACE] = { .file = "trace" }, 390 [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" }, 391 [WM_ADSP_FW_MISC] = { .file = "misc" }, 392 }; 393 394 struct wm_coeff_ctl_ops { 395 int (*xget)(struct snd_kcontrol *kcontrol, 396 struct snd_ctl_elem_value *ucontrol); 397 int (*xput)(struct snd_kcontrol *kcontrol, 398 struct snd_ctl_elem_value *ucontrol); 399 int (*xinfo)(struct snd_kcontrol *kcontrol, 400 struct snd_ctl_elem_info *uinfo); 401 }; 402 403 struct wm_coeff_ctl { 404 const char *name; 405 const char *fw_name; 406 struct wm_adsp_alg_region alg_region; 407 struct wm_coeff_ctl_ops ops; 408 struct wm_adsp *dsp; 409 unsigned int enabled:1; 410 struct list_head list; 411 void *cache; 412 unsigned int offset; 413 size_t len; 414 unsigned int set:1; 415 struct snd_kcontrol *kcontrol; 416 unsigned int flags; 417 }; 418 419 #ifdef CONFIG_DEBUG_FS 420 static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) 421 { 422 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); 423 424 kfree(dsp->wmfw_file_name); 425 dsp->wmfw_file_name = tmp; 426 } 427 428 static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) 429 { 430 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); 431 432 kfree(dsp->bin_file_name); 433 dsp->bin_file_name = tmp; 434 } 435 436 static void wm_adsp_debugfs_clear(struct wm_adsp *dsp) 437 { 438 kfree(dsp->wmfw_file_name); 439 kfree(dsp->bin_file_name); 440 dsp->wmfw_file_name = NULL; 441 dsp->bin_file_name = NULL; 442 } 443 444 static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, 445 char __user *user_buf, 446 size_t count, loff_t *ppos) 447 { 448 struct wm_adsp *dsp = file->private_data; 449 ssize_t ret; 450 451 mutex_lock(&dsp->pwr_lock); 452 453 if (!dsp->wmfw_file_name || !dsp->running) 454 ret = 0; 455 else 456 ret = simple_read_from_buffer(user_buf, count, ppos, 457 dsp->wmfw_file_name, 458 strlen(dsp->wmfw_file_name)); 459 460 mutex_unlock(&dsp->pwr_lock); 461 return ret; 462 } 463 464 static ssize_t wm_adsp_debugfs_bin_read(struct file *file, 465 char __user *user_buf, 466 size_t count, loff_t *ppos) 467 { 468 struct wm_adsp *dsp = file->private_data; 469 ssize_t ret; 470 471 mutex_lock(&dsp->pwr_lock); 472 473 if (!dsp->bin_file_name || !dsp->running) 474 ret = 0; 475 else 476 ret = simple_read_from_buffer(user_buf, count, ppos, 477 dsp->bin_file_name, 478 strlen(dsp->bin_file_name)); 479 480 mutex_unlock(&dsp->pwr_lock); 481 return ret; 482 } 483 484 static const struct { 485 const char *name; 486 const struct file_operations fops; 487 } wm_adsp_debugfs_fops[] = { 488 { 489 .name = "wmfw_file_name", 490 .fops = { 491 .open = simple_open, 492 .read = wm_adsp_debugfs_wmfw_read, 493 }, 494 }, 495 { 496 .name = "bin_file_name", 497 .fops = { 498 .open = simple_open, 499 .read = wm_adsp_debugfs_bin_read, 500 }, 501 }, 502 }; 503 504 static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, 505 struct snd_soc_codec *codec) 506 { 507 struct dentry *root = NULL; 508 char *root_name; 509 int i; 510 511 if (!codec->component.debugfs_root) { 512 adsp_err(dsp, "No codec debugfs root\n"); 513 goto err; 514 } 515 516 root_name = kmalloc(PAGE_SIZE, GFP_KERNEL); 517 if (!root_name) 518 goto err; 519 520 snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num); 521 root = debugfs_create_dir(root_name, codec->component.debugfs_root); 522 kfree(root_name); 523 524 if (!root) 525 goto err; 526 527 if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running)) 528 goto err; 529 530 if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id)) 531 goto err; 532 533 if (!debugfs_create_x32("fw_version", S_IRUGO, root, 534 &dsp->fw_id_version)) 535 goto err; 536 537 for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) { 538 if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name, 539 S_IRUGO, root, dsp, 540 &wm_adsp_debugfs_fops[i].fops)) 541 goto err; 542 } 543 544 dsp->debugfs_root = root; 545 return; 546 547 err: 548 debugfs_remove_recursive(root); 549 adsp_err(dsp, "Failed to create debugfs\n"); 550 } 551 552 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) 553 { 554 wm_adsp_debugfs_clear(dsp); 555 debugfs_remove_recursive(dsp->debugfs_root); 556 } 557 #else 558 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp, 559 struct snd_soc_codec *codec) 560 { 561 } 562 563 static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) 564 { 565 } 566 567 static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, 568 const char *s) 569 { 570 } 571 572 static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, 573 const char *s) 574 { 575 } 576 577 static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp) 578 { 579 } 580 #endif 581 582 static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 583 struct snd_ctl_elem_value *ucontrol) 584 { 585 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 586 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 587 struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); 588 589 ucontrol->value.integer.value[0] = dsp[e->shift_l].fw; 590 591 return 0; 592 } 593 594 static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, 595 struct snd_ctl_elem_value *ucontrol) 596 { 597 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 598 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 599 struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); 600 int ret = 0; 601 602 if (ucontrol->value.integer.value[0] == dsp[e->shift_l].fw) 603 return 0; 604 605 if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW) 606 return -EINVAL; 607 608 mutex_lock(&dsp[e->shift_l].pwr_lock); 609 610 if (dsp[e->shift_l].running || dsp[e->shift_l].compr) 611 ret = -EBUSY; 612 else 613 dsp[e->shift_l].fw = ucontrol->value.integer.value[0]; 614 615 mutex_unlock(&dsp[e->shift_l].pwr_lock); 616 617 return ret; 618 } 619 620 static const struct soc_enum wm_adsp_fw_enum[] = { 621 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 622 SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 623 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 624 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 625 }; 626 627 const struct snd_kcontrol_new wm_adsp_fw_controls[] = { 628 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], 629 wm_adsp_fw_get, wm_adsp_fw_put), 630 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], 631 wm_adsp_fw_get, wm_adsp_fw_put), 632 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], 633 wm_adsp_fw_get, wm_adsp_fw_put), 634 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], 635 wm_adsp_fw_get, wm_adsp_fw_put), 636 }; 637 EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); 638 639 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, 640 int type) 641 { 642 int i; 643 644 for (i = 0; i < dsp->num_mems; i++) 645 if (dsp->mem[i].type == type) 646 return &dsp->mem[i]; 647 648 return NULL; 649 } 650 651 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem, 652 unsigned int offset) 653 { 654 if (WARN_ON(!mem)) 655 return offset; 656 switch (mem->type) { 657 case WMFW_ADSP1_PM: 658 return mem->base + (offset * 3); 659 case WMFW_ADSP1_DM: 660 return mem->base + (offset * 2); 661 case WMFW_ADSP2_XM: 662 return mem->base + (offset * 2); 663 case WMFW_ADSP2_YM: 664 return mem->base + (offset * 2); 665 case WMFW_ADSP1_ZM: 666 return mem->base + (offset * 2); 667 default: 668 WARN(1, "Unknown memory region type"); 669 return offset; 670 } 671 } 672 673 static void wm_adsp2_show_fw_status(struct wm_adsp *dsp) 674 { 675 u16 scratch[4]; 676 int ret; 677 678 ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0, 679 scratch, sizeof(scratch)); 680 if (ret) { 681 adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret); 682 return; 683 } 684 685 adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", 686 be16_to_cpu(scratch[0]), 687 be16_to_cpu(scratch[1]), 688 be16_to_cpu(scratch[2]), 689 be16_to_cpu(scratch[3])); 690 } 691 692 static int wm_coeff_info(struct snd_kcontrol *kctl, 693 struct snd_ctl_elem_info *uinfo) 694 { 695 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value; 696 697 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 698 uinfo->count = ctl->len; 699 return 0; 700 } 701 702 static int wm_coeff_write_control(struct wm_coeff_ctl *ctl, 703 const void *buf, size_t len) 704 { 705 struct wm_adsp_alg_region *alg_region = &ctl->alg_region; 706 const struct wm_adsp_region *mem; 707 struct wm_adsp *dsp = ctl->dsp; 708 void *scratch; 709 int ret; 710 unsigned int reg; 711 712 mem = wm_adsp_find_region(dsp, alg_region->type); 713 if (!mem) { 714 adsp_err(dsp, "No base for region %x\n", 715 alg_region->type); 716 return -EINVAL; 717 } 718 719 reg = ctl->alg_region.base + ctl->offset; 720 reg = wm_adsp_region_to_reg(mem, reg); 721 722 scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA); 723 if (!scratch) 724 return -ENOMEM; 725 726 ret = regmap_raw_write(dsp->regmap, reg, scratch, 727 ctl->len); 728 if (ret) { 729 adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n", 730 ctl->len, reg, ret); 731 kfree(scratch); 732 return ret; 733 } 734 adsp_dbg(dsp, "Wrote %zu bytes to %x\n", ctl->len, reg); 735 736 kfree(scratch); 737 738 return 0; 739 } 740 741 static int wm_coeff_put(struct snd_kcontrol *kctl, 742 struct snd_ctl_elem_value *ucontrol) 743 { 744 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value; 745 char *p = ucontrol->value.bytes.data; 746 int ret = 0; 747 748 mutex_lock(&ctl->dsp->pwr_lock); 749 750 memcpy(ctl->cache, p, ctl->len); 751 752 ctl->set = 1; 753 if (ctl->enabled) 754 ret = wm_coeff_write_control(ctl, p, ctl->len); 755 756 mutex_unlock(&ctl->dsp->pwr_lock); 757 758 return ret; 759 } 760 761 static int wm_coeff_read_control(struct wm_coeff_ctl *ctl, 762 void *buf, size_t len) 763 { 764 struct wm_adsp_alg_region *alg_region = &ctl->alg_region; 765 const struct wm_adsp_region *mem; 766 struct wm_adsp *dsp = ctl->dsp; 767 void *scratch; 768 int ret; 769 unsigned int reg; 770 771 mem = wm_adsp_find_region(dsp, alg_region->type); 772 if (!mem) { 773 adsp_err(dsp, "No base for region %x\n", 774 alg_region->type); 775 return -EINVAL; 776 } 777 778 reg = ctl->alg_region.base + ctl->offset; 779 reg = wm_adsp_region_to_reg(mem, reg); 780 781 scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA); 782 if (!scratch) 783 return -ENOMEM; 784 785 ret = regmap_raw_read(dsp->regmap, reg, scratch, ctl->len); 786 if (ret) { 787 adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n", 788 ctl->len, reg, ret); 789 kfree(scratch); 790 return ret; 791 } 792 adsp_dbg(dsp, "Read %zu bytes from %x\n", ctl->len, reg); 793 794 memcpy(buf, scratch, ctl->len); 795 kfree(scratch); 796 797 return 0; 798 } 799 800 static int wm_coeff_get(struct snd_kcontrol *kctl, 801 struct snd_ctl_elem_value *ucontrol) 802 { 803 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value; 804 char *p = ucontrol->value.bytes.data; 805 int ret = 0; 806 807 mutex_lock(&ctl->dsp->pwr_lock); 808 809 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { 810 if (ctl->enabled) 811 ret = wm_coeff_read_control(ctl, p, ctl->len); 812 else 813 ret = -EPERM; 814 } else { 815 if (!ctl->flags && ctl->enabled) 816 ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); 817 818 memcpy(p, ctl->cache, ctl->len); 819 } 820 821 mutex_unlock(&ctl->dsp->pwr_lock); 822 823 return ret; 824 } 825 826 struct wmfw_ctl_work { 827 struct wm_adsp *dsp; 828 struct wm_coeff_ctl *ctl; 829 struct work_struct work; 830 }; 831 832 static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl) 833 { 834 struct snd_kcontrol_new *kcontrol; 835 int ret; 836 837 if (!ctl || !ctl->name) 838 return -EINVAL; 839 840 kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); 841 if (!kcontrol) 842 return -ENOMEM; 843 kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 844 845 kcontrol->name = ctl->name; 846 kcontrol->info = wm_coeff_info; 847 kcontrol->get = wm_coeff_get; 848 kcontrol->put = wm_coeff_put; 849 kcontrol->private_value = (unsigned long)ctl; 850 851 if (ctl->flags) { 852 if (ctl->flags & WMFW_CTL_FLAG_WRITEABLE) 853 kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_WRITE; 854 if (ctl->flags & WMFW_CTL_FLAG_READABLE) 855 kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_READ; 856 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 857 kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE; 858 } 859 860 ret = snd_soc_add_card_controls(dsp->card, 861 kcontrol, 1); 862 if (ret < 0) 863 goto err_kcontrol; 864 865 kfree(kcontrol); 866 867 ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card, 868 ctl->name); 869 870 return 0; 871 872 err_kcontrol: 873 kfree(kcontrol); 874 return ret; 875 } 876 877 static int wm_coeff_init_control_caches(struct wm_adsp *dsp) 878 { 879 struct wm_coeff_ctl *ctl; 880 int ret; 881 882 list_for_each_entry(ctl, &dsp->ctl_list, list) { 883 if (!ctl->enabled || ctl->set) 884 continue; 885 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) 886 continue; 887 888 ret = wm_coeff_read_control(ctl, 889 ctl->cache, 890 ctl->len); 891 if (ret < 0) 892 return ret; 893 } 894 895 return 0; 896 } 897 898 static int wm_coeff_sync_controls(struct wm_adsp *dsp) 899 { 900 struct wm_coeff_ctl *ctl; 901 int ret; 902 903 list_for_each_entry(ctl, &dsp->ctl_list, list) { 904 if (!ctl->enabled) 905 continue; 906 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) { 907 ret = wm_coeff_write_control(ctl, 908 ctl->cache, 909 ctl->len); 910 if (ret < 0) 911 return ret; 912 } 913 } 914 915 return 0; 916 } 917 918 static void wm_adsp_ctl_work(struct work_struct *work) 919 { 920 struct wmfw_ctl_work *ctl_work = container_of(work, 921 struct wmfw_ctl_work, 922 work); 923 924 wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl); 925 kfree(ctl_work); 926 } 927 928 static int wm_adsp_create_control(struct wm_adsp *dsp, 929 const struct wm_adsp_alg_region *alg_region, 930 unsigned int offset, unsigned int len, 931 const char *subname, unsigned int subname_len, 932 unsigned int flags) 933 { 934 struct wm_coeff_ctl *ctl; 935 struct wmfw_ctl_work *ctl_work; 936 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 937 char *region_name; 938 int ret; 939 940 if (flags & WMFW_CTL_FLAG_SYS) 941 return 0; 942 943 switch (alg_region->type) { 944 case WMFW_ADSP1_PM: 945 region_name = "PM"; 946 break; 947 case WMFW_ADSP1_DM: 948 region_name = "DM"; 949 break; 950 case WMFW_ADSP2_XM: 951 region_name = "XM"; 952 break; 953 case WMFW_ADSP2_YM: 954 region_name = "YM"; 955 break; 956 case WMFW_ADSP1_ZM: 957 region_name = "ZM"; 958 break; 959 default: 960 adsp_err(dsp, "Unknown region type: %d\n", alg_region->type); 961 return -EINVAL; 962 } 963 964 switch (dsp->fw_ver) { 965 case 0: 966 case 1: 967 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x", 968 dsp->num, region_name, alg_region->alg); 969 break; 970 default: 971 ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 972 "DSP%d%c %.12s %x", dsp->num, *region_name, 973 wm_adsp_fw_text[dsp->fw], alg_region->alg); 974 975 /* Truncate the subname from the start if it is too long */ 976 if (subname) { 977 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2; 978 int skip = 0; 979 980 if (subname_len > avail) 981 skip = subname_len - avail; 982 983 snprintf(name + ret, 984 SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s", 985 subname_len - skip, subname + skip); 986 } 987 break; 988 } 989 990 list_for_each_entry(ctl, &dsp->ctl_list, list) { 991 if (!strcmp(ctl->name, name)) { 992 if (!ctl->enabled) 993 ctl->enabled = 1; 994 return 0; 995 } 996 } 997 998 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); 999 if (!ctl) 1000 return -ENOMEM; 1001 ctl->fw_name = wm_adsp_fw_text[dsp->fw]; 1002 ctl->alg_region = *alg_region; 1003 ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); 1004 if (!ctl->name) { 1005 ret = -ENOMEM; 1006 goto err_ctl; 1007 } 1008 ctl->enabled = 1; 1009 ctl->set = 0; 1010 ctl->ops.xget = wm_coeff_get; 1011 ctl->ops.xput = wm_coeff_put; 1012 ctl->dsp = dsp; 1013 1014 ctl->flags = flags; 1015 ctl->offset = offset; 1016 if (len > 512) { 1017 adsp_warn(dsp, "Truncating control %s from %d\n", 1018 ctl->name, len); 1019 len = 512; 1020 } 1021 ctl->len = len; 1022 ctl->cache = kzalloc(ctl->len, GFP_KERNEL); 1023 if (!ctl->cache) { 1024 ret = -ENOMEM; 1025 goto err_ctl_name; 1026 } 1027 1028 list_add(&ctl->list, &dsp->ctl_list); 1029 1030 ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); 1031 if (!ctl_work) { 1032 ret = -ENOMEM; 1033 goto err_ctl_cache; 1034 } 1035 1036 ctl_work->dsp = dsp; 1037 ctl_work->ctl = ctl; 1038 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); 1039 schedule_work(&ctl_work->work); 1040 1041 return 0; 1042 1043 err_ctl_cache: 1044 kfree(ctl->cache); 1045 err_ctl_name: 1046 kfree(ctl->name); 1047 err_ctl: 1048 kfree(ctl); 1049 1050 return ret; 1051 } 1052 1053 struct wm_coeff_parsed_alg { 1054 int id; 1055 const u8 *name; 1056 int name_len; 1057 int ncoeff; 1058 }; 1059 1060 struct wm_coeff_parsed_coeff { 1061 int offset; 1062 int mem_type; 1063 const u8 *name; 1064 int name_len; 1065 int ctl_type; 1066 int flags; 1067 int len; 1068 }; 1069 1070 static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str) 1071 { 1072 int length; 1073 1074 switch (bytes) { 1075 case 1: 1076 length = **pos; 1077 break; 1078 case 2: 1079 length = le16_to_cpu(*((__le16 *)*pos)); 1080 break; 1081 default: 1082 return 0; 1083 } 1084 1085 if (str) 1086 *str = *pos + bytes; 1087 1088 *pos += ((length + bytes) + 3) & ~0x03; 1089 1090 return length; 1091 } 1092 1093 static int wm_coeff_parse_int(int bytes, const u8 **pos) 1094 { 1095 int val = 0; 1096 1097 switch (bytes) { 1098 case 2: 1099 val = le16_to_cpu(*((__le16 *)*pos)); 1100 break; 1101 case 4: 1102 val = le32_to_cpu(*((__le32 *)*pos)); 1103 break; 1104 default: 1105 break; 1106 } 1107 1108 *pos += bytes; 1109 1110 return val; 1111 } 1112 1113 static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data, 1114 struct wm_coeff_parsed_alg *blk) 1115 { 1116 const struct wmfw_adsp_alg_data *raw; 1117 1118 switch (dsp->fw_ver) { 1119 case 0: 1120 case 1: 1121 raw = (const struct wmfw_adsp_alg_data *)*data; 1122 *data = raw->data; 1123 1124 blk->id = le32_to_cpu(raw->id); 1125 blk->name = raw->name; 1126 blk->name_len = strlen(raw->name); 1127 blk->ncoeff = le32_to_cpu(raw->ncoeff); 1128 break; 1129 default: 1130 blk->id = wm_coeff_parse_int(sizeof(raw->id), data); 1131 blk->name_len = wm_coeff_parse_string(sizeof(u8), data, 1132 &blk->name); 1133 wm_coeff_parse_string(sizeof(u16), data, NULL); 1134 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data); 1135 break; 1136 } 1137 1138 adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); 1139 adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); 1140 adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); 1141 } 1142 1143 static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, 1144 struct wm_coeff_parsed_coeff *blk) 1145 { 1146 const struct wmfw_adsp_coeff_data *raw; 1147 const u8 *tmp; 1148 int length; 1149 1150 switch (dsp->fw_ver) { 1151 case 0: 1152 case 1: 1153 raw = (const struct wmfw_adsp_coeff_data *)*data; 1154 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); 1155 1156 blk->offset = le16_to_cpu(raw->hdr.offset); 1157 blk->mem_type = le16_to_cpu(raw->hdr.type); 1158 blk->name = raw->name; 1159 blk->name_len = strlen(raw->name); 1160 blk->ctl_type = le16_to_cpu(raw->ctl_type); 1161 blk->flags = le16_to_cpu(raw->flags); 1162 blk->len = le32_to_cpu(raw->len); 1163 break; 1164 default: 1165 tmp = *data; 1166 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp); 1167 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp); 1168 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp); 1169 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp, 1170 &blk->name); 1171 wm_coeff_parse_string(sizeof(u8), &tmp, NULL); 1172 wm_coeff_parse_string(sizeof(u16), &tmp, NULL); 1173 blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp); 1174 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp); 1175 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp); 1176 1177 *data = *data + sizeof(raw->hdr) + length; 1178 break; 1179 } 1180 1181 adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); 1182 adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); 1183 adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name); 1184 adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); 1185 adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); 1186 adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); 1187 } 1188 1189 static int wm_adsp_parse_coeff(struct wm_adsp *dsp, 1190 const struct wmfw_region *region) 1191 { 1192 struct wm_adsp_alg_region alg_region = {}; 1193 struct wm_coeff_parsed_alg alg_blk; 1194 struct wm_coeff_parsed_coeff coeff_blk; 1195 const u8 *data = region->data; 1196 int i, ret; 1197 1198 wm_coeff_parse_alg(dsp, &data, &alg_blk); 1199 for (i = 0; i < alg_blk.ncoeff; i++) { 1200 wm_coeff_parse_coeff(dsp, &data, &coeff_blk); 1201 1202 switch (coeff_blk.ctl_type) { 1203 case SNDRV_CTL_ELEM_TYPE_BYTES: 1204 break; 1205 default: 1206 adsp_err(dsp, "Unknown control type: %d\n", 1207 coeff_blk.ctl_type); 1208 return -EINVAL; 1209 } 1210 1211 alg_region.type = coeff_blk.mem_type; 1212 alg_region.alg = alg_blk.id; 1213 1214 ret = wm_adsp_create_control(dsp, &alg_region, 1215 coeff_blk.offset, 1216 coeff_blk.len, 1217 coeff_blk.name, 1218 coeff_blk.name_len, 1219 coeff_blk.flags); 1220 if (ret < 0) 1221 adsp_err(dsp, "Failed to create control: %.*s, %d\n", 1222 coeff_blk.name_len, coeff_blk.name, ret); 1223 } 1224 1225 return 0; 1226 } 1227 1228 static int wm_adsp_load(struct wm_adsp *dsp) 1229 { 1230 LIST_HEAD(buf_list); 1231 const struct firmware *firmware; 1232 struct regmap *regmap = dsp->regmap; 1233 unsigned int pos = 0; 1234 const struct wmfw_header *header; 1235 const struct wmfw_adsp1_sizes *adsp1_sizes; 1236 const struct wmfw_adsp2_sizes *adsp2_sizes; 1237 const struct wmfw_footer *footer; 1238 const struct wmfw_region *region; 1239 const struct wm_adsp_region *mem; 1240 const char *region_name; 1241 char *file, *text; 1242 struct wm_adsp_buf *buf; 1243 unsigned int reg; 1244 int regions = 0; 1245 int ret, offset, type, sizes; 1246 1247 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 1248 if (file == NULL) 1249 return -ENOMEM; 1250 1251 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num, 1252 wm_adsp_fw[dsp->fw].file); 1253 file[PAGE_SIZE - 1] = '\0'; 1254 1255 ret = request_firmware(&firmware, file, dsp->dev); 1256 if (ret != 0) { 1257 adsp_err(dsp, "Failed to request '%s'\n", file); 1258 goto out; 1259 } 1260 ret = -EINVAL; 1261 1262 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1263 if (pos >= firmware->size) { 1264 adsp_err(dsp, "%s: file too short, %zu bytes\n", 1265 file, firmware->size); 1266 goto out_fw; 1267 } 1268 1269 header = (void *)&firmware->data[0]; 1270 1271 if (memcmp(&header->magic[0], "WMFW", 4) != 0) { 1272 adsp_err(dsp, "%s: invalid magic\n", file); 1273 goto out_fw; 1274 } 1275 1276 switch (header->ver) { 1277 case 0: 1278 adsp_warn(dsp, "%s: Depreciated file format %d\n", 1279 file, header->ver); 1280 break; 1281 case 1: 1282 case 2: 1283 break; 1284 default: 1285 adsp_err(dsp, "%s: unknown file format %d\n", 1286 file, header->ver); 1287 goto out_fw; 1288 } 1289 1290 adsp_info(dsp, "Firmware version: %d\n", header->ver); 1291 dsp->fw_ver = header->ver; 1292 1293 if (header->core != dsp->type) { 1294 adsp_err(dsp, "%s: invalid core %d != %d\n", 1295 file, header->core, dsp->type); 1296 goto out_fw; 1297 } 1298 1299 switch (dsp->type) { 1300 case WMFW_ADSP1: 1301 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1302 adsp1_sizes = (void *)&(header[1]); 1303 footer = (void *)&(adsp1_sizes[1]); 1304 sizes = sizeof(*adsp1_sizes); 1305 1306 adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", 1307 file, le32_to_cpu(adsp1_sizes->dm), 1308 le32_to_cpu(adsp1_sizes->pm), 1309 le32_to_cpu(adsp1_sizes->zm)); 1310 break; 1311 1312 case WMFW_ADSP2: 1313 pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer); 1314 adsp2_sizes = (void *)&(header[1]); 1315 footer = (void *)&(adsp2_sizes[1]); 1316 sizes = sizeof(*adsp2_sizes); 1317 1318 adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", 1319 file, le32_to_cpu(adsp2_sizes->xm), 1320 le32_to_cpu(adsp2_sizes->ym), 1321 le32_to_cpu(adsp2_sizes->pm), 1322 le32_to_cpu(adsp2_sizes->zm)); 1323 break; 1324 1325 default: 1326 WARN(1, "Unknown DSP type"); 1327 goto out_fw; 1328 } 1329 1330 if (le32_to_cpu(header->len) != sizeof(*header) + 1331 sizes + sizeof(*footer)) { 1332 adsp_err(dsp, "%s: unexpected header length %d\n", 1333 file, le32_to_cpu(header->len)); 1334 goto out_fw; 1335 } 1336 1337 adsp_dbg(dsp, "%s: timestamp %llu\n", file, 1338 le64_to_cpu(footer->timestamp)); 1339 1340 while (pos < firmware->size && 1341 pos - firmware->size > sizeof(*region)) { 1342 region = (void *)&(firmware->data[pos]); 1343 region_name = "Unknown"; 1344 reg = 0; 1345 text = NULL; 1346 offset = le32_to_cpu(region->offset) & 0xffffff; 1347 type = be32_to_cpu(region->type) & 0xff; 1348 mem = wm_adsp_find_region(dsp, type); 1349 1350 switch (type) { 1351 case WMFW_NAME_TEXT: 1352 region_name = "Firmware name"; 1353 text = kzalloc(le32_to_cpu(region->len) + 1, 1354 GFP_KERNEL); 1355 break; 1356 case WMFW_ALGORITHM_DATA: 1357 region_name = "Algorithm"; 1358 ret = wm_adsp_parse_coeff(dsp, region); 1359 if (ret != 0) 1360 goto out_fw; 1361 break; 1362 case WMFW_INFO_TEXT: 1363 region_name = "Information"; 1364 text = kzalloc(le32_to_cpu(region->len) + 1, 1365 GFP_KERNEL); 1366 break; 1367 case WMFW_ABSOLUTE: 1368 region_name = "Absolute"; 1369 reg = offset; 1370 break; 1371 case WMFW_ADSP1_PM: 1372 region_name = "PM"; 1373 reg = wm_adsp_region_to_reg(mem, offset); 1374 break; 1375 case WMFW_ADSP1_DM: 1376 region_name = "DM"; 1377 reg = wm_adsp_region_to_reg(mem, offset); 1378 break; 1379 case WMFW_ADSP2_XM: 1380 region_name = "XM"; 1381 reg = wm_adsp_region_to_reg(mem, offset); 1382 break; 1383 case WMFW_ADSP2_YM: 1384 region_name = "YM"; 1385 reg = wm_adsp_region_to_reg(mem, offset); 1386 break; 1387 case WMFW_ADSP1_ZM: 1388 region_name = "ZM"; 1389 reg = wm_adsp_region_to_reg(mem, offset); 1390 break; 1391 default: 1392 adsp_warn(dsp, 1393 "%s.%d: Unknown region type %x at %d(%x)\n", 1394 file, regions, type, pos, pos); 1395 break; 1396 } 1397 1398 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 1399 regions, le32_to_cpu(region->len), offset, 1400 region_name); 1401 1402 if (text) { 1403 memcpy(text, region->data, le32_to_cpu(region->len)); 1404 adsp_info(dsp, "%s: %s\n", file, text); 1405 kfree(text); 1406 } 1407 1408 if (reg) { 1409 buf = wm_adsp_buf_alloc(region->data, 1410 le32_to_cpu(region->len), 1411 &buf_list); 1412 if (!buf) { 1413 adsp_err(dsp, "Out of memory\n"); 1414 ret = -ENOMEM; 1415 goto out_fw; 1416 } 1417 1418 ret = regmap_raw_write_async(regmap, reg, buf->buf, 1419 le32_to_cpu(region->len)); 1420 if (ret != 0) { 1421 adsp_err(dsp, 1422 "%s.%d: Failed to write %d bytes at %d in %s: %d\n", 1423 file, regions, 1424 le32_to_cpu(region->len), offset, 1425 region_name, ret); 1426 goto out_fw; 1427 } 1428 } 1429 1430 pos += le32_to_cpu(region->len) + sizeof(*region); 1431 regions++; 1432 } 1433 1434 ret = regmap_async_complete(regmap); 1435 if (ret != 0) { 1436 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 1437 goto out_fw; 1438 } 1439 1440 if (pos > firmware->size) 1441 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 1442 file, regions, pos - firmware->size); 1443 1444 wm_adsp_debugfs_save_wmfwname(dsp, file); 1445 1446 out_fw: 1447 regmap_async_complete(regmap); 1448 wm_adsp_buf_free(&buf_list); 1449 release_firmware(firmware); 1450 out: 1451 kfree(file); 1452 1453 return ret; 1454 } 1455 1456 static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp, 1457 const struct wm_adsp_alg_region *alg_region) 1458 { 1459 struct wm_coeff_ctl *ctl; 1460 1461 list_for_each_entry(ctl, &dsp->ctl_list, list) { 1462 if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] && 1463 alg_region->alg == ctl->alg_region.alg && 1464 alg_region->type == ctl->alg_region.type) { 1465 ctl->alg_region.base = alg_region->base; 1466 } 1467 } 1468 } 1469 1470 static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, 1471 unsigned int pos, unsigned int len) 1472 { 1473 void *alg; 1474 int ret; 1475 __be32 val; 1476 1477 if (n_algs == 0) { 1478 adsp_err(dsp, "No algorithms\n"); 1479 return ERR_PTR(-EINVAL); 1480 } 1481 1482 if (n_algs > 1024) { 1483 adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs); 1484 return ERR_PTR(-EINVAL); 1485 } 1486 1487 /* Read the terminator first to validate the length */ 1488 ret = regmap_raw_read(dsp->regmap, pos + len, &val, sizeof(val)); 1489 if (ret != 0) { 1490 adsp_err(dsp, "Failed to read algorithm list end: %d\n", 1491 ret); 1492 return ERR_PTR(ret); 1493 } 1494 1495 if (be32_to_cpu(val) != 0xbedead) 1496 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n", 1497 pos + len, be32_to_cpu(val)); 1498 1499 alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA); 1500 if (!alg) 1501 return ERR_PTR(-ENOMEM); 1502 1503 ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2); 1504 if (ret != 0) { 1505 adsp_err(dsp, "Failed to read algorithm list: %d\n", 1506 ret); 1507 kfree(alg); 1508 return ERR_PTR(ret); 1509 } 1510 1511 return alg; 1512 } 1513 1514 static struct wm_adsp_alg_region * 1515 wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id) 1516 { 1517 struct wm_adsp_alg_region *alg_region; 1518 1519 list_for_each_entry(alg_region, &dsp->alg_regions, list) { 1520 if (id == alg_region->alg && type == alg_region->type) 1521 return alg_region; 1522 } 1523 1524 return NULL; 1525 } 1526 1527 static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp, 1528 int type, __be32 id, 1529 __be32 base) 1530 { 1531 struct wm_adsp_alg_region *alg_region; 1532 1533 alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL); 1534 if (!alg_region) 1535 return ERR_PTR(-ENOMEM); 1536 1537 alg_region->type = type; 1538 alg_region->alg = be32_to_cpu(id); 1539 alg_region->base = be32_to_cpu(base); 1540 1541 list_add_tail(&alg_region->list, &dsp->alg_regions); 1542 1543 if (dsp->fw_ver > 0) 1544 wm_adsp_ctl_fixup_base(dsp, alg_region); 1545 1546 return alg_region; 1547 } 1548 1549 static int wm_adsp1_setup_algs(struct wm_adsp *dsp) 1550 { 1551 struct wmfw_adsp1_id_hdr adsp1_id; 1552 struct wmfw_adsp1_alg_hdr *adsp1_alg; 1553 struct wm_adsp_alg_region *alg_region; 1554 const struct wm_adsp_region *mem; 1555 unsigned int pos, len; 1556 size_t n_algs; 1557 int i, ret; 1558 1559 mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM); 1560 if (WARN_ON(!mem)) 1561 return -EINVAL; 1562 1563 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id, 1564 sizeof(adsp1_id)); 1565 if (ret != 0) { 1566 adsp_err(dsp, "Failed to read algorithm info: %d\n", 1567 ret); 1568 return ret; 1569 } 1570 1571 n_algs = be32_to_cpu(adsp1_id.n_algs); 1572 dsp->fw_id = be32_to_cpu(adsp1_id.fw.id); 1573 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 1574 dsp->fw_id, 1575 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, 1576 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, 1577 be32_to_cpu(adsp1_id.fw.ver) & 0xff, 1578 n_algs); 1579 1580 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, 1581 adsp1_id.fw.id, adsp1_id.zm); 1582 if (IS_ERR(alg_region)) 1583 return PTR_ERR(alg_region); 1584 1585 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, 1586 adsp1_id.fw.id, adsp1_id.dm); 1587 if (IS_ERR(alg_region)) 1588 return PTR_ERR(alg_region); 1589 1590 pos = sizeof(adsp1_id) / 2; 1591 len = (sizeof(*adsp1_alg) * n_algs) / 2; 1592 1593 adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len); 1594 if (IS_ERR(adsp1_alg)) 1595 return PTR_ERR(adsp1_alg); 1596 1597 for (i = 0; i < n_algs; i++) { 1598 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", 1599 i, be32_to_cpu(adsp1_alg[i].alg.id), 1600 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, 1601 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, 1602 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, 1603 be32_to_cpu(adsp1_alg[i].dm), 1604 be32_to_cpu(adsp1_alg[i].zm)); 1605 1606 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, 1607 adsp1_alg[i].alg.id, 1608 adsp1_alg[i].dm); 1609 if (IS_ERR(alg_region)) { 1610 ret = PTR_ERR(alg_region); 1611 goto out; 1612 } 1613 if (dsp->fw_ver == 0) { 1614 if (i + 1 < n_algs) { 1615 len = be32_to_cpu(adsp1_alg[i + 1].dm); 1616 len -= be32_to_cpu(adsp1_alg[i].dm); 1617 len *= 4; 1618 wm_adsp_create_control(dsp, alg_region, 0, 1619 len, NULL, 0, 0); 1620 } else { 1621 adsp_warn(dsp, "Missing length info for region DM with ID %x\n", 1622 be32_to_cpu(adsp1_alg[i].alg.id)); 1623 } 1624 } 1625 1626 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, 1627 adsp1_alg[i].alg.id, 1628 adsp1_alg[i].zm); 1629 if (IS_ERR(alg_region)) { 1630 ret = PTR_ERR(alg_region); 1631 goto out; 1632 } 1633 if (dsp->fw_ver == 0) { 1634 if (i + 1 < n_algs) { 1635 len = be32_to_cpu(adsp1_alg[i + 1].zm); 1636 len -= be32_to_cpu(adsp1_alg[i].zm); 1637 len *= 4; 1638 wm_adsp_create_control(dsp, alg_region, 0, 1639 len, NULL, 0, 0); 1640 } else { 1641 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1642 be32_to_cpu(adsp1_alg[i].alg.id)); 1643 } 1644 } 1645 } 1646 1647 out: 1648 kfree(adsp1_alg); 1649 return ret; 1650 } 1651 1652 static int wm_adsp2_setup_algs(struct wm_adsp *dsp) 1653 { 1654 struct wmfw_adsp2_id_hdr adsp2_id; 1655 struct wmfw_adsp2_alg_hdr *adsp2_alg; 1656 struct wm_adsp_alg_region *alg_region; 1657 const struct wm_adsp_region *mem; 1658 unsigned int pos, len; 1659 size_t n_algs; 1660 int i, ret; 1661 1662 mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM); 1663 if (WARN_ON(!mem)) 1664 return -EINVAL; 1665 1666 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id, 1667 sizeof(adsp2_id)); 1668 if (ret != 0) { 1669 adsp_err(dsp, "Failed to read algorithm info: %d\n", 1670 ret); 1671 return ret; 1672 } 1673 1674 n_algs = be32_to_cpu(adsp2_id.n_algs); 1675 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); 1676 dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver); 1677 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 1678 dsp->fw_id, 1679 (dsp->fw_id_version & 0xff0000) >> 16, 1680 (dsp->fw_id_version & 0xff00) >> 8, 1681 dsp->fw_id_version & 0xff, 1682 n_algs); 1683 1684 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, 1685 adsp2_id.fw.id, adsp2_id.xm); 1686 if (IS_ERR(alg_region)) 1687 return PTR_ERR(alg_region); 1688 1689 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, 1690 adsp2_id.fw.id, adsp2_id.ym); 1691 if (IS_ERR(alg_region)) 1692 return PTR_ERR(alg_region); 1693 1694 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, 1695 adsp2_id.fw.id, adsp2_id.zm); 1696 if (IS_ERR(alg_region)) 1697 return PTR_ERR(alg_region); 1698 1699 pos = sizeof(adsp2_id) / 2; 1700 len = (sizeof(*adsp2_alg) * n_algs) / 2; 1701 1702 adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len); 1703 if (IS_ERR(adsp2_alg)) 1704 return PTR_ERR(adsp2_alg); 1705 1706 for (i = 0; i < n_algs; i++) { 1707 adsp_info(dsp, 1708 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", 1709 i, be32_to_cpu(adsp2_alg[i].alg.id), 1710 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, 1711 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, 1712 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, 1713 be32_to_cpu(adsp2_alg[i].xm), 1714 be32_to_cpu(adsp2_alg[i].ym), 1715 be32_to_cpu(adsp2_alg[i].zm)); 1716 1717 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, 1718 adsp2_alg[i].alg.id, 1719 adsp2_alg[i].xm); 1720 if (IS_ERR(alg_region)) { 1721 ret = PTR_ERR(alg_region); 1722 goto out; 1723 } 1724 if (dsp->fw_ver == 0) { 1725 if (i + 1 < n_algs) { 1726 len = be32_to_cpu(adsp2_alg[i + 1].xm); 1727 len -= be32_to_cpu(adsp2_alg[i].xm); 1728 len *= 4; 1729 wm_adsp_create_control(dsp, alg_region, 0, 1730 len, NULL, 0, 0); 1731 } else { 1732 adsp_warn(dsp, "Missing length info for region XM with ID %x\n", 1733 be32_to_cpu(adsp2_alg[i].alg.id)); 1734 } 1735 } 1736 1737 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, 1738 adsp2_alg[i].alg.id, 1739 adsp2_alg[i].ym); 1740 if (IS_ERR(alg_region)) { 1741 ret = PTR_ERR(alg_region); 1742 goto out; 1743 } 1744 if (dsp->fw_ver == 0) { 1745 if (i + 1 < n_algs) { 1746 len = be32_to_cpu(adsp2_alg[i + 1].ym); 1747 len -= be32_to_cpu(adsp2_alg[i].ym); 1748 len *= 4; 1749 wm_adsp_create_control(dsp, alg_region, 0, 1750 len, NULL, 0, 0); 1751 } else { 1752 adsp_warn(dsp, "Missing length info for region YM with ID %x\n", 1753 be32_to_cpu(adsp2_alg[i].alg.id)); 1754 } 1755 } 1756 1757 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, 1758 adsp2_alg[i].alg.id, 1759 adsp2_alg[i].zm); 1760 if (IS_ERR(alg_region)) { 1761 ret = PTR_ERR(alg_region); 1762 goto out; 1763 } 1764 if (dsp->fw_ver == 0) { 1765 if (i + 1 < n_algs) { 1766 len = be32_to_cpu(adsp2_alg[i + 1].zm); 1767 len -= be32_to_cpu(adsp2_alg[i].zm); 1768 len *= 4; 1769 wm_adsp_create_control(dsp, alg_region, 0, 1770 len, NULL, 0, 0); 1771 } else { 1772 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1773 be32_to_cpu(adsp2_alg[i].alg.id)); 1774 } 1775 } 1776 } 1777 1778 out: 1779 kfree(adsp2_alg); 1780 return ret; 1781 } 1782 1783 static int wm_adsp_load_coeff(struct wm_adsp *dsp) 1784 { 1785 LIST_HEAD(buf_list); 1786 struct regmap *regmap = dsp->regmap; 1787 struct wmfw_coeff_hdr *hdr; 1788 struct wmfw_coeff_item *blk; 1789 const struct firmware *firmware; 1790 const struct wm_adsp_region *mem; 1791 struct wm_adsp_alg_region *alg_region; 1792 const char *region_name; 1793 int ret, pos, blocks, type, offset, reg; 1794 char *file; 1795 struct wm_adsp_buf *buf; 1796 1797 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 1798 if (file == NULL) 1799 return -ENOMEM; 1800 1801 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num, 1802 wm_adsp_fw[dsp->fw].file); 1803 file[PAGE_SIZE - 1] = '\0'; 1804 1805 ret = request_firmware(&firmware, file, dsp->dev); 1806 if (ret != 0) { 1807 adsp_warn(dsp, "Failed to request '%s'\n", file); 1808 ret = 0; 1809 goto out; 1810 } 1811 ret = -EINVAL; 1812 1813 if (sizeof(*hdr) >= firmware->size) { 1814 adsp_err(dsp, "%s: file too short, %zu bytes\n", 1815 file, firmware->size); 1816 goto out_fw; 1817 } 1818 1819 hdr = (void *)&firmware->data[0]; 1820 if (memcmp(hdr->magic, "WMDR", 4) != 0) { 1821 adsp_err(dsp, "%s: invalid magic\n", file); 1822 goto out_fw; 1823 } 1824 1825 switch (be32_to_cpu(hdr->rev) & 0xff) { 1826 case 1: 1827 break; 1828 default: 1829 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n", 1830 file, be32_to_cpu(hdr->rev) & 0xff); 1831 ret = -EINVAL; 1832 goto out_fw; 1833 } 1834 1835 adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, 1836 (le32_to_cpu(hdr->ver) >> 16) & 0xff, 1837 (le32_to_cpu(hdr->ver) >> 8) & 0xff, 1838 le32_to_cpu(hdr->ver) & 0xff); 1839 1840 pos = le32_to_cpu(hdr->len); 1841 1842 blocks = 0; 1843 while (pos < firmware->size && 1844 pos - firmware->size > sizeof(*blk)) { 1845 blk = (void *)(&firmware->data[pos]); 1846 1847 type = le16_to_cpu(blk->type); 1848 offset = le16_to_cpu(blk->offset); 1849 1850 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", 1851 file, blocks, le32_to_cpu(blk->id), 1852 (le32_to_cpu(blk->ver) >> 16) & 0xff, 1853 (le32_to_cpu(blk->ver) >> 8) & 0xff, 1854 le32_to_cpu(blk->ver) & 0xff); 1855 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", 1856 file, blocks, le32_to_cpu(blk->len), offset, type); 1857 1858 reg = 0; 1859 region_name = "Unknown"; 1860 switch (type) { 1861 case (WMFW_NAME_TEXT << 8): 1862 case (WMFW_INFO_TEXT << 8): 1863 break; 1864 case (WMFW_ABSOLUTE << 8): 1865 /* 1866 * Old files may use this for global 1867 * coefficients. 1868 */ 1869 if (le32_to_cpu(blk->id) == dsp->fw_id && 1870 offset == 0) { 1871 region_name = "global coefficients"; 1872 mem = wm_adsp_find_region(dsp, type); 1873 if (!mem) { 1874 adsp_err(dsp, "No ZM\n"); 1875 break; 1876 } 1877 reg = wm_adsp_region_to_reg(mem, 0); 1878 1879 } else { 1880 region_name = "register"; 1881 reg = offset; 1882 } 1883 break; 1884 1885 case WMFW_ADSP1_DM: 1886 case WMFW_ADSP1_ZM: 1887 case WMFW_ADSP2_XM: 1888 case WMFW_ADSP2_YM: 1889 adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", 1890 file, blocks, le32_to_cpu(blk->len), 1891 type, le32_to_cpu(blk->id)); 1892 1893 mem = wm_adsp_find_region(dsp, type); 1894 if (!mem) { 1895 adsp_err(dsp, "No base for region %x\n", type); 1896 break; 1897 } 1898 1899 alg_region = wm_adsp_find_alg_region(dsp, type, 1900 le32_to_cpu(blk->id)); 1901 if (alg_region) { 1902 reg = alg_region->base; 1903 reg = wm_adsp_region_to_reg(mem, reg); 1904 reg += offset; 1905 } else { 1906 adsp_err(dsp, "No %x for algorithm %x\n", 1907 type, le32_to_cpu(blk->id)); 1908 } 1909 break; 1910 1911 default: 1912 adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n", 1913 file, blocks, type, pos); 1914 break; 1915 } 1916 1917 if (reg) { 1918 buf = wm_adsp_buf_alloc(blk->data, 1919 le32_to_cpu(blk->len), 1920 &buf_list); 1921 if (!buf) { 1922 adsp_err(dsp, "Out of memory\n"); 1923 ret = -ENOMEM; 1924 goto out_fw; 1925 } 1926 1927 adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", 1928 file, blocks, le32_to_cpu(blk->len), 1929 reg); 1930 ret = regmap_raw_write_async(regmap, reg, buf->buf, 1931 le32_to_cpu(blk->len)); 1932 if (ret != 0) { 1933 adsp_err(dsp, 1934 "%s.%d: Failed to write to %x in %s: %d\n", 1935 file, blocks, reg, region_name, ret); 1936 } 1937 } 1938 1939 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03; 1940 blocks++; 1941 } 1942 1943 ret = regmap_async_complete(regmap); 1944 if (ret != 0) 1945 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 1946 1947 if (pos > firmware->size) 1948 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 1949 file, blocks, pos - firmware->size); 1950 1951 wm_adsp_debugfs_save_binname(dsp, file); 1952 1953 out_fw: 1954 regmap_async_complete(regmap); 1955 release_firmware(firmware); 1956 wm_adsp_buf_free(&buf_list); 1957 out: 1958 kfree(file); 1959 return ret; 1960 } 1961 1962 int wm_adsp1_init(struct wm_adsp *dsp) 1963 { 1964 INIT_LIST_HEAD(&dsp->alg_regions); 1965 1966 mutex_init(&dsp->pwr_lock); 1967 1968 return 0; 1969 } 1970 EXPORT_SYMBOL_GPL(wm_adsp1_init); 1971 1972 int wm_adsp1_event(struct snd_soc_dapm_widget *w, 1973 struct snd_kcontrol *kcontrol, 1974 int event) 1975 { 1976 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 1977 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1978 struct wm_adsp *dsp = &dsps[w->shift]; 1979 struct wm_adsp_alg_region *alg_region; 1980 struct wm_coeff_ctl *ctl; 1981 int ret; 1982 unsigned int val; 1983 1984 dsp->card = codec->component.card; 1985 1986 mutex_lock(&dsp->pwr_lock); 1987 1988 switch (event) { 1989 case SND_SOC_DAPM_POST_PMU: 1990 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1991 ADSP1_SYS_ENA, ADSP1_SYS_ENA); 1992 1993 /* 1994 * For simplicity set the DSP clock rate to be the 1995 * SYSCLK rate rather than making it configurable. 1996 */ 1997 if (dsp->sysclk_reg) { 1998 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); 1999 if (ret != 0) { 2000 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", 2001 ret); 2002 goto err_mutex; 2003 } 2004 2005 val = (val & dsp->sysclk_mask) 2006 >> dsp->sysclk_shift; 2007 2008 ret = regmap_update_bits(dsp->regmap, 2009 dsp->base + ADSP1_CONTROL_31, 2010 ADSP1_CLK_SEL_MASK, val); 2011 if (ret != 0) { 2012 adsp_err(dsp, "Failed to set clock rate: %d\n", 2013 ret); 2014 goto err_mutex; 2015 } 2016 } 2017 2018 ret = wm_adsp_load(dsp); 2019 if (ret != 0) 2020 goto err_ena; 2021 2022 ret = wm_adsp1_setup_algs(dsp); 2023 if (ret != 0) 2024 goto err_ena; 2025 2026 ret = wm_adsp_load_coeff(dsp); 2027 if (ret != 0) 2028 goto err_ena; 2029 2030 /* Initialize caches for enabled and unset controls */ 2031 ret = wm_coeff_init_control_caches(dsp); 2032 if (ret != 0) 2033 goto err_ena; 2034 2035 /* Sync set controls */ 2036 ret = wm_coeff_sync_controls(dsp); 2037 if (ret != 0) 2038 goto err_ena; 2039 2040 /* Start the core running */ 2041 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2042 ADSP1_CORE_ENA | ADSP1_START, 2043 ADSP1_CORE_ENA | ADSP1_START); 2044 break; 2045 2046 case SND_SOC_DAPM_PRE_PMD: 2047 /* Halt the core */ 2048 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2049 ADSP1_CORE_ENA | ADSP1_START, 0); 2050 2051 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, 2052 ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); 2053 2054 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2055 ADSP1_SYS_ENA, 0); 2056 2057 list_for_each_entry(ctl, &dsp->ctl_list, list) 2058 ctl->enabled = 0; 2059 2060 while (!list_empty(&dsp->alg_regions)) { 2061 alg_region = list_first_entry(&dsp->alg_regions, 2062 struct wm_adsp_alg_region, 2063 list); 2064 list_del(&alg_region->list); 2065 kfree(alg_region); 2066 } 2067 break; 2068 2069 default: 2070 break; 2071 } 2072 2073 mutex_unlock(&dsp->pwr_lock); 2074 2075 return 0; 2076 2077 err_ena: 2078 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 2079 ADSP1_SYS_ENA, 0); 2080 err_mutex: 2081 mutex_unlock(&dsp->pwr_lock); 2082 2083 return ret; 2084 } 2085 EXPORT_SYMBOL_GPL(wm_adsp1_event); 2086 2087 static int wm_adsp2_ena(struct wm_adsp *dsp) 2088 { 2089 unsigned int val; 2090 int ret, count; 2091 2092 ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL, 2093 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 2094 if (ret != 0) 2095 return ret; 2096 2097 /* Wait for the RAM to start, should be near instantaneous */ 2098 for (count = 0; count < 10; ++count) { 2099 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, 2100 &val); 2101 if (ret != 0) 2102 return ret; 2103 2104 if (val & ADSP2_RAM_RDY) 2105 break; 2106 2107 msleep(1); 2108 } 2109 2110 if (!(val & ADSP2_RAM_RDY)) { 2111 adsp_err(dsp, "Failed to start DSP RAM\n"); 2112 return -EBUSY; 2113 } 2114 2115 adsp_dbg(dsp, "RAM ready after %d polls\n", count); 2116 2117 return 0; 2118 } 2119 2120 static void wm_adsp2_boot_work(struct work_struct *work) 2121 { 2122 struct wm_adsp *dsp = container_of(work, 2123 struct wm_adsp, 2124 boot_work); 2125 int ret; 2126 unsigned int val; 2127 2128 mutex_lock(&dsp->pwr_lock); 2129 2130 /* 2131 * For simplicity set the DSP clock rate to be the 2132 * SYSCLK rate rather than making it configurable. 2133 */ 2134 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); 2135 if (ret != 0) { 2136 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); 2137 goto err_mutex; 2138 } 2139 val = (val & ARIZONA_SYSCLK_FREQ_MASK) 2140 >> ARIZONA_SYSCLK_FREQ_SHIFT; 2141 2142 ret = regmap_update_bits_async(dsp->regmap, 2143 dsp->base + ADSP2_CLOCKING, 2144 ADSP2_CLK_SEL_MASK, val); 2145 if (ret != 0) { 2146 adsp_err(dsp, "Failed to set clock rate: %d\n", ret); 2147 goto err_mutex; 2148 } 2149 2150 ret = wm_adsp2_ena(dsp); 2151 if (ret != 0) 2152 goto err_mutex; 2153 2154 ret = wm_adsp_load(dsp); 2155 if (ret != 0) 2156 goto err_ena; 2157 2158 ret = wm_adsp2_setup_algs(dsp); 2159 if (ret != 0) 2160 goto err_ena; 2161 2162 ret = wm_adsp_load_coeff(dsp); 2163 if (ret != 0) 2164 goto err_ena; 2165 2166 /* Initialize caches for enabled and unset controls */ 2167 ret = wm_coeff_init_control_caches(dsp); 2168 if (ret != 0) 2169 goto err_ena; 2170 2171 /* Sync set controls */ 2172 ret = wm_coeff_sync_controls(dsp); 2173 if (ret != 0) 2174 goto err_ena; 2175 2176 dsp->running = true; 2177 2178 mutex_unlock(&dsp->pwr_lock); 2179 2180 return; 2181 2182 err_ena: 2183 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2184 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2185 err_mutex: 2186 mutex_unlock(&dsp->pwr_lock); 2187 } 2188 2189 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 2190 struct snd_kcontrol *kcontrol, int event) 2191 { 2192 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 2193 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 2194 struct wm_adsp *dsp = &dsps[w->shift]; 2195 2196 dsp->card = codec->component.card; 2197 2198 switch (event) { 2199 case SND_SOC_DAPM_PRE_PMU: 2200 queue_work(system_unbound_wq, &dsp->boot_work); 2201 break; 2202 default: 2203 break; 2204 } 2205 2206 return 0; 2207 } 2208 EXPORT_SYMBOL_GPL(wm_adsp2_early_event); 2209 2210 int wm_adsp2_event(struct snd_soc_dapm_widget *w, 2211 struct snd_kcontrol *kcontrol, int event) 2212 { 2213 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 2214 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 2215 struct wm_adsp *dsp = &dsps[w->shift]; 2216 struct wm_adsp_alg_region *alg_region; 2217 struct wm_coeff_ctl *ctl; 2218 int ret; 2219 2220 switch (event) { 2221 case SND_SOC_DAPM_POST_PMU: 2222 flush_work(&dsp->boot_work); 2223 2224 if (!dsp->running) 2225 return -EIO; 2226 2227 ret = regmap_update_bits(dsp->regmap, 2228 dsp->base + ADSP2_CONTROL, 2229 ADSP2_CORE_ENA | ADSP2_START, 2230 ADSP2_CORE_ENA | ADSP2_START); 2231 if (ret != 0) 2232 goto err; 2233 2234 if (wm_adsp_fw[dsp->fw].num_caps != 0) 2235 ret = wm_adsp_buffer_init(dsp); 2236 2237 break; 2238 2239 case SND_SOC_DAPM_PRE_PMD: 2240 /* Log firmware state, it can be useful for analysis */ 2241 wm_adsp2_show_fw_status(dsp); 2242 2243 mutex_lock(&dsp->pwr_lock); 2244 2245 wm_adsp_debugfs_clear(dsp); 2246 2247 dsp->fw_id = 0; 2248 dsp->fw_id_version = 0; 2249 dsp->running = false; 2250 2251 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2252 ADSP2_SYS_ENA | ADSP2_CORE_ENA | 2253 ADSP2_START, 0); 2254 2255 /* Make sure DMAs are quiesced */ 2256 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); 2257 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); 2258 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); 2259 2260 list_for_each_entry(ctl, &dsp->ctl_list, list) 2261 ctl->enabled = 0; 2262 2263 while (!list_empty(&dsp->alg_regions)) { 2264 alg_region = list_first_entry(&dsp->alg_regions, 2265 struct wm_adsp_alg_region, 2266 list); 2267 list_del(&alg_region->list); 2268 kfree(alg_region); 2269 } 2270 2271 if (wm_adsp_fw[dsp->fw].num_caps != 0) 2272 wm_adsp_buffer_free(dsp); 2273 2274 mutex_unlock(&dsp->pwr_lock); 2275 2276 adsp_dbg(dsp, "Shutdown complete\n"); 2277 break; 2278 2279 default: 2280 break; 2281 } 2282 2283 return 0; 2284 err: 2285 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2286 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 2287 return ret; 2288 } 2289 EXPORT_SYMBOL_GPL(wm_adsp2_event); 2290 2291 int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) 2292 { 2293 wm_adsp2_init_debugfs(dsp, codec); 2294 2295 return snd_soc_add_codec_controls(codec, 2296 &wm_adsp_fw_controls[dsp->num - 1], 2297 1); 2298 } 2299 EXPORT_SYMBOL_GPL(wm_adsp2_codec_probe); 2300 2301 int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec) 2302 { 2303 wm_adsp2_cleanup_debugfs(dsp); 2304 2305 return 0; 2306 } 2307 EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove); 2308 2309 int wm_adsp2_init(struct wm_adsp *dsp) 2310 { 2311 int ret; 2312 2313 /* 2314 * Disable the DSP memory by default when in reset for a small 2315 * power saving. 2316 */ 2317 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2318 ADSP2_MEM_ENA, 0); 2319 if (ret != 0) { 2320 adsp_err(dsp, "Failed to clear memory retention: %d\n", ret); 2321 return ret; 2322 } 2323 2324 INIT_LIST_HEAD(&dsp->alg_regions); 2325 INIT_LIST_HEAD(&dsp->ctl_list); 2326 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); 2327 2328 mutex_init(&dsp->pwr_lock); 2329 2330 return 0; 2331 } 2332 EXPORT_SYMBOL_GPL(wm_adsp2_init); 2333 2334 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream) 2335 { 2336 struct wm_adsp_compr *compr; 2337 int ret = 0; 2338 2339 mutex_lock(&dsp->pwr_lock); 2340 2341 if (wm_adsp_fw[dsp->fw].num_caps == 0) { 2342 adsp_err(dsp, "Firmware does not support compressed API\n"); 2343 ret = -ENXIO; 2344 goto out; 2345 } 2346 2347 if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) { 2348 adsp_err(dsp, "Firmware does not support stream direction\n"); 2349 ret = -EINVAL; 2350 goto out; 2351 } 2352 2353 if (dsp->compr) { 2354 /* It is expect this limitation will be removed in future */ 2355 adsp_err(dsp, "Only a single stream supported per DSP\n"); 2356 ret = -EBUSY; 2357 goto out; 2358 } 2359 2360 compr = kzalloc(sizeof(*compr), GFP_KERNEL); 2361 if (!compr) { 2362 ret = -ENOMEM; 2363 goto out; 2364 } 2365 2366 compr->dsp = dsp; 2367 compr->stream = stream; 2368 2369 dsp->compr = compr; 2370 2371 stream->runtime->private_data = compr; 2372 2373 out: 2374 mutex_unlock(&dsp->pwr_lock); 2375 2376 return ret; 2377 } 2378 EXPORT_SYMBOL_GPL(wm_adsp_compr_open); 2379 2380 int wm_adsp_compr_free(struct snd_compr_stream *stream) 2381 { 2382 struct wm_adsp_compr *compr = stream->runtime->private_data; 2383 struct wm_adsp *dsp = compr->dsp; 2384 2385 mutex_lock(&dsp->pwr_lock); 2386 2387 dsp->compr = NULL; 2388 2389 kfree(compr->raw_buf); 2390 kfree(compr); 2391 2392 mutex_unlock(&dsp->pwr_lock); 2393 2394 return 0; 2395 } 2396 EXPORT_SYMBOL_GPL(wm_adsp_compr_free); 2397 2398 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream, 2399 struct snd_compr_params *params) 2400 { 2401 struct wm_adsp_compr *compr = stream->runtime->private_data; 2402 struct wm_adsp *dsp = compr->dsp; 2403 const struct wm_adsp_fw_caps *caps; 2404 const struct snd_codec_desc *desc; 2405 int i, j; 2406 2407 if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE || 2408 params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE || 2409 params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS || 2410 params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS || 2411 params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) { 2412 adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n", 2413 params->buffer.fragment_size, 2414 params->buffer.fragments); 2415 2416 return -EINVAL; 2417 } 2418 2419 for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) { 2420 caps = &wm_adsp_fw[dsp->fw].caps[i]; 2421 desc = &caps->desc; 2422 2423 if (caps->id != params->codec.id) 2424 continue; 2425 2426 if (stream->direction == SND_COMPRESS_PLAYBACK) { 2427 if (desc->max_ch < params->codec.ch_out) 2428 continue; 2429 } else { 2430 if (desc->max_ch < params->codec.ch_in) 2431 continue; 2432 } 2433 2434 if (!(desc->formats & (1 << params->codec.format))) 2435 continue; 2436 2437 for (j = 0; j < desc->num_sample_rates; ++j) 2438 if (desc->sample_rates[j] == params->codec.sample_rate) 2439 return 0; 2440 } 2441 2442 adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n", 2443 params->codec.id, params->codec.ch_in, params->codec.ch_out, 2444 params->codec.sample_rate, params->codec.format); 2445 return -EINVAL; 2446 } 2447 2448 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr) 2449 { 2450 return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE; 2451 } 2452 2453 int wm_adsp_compr_set_params(struct snd_compr_stream *stream, 2454 struct snd_compr_params *params) 2455 { 2456 struct wm_adsp_compr *compr = stream->runtime->private_data; 2457 unsigned int size; 2458 int ret; 2459 2460 ret = wm_adsp_compr_check_params(stream, params); 2461 if (ret) 2462 return ret; 2463 2464 compr->size = params->buffer; 2465 2466 adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n", 2467 compr->size.fragment_size, compr->size.fragments); 2468 2469 size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf); 2470 compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); 2471 if (!compr->raw_buf) 2472 return -ENOMEM; 2473 2474 return 0; 2475 } 2476 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); 2477 2478 int wm_adsp_compr_get_caps(struct snd_compr_stream *stream, 2479 struct snd_compr_caps *caps) 2480 { 2481 struct wm_adsp_compr *compr = stream->runtime->private_data; 2482 int fw = compr->dsp->fw; 2483 int i; 2484 2485 if (wm_adsp_fw[fw].caps) { 2486 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++) 2487 caps->codecs[i] = wm_adsp_fw[fw].caps[i].id; 2488 2489 caps->num_codecs = i; 2490 caps->direction = wm_adsp_fw[fw].compr_direction; 2491 2492 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE; 2493 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE; 2494 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS; 2495 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS; 2496 } 2497 2498 return 0; 2499 } 2500 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); 2501 2502 static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, 2503 unsigned int mem_addr, 2504 unsigned int num_words, u32 *data) 2505 { 2506 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 2507 unsigned int i, reg; 2508 int ret; 2509 2510 if (!mem) 2511 return -EINVAL; 2512 2513 reg = wm_adsp_region_to_reg(mem, mem_addr); 2514 2515 ret = regmap_raw_read(dsp->regmap, reg, data, 2516 sizeof(*data) * num_words); 2517 if (ret < 0) 2518 return ret; 2519 2520 for (i = 0; i < num_words; ++i) 2521 data[i] = be32_to_cpu(data[i]) & 0x00ffffffu; 2522 2523 return 0; 2524 } 2525 2526 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type, 2527 unsigned int mem_addr, u32 *data) 2528 { 2529 return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data); 2530 } 2531 2532 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, 2533 unsigned int mem_addr, u32 data) 2534 { 2535 struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); 2536 unsigned int reg; 2537 2538 if (!mem) 2539 return -EINVAL; 2540 2541 reg = wm_adsp_region_to_reg(mem, mem_addr); 2542 2543 data = cpu_to_be32(data & 0x00ffffffu); 2544 2545 return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data)); 2546 } 2547 2548 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, 2549 unsigned int field_offset, u32 *data) 2550 { 2551 return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM, 2552 buf->host_buf_ptr + field_offset, data); 2553 } 2554 2555 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, 2556 unsigned int field_offset, u32 data) 2557 { 2558 return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM, 2559 buf->host_buf_ptr + field_offset, data); 2560 } 2561 2562 static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf) 2563 { 2564 struct wm_adsp_alg_region *alg_region; 2565 struct wm_adsp *dsp = buf->dsp; 2566 u32 xmalg, addr, magic; 2567 int i, ret; 2568 2569 alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id); 2570 xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32); 2571 2572 addr = alg_region->base + xmalg + ALG_XM_FIELD(magic); 2573 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic); 2574 if (ret < 0) 2575 return ret; 2576 2577 if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC) 2578 return -EINVAL; 2579 2580 addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr); 2581 for (i = 0; i < 5; ++i) { 2582 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, 2583 &buf->host_buf_ptr); 2584 if (ret < 0) 2585 return ret; 2586 2587 if (buf->host_buf_ptr) 2588 break; 2589 2590 usleep_range(1000, 2000); 2591 } 2592 2593 if (!buf->host_buf_ptr) 2594 return -EIO; 2595 2596 adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr); 2597 2598 return 0; 2599 } 2600 2601 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) 2602 { 2603 const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; 2604 struct wm_adsp_buffer_region *region; 2605 u32 offset = 0; 2606 int i, ret; 2607 2608 for (i = 0; i < caps->num_regions; ++i) { 2609 region = &buf->regions[i]; 2610 2611 region->offset = offset; 2612 region->mem_type = caps->region_defs[i].mem_type; 2613 2614 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset, 2615 ®ion->base_addr); 2616 if (ret < 0) 2617 return ret; 2618 2619 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset, 2620 &offset); 2621 if (ret < 0) 2622 return ret; 2623 2624 region->cumulative_size = offset; 2625 2626 adsp_dbg(buf->dsp, 2627 "region=%d type=%d base=%04x off=%04x size=%04x\n", 2628 i, region->mem_type, region->base_addr, 2629 region->offset, region->cumulative_size); 2630 } 2631 2632 return 0; 2633 } 2634 2635 static int wm_adsp_buffer_init(struct wm_adsp *dsp) 2636 { 2637 struct wm_adsp_compr_buf *buf; 2638 int ret; 2639 2640 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 2641 if (!buf) 2642 return -ENOMEM; 2643 2644 buf->dsp = dsp; 2645 buf->read_index = -1; 2646 buf->irq_count = 0xFFFFFFFF; 2647 2648 ret = wm_adsp_buffer_locate(buf); 2649 if (ret < 0) { 2650 adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret); 2651 goto err_buffer; 2652 } 2653 2654 buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions, 2655 sizeof(*buf->regions), GFP_KERNEL); 2656 if (!buf->regions) { 2657 ret = -ENOMEM; 2658 goto err_buffer; 2659 } 2660 2661 ret = wm_adsp_buffer_populate(buf); 2662 if (ret < 0) { 2663 adsp_err(dsp, "Failed to populate host buffer: %d\n", ret); 2664 goto err_regions; 2665 } 2666 2667 dsp->buffer = buf; 2668 2669 return 0; 2670 2671 err_regions: 2672 kfree(buf->regions); 2673 err_buffer: 2674 kfree(buf); 2675 return ret; 2676 } 2677 2678 static int wm_adsp_buffer_free(struct wm_adsp *dsp) 2679 { 2680 if (dsp->buffer) { 2681 kfree(dsp->buffer->regions); 2682 kfree(dsp->buffer); 2683 2684 dsp->buffer = NULL; 2685 } 2686 2687 return 0; 2688 } 2689 2690 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr) 2691 { 2692 return compr->buf != NULL; 2693 } 2694 2695 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr) 2696 { 2697 /* 2698 * Note this will be more complex once each DSP can support multiple 2699 * streams 2700 */ 2701 if (!compr->dsp->buffer) 2702 return -EINVAL; 2703 2704 compr->buf = compr->dsp->buffer; 2705 2706 return 0; 2707 } 2708 2709 int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd) 2710 { 2711 struct wm_adsp_compr *compr = stream->runtime->private_data; 2712 struct wm_adsp *dsp = compr->dsp; 2713 int ret = 0; 2714 2715 adsp_dbg(dsp, "Trigger: %d\n", cmd); 2716 2717 mutex_lock(&dsp->pwr_lock); 2718 2719 switch (cmd) { 2720 case SNDRV_PCM_TRIGGER_START: 2721 if (wm_adsp_compr_attached(compr)) 2722 break; 2723 2724 ret = wm_adsp_compr_attach(compr); 2725 if (ret < 0) { 2726 adsp_err(dsp, "Failed to link buffer and stream: %d\n", 2727 ret); 2728 break; 2729 } 2730 2731 /* Trigger the IRQ at one fragment of data */ 2732 ret = wm_adsp_buffer_write(compr->buf, 2733 HOST_BUFFER_FIELD(high_water_mark), 2734 wm_adsp_compr_frag_words(compr)); 2735 if (ret < 0) { 2736 adsp_err(dsp, "Failed to set high water mark: %d\n", 2737 ret); 2738 break; 2739 } 2740 break; 2741 case SNDRV_PCM_TRIGGER_STOP: 2742 break; 2743 default: 2744 ret = -EINVAL; 2745 break; 2746 } 2747 2748 mutex_unlock(&dsp->pwr_lock); 2749 2750 return ret; 2751 } 2752 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger); 2753 2754 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf) 2755 { 2756 int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1; 2757 2758 return buf->regions[last_region].cumulative_size; 2759 } 2760 2761 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) 2762 { 2763 u32 next_read_index, next_write_index; 2764 int write_index, read_index, avail; 2765 int ret; 2766 2767 /* Only sync read index if we haven't already read a valid index */ 2768 if (buf->read_index < 0) { 2769 ret = wm_adsp_buffer_read(buf, 2770 HOST_BUFFER_FIELD(next_read_index), 2771 &next_read_index); 2772 if (ret < 0) 2773 return ret; 2774 2775 read_index = sign_extend32(next_read_index, 23); 2776 2777 if (read_index < 0) { 2778 adsp_dbg(buf->dsp, "Avail check on unstarted stream\n"); 2779 return 0; 2780 } 2781 2782 buf->read_index = read_index; 2783 } 2784 2785 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index), 2786 &next_write_index); 2787 if (ret < 0) 2788 return ret; 2789 2790 write_index = sign_extend32(next_write_index, 23); 2791 2792 avail = write_index - buf->read_index; 2793 if (avail < 0) 2794 avail += wm_adsp_buffer_size(buf); 2795 2796 adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n", 2797 buf->read_index, write_index, avail); 2798 2799 buf->avail = avail; 2800 2801 return 0; 2802 } 2803 2804 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) 2805 { 2806 struct wm_adsp_compr_buf *buf = dsp->buffer; 2807 struct wm_adsp_compr *compr = dsp->compr; 2808 int ret = 0; 2809 2810 mutex_lock(&dsp->pwr_lock); 2811 2812 if (!buf) { 2813 adsp_err(dsp, "Spurious buffer IRQ\n"); 2814 ret = -ENODEV; 2815 goto out; 2816 } 2817 2818 adsp_dbg(dsp, "Handling buffer IRQ\n"); 2819 2820 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error); 2821 if (ret < 0) { 2822 adsp_err(dsp, "Failed to check buffer error: %d\n", ret); 2823 goto out; 2824 } 2825 if (buf->error != 0) { 2826 adsp_err(dsp, "Buffer error occurred: %d\n", buf->error); 2827 ret = -EIO; 2828 goto out; 2829 } 2830 2831 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count), 2832 &buf->irq_count); 2833 if (ret < 0) { 2834 adsp_err(dsp, "Failed to get irq_count: %d\n", ret); 2835 goto out; 2836 } 2837 2838 ret = wm_adsp_buffer_update_avail(buf); 2839 if (ret < 0) { 2840 adsp_err(dsp, "Error reading avail: %d\n", ret); 2841 goto out; 2842 } 2843 2844 if (compr->stream) 2845 snd_compr_fragment_elapsed(compr->stream); 2846 2847 out: 2848 mutex_unlock(&dsp->pwr_lock); 2849 2850 return ret; 2851 } 2852 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq); 2853 2854 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf) 2855 { 2856 if (buf->irq_count & 0x01) 2857 return 0; 2858 2859 adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n", 2860 buf->irq_count); 2861 2862 buf->irq_count |= 0x01; 2863 2864 return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack), 2865 buf->irq_count); 2866 } 2867 2868 int wm_adsp_compr_pointer(struct snd_compr_stream *stream, 2869 struct snd_compr_tstamp *tstamp) 2870 { 2871 struct wm_adsp_compr *compr = stream->runtime->private_data; 2872 struct wm_adsp_compr_buf *buf = compr->buf; 2873 struct wm_adsp *dsp = compr->dsp; 2874 int ret = 0; 2875 2876 adsp_dbg(dsp, "Pointer request\n"); 2877 2878 mutex_lock(&dsp->pwr_lock); 2879 2880 if (!compr->buf) { 2881 ret = -ENXIO; 2882 goto out; 2883 } 2884 2885 if (compr->buf->error) { 2886 ret = -EIO; 2887 goto out; 2888 } 2889 2890 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 2891 ret = wm_adsp_buffer_update_avail(buf); 2892 if (ret < 0) { 2893 adsp_err(dsp, "Error reading avail: %d\n", ret); 2894 goto out; 2895 } 2896 2897 /* 2898 * If we really have less than 1 fragment available tell the 2899 * DSP to inform us once a whole fragment is available. 2900 */ 2901 if (buf->avail < wm_adsp_compr_frag_words(compr)) { 2902 ret = wm_adsp_buffer_reenable_irq(buf); 2903 if (ret < 0) { 2904 adsp_err(dsp, 2905 "Failed to re-enable buffer IRQ: %d\n", 2906 ret); 2907 goto out; 2908 } 2909 } 2910 } 2911 2912 tstamp->copied_total = compr->copied_total; 2913 tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE; 2914 2915 out: 2916 mutex_unlock(&dsp->pwr_lock); 2917 2918 return ret; 2919 } 2920 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer); 2921 2922 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) 2923 { 2924 struct wm_adsp_compr_buf *buf = compr->buf; 2925 u8 *pack_in = (u8 *)compr->raw_buf; 2926 u8 *pack_out = (u8 *)compr->raw_buf; 2927 unsigned int adsp_addr; 2928 int mem_type, nwords, max_read; 2929 int i, j, ret; 2930 2931 /* Calculate read parameters */ 2932 for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i) 2933 if (buf->read_index < buf->regions[i].cumulative_size) 2934 break; 2935 2936 if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions) 2937 return -EINVAL; 2938 2939 mem_type = buf->regions[i].mem_type; 2940 adsp_addr = buf->regions[i].base_addr + 2941 (buf->read_index - buf->regions[i].offset); 2942 2943 max_read = wm_adsp_compr_frag_words(compr); 2944 nwords = buf->regions[i].cumulative_size - buf->read_index; 2945 2946 if (nwords > target) 2947 nwords = target; 2948 if (nwords > buf->avail) 2949 nwords = buf->avail; 2950 if (nwords > max_read) 2951 nwords = max_read; 2952 if (!nwords) 2953 return 0; 2954 2955 /* Read data from DSP */ 2956 ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, 2957 nwords, compr->raw_buf); 2958 if (ret < 0) 2959 return ret; 2960 2961 /* Remove the padding bytes from the data read from the DSP */ 2962 for (i = 0; i < nwords; i++) { 2963 for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++) 2964 *pack_out++ = *pack_in++; 2965 2966 pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE; 2967 } 2968 2969 /* update read index to account for words read */ 2970 buf->read_index += nwords; 2971 if (buf->read_index == wm_adsp_buffer_size(buf)) 2972 buf->read_index = 0; 2973 2974 ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index), 2975 buf->read_index); 2976 if (ret < 0) 2977 return ret; 2978 2979 /* update avail to account for words read */ 2980 buf->avail -= nwords; 2981 2982 return nwords; 2983 } 2984 2985 static int wm_adsp_compr_read(struct wm_adsp_compr *compr, 2986 char __user *buf, size_t count) 2987 { 2988 struct wm_adsp *dsp = compr->dsp; 2989 int ntotal = 0; 2990 int nwords, nbytes; 2991 2992 adsp_dbg(dsp, "Requested read of %zu bytes\n", count); 2993 2994 if (!compr->buf) 2995 return -ENXIO; 2996 2997 if (compr->buf->error) 2998 return -EIO; 2999 3000 count /= WM_ADSP_DATA_WORD_SIZE; 3001 3002 do { 3003 nwords = wm_adsp_buffer_capture_block(compr, count); 3004 if (nwords < 0) { 3005 adsp_err(dsp, "Failed to capture block: %d\n", nwords); 3006 return nwords; 3007 } 3008 3009 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE; 3010 3011 adsp_dbg(dsp, "Read %d bytes\n", nbytes); 3012 3013 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) { 3014 adsp_err(dsp, "Failed to copy data to user: %d, %d\n", 3015 ntotal, nbytes); 3016 return -EFAULT; 3017 } 3018 3019 count -= nwords; 3020 ntotal += nbytes; 3021 } while (nwords > 0 && count > 0); 3022 3023 compr->copied_total += ntotal; 3024 3025 return ntotal; 3026 } 3027 3028 int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf, 3029 size_t count) 3030 { 3031 struct wm_adsp_compr *compr = stream->runtime->private_data; 3032 struct wm_adsp *dsp = compr->dsp; 3033 int ret; 3034 3035 mutex_lock(&dsp->pwr_lock); 3036 3037 if (stream->direction == SND_COMPRESS_CAPTURE) 3038 ret = wm_adsp_compr_read(compr, buf, count); 3039 else 3040 ret = -ENOTSUPP; 3041 3042 mutex_unlock(&dsp->pwr_lock); 3043 3044 return ret; 3045 } 3046 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy); 3047 3048 MODULE_LICENSE("GPL v2"); 3049