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