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