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