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 <sound/core.h> 25 #include <sound/pcm.h> 26 #include <sound/pcm_params.h> 27 #include <sound/soc.h> 28 #include <sound/jack.h> 29 #include <sound/initval.h> 30 #include <sound/tlv.h> 31 32 #include <linux/mfd/arizona/registers.h> 33 34 #include "wm_adsp.h" 35 36 #define adsp_crit(_dsp, fmt, ...) \ 37 dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 38 #define adsp_err(_dsp, fmt, ...) \ 39 dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 40 #define adsp_warn(_dsp, fmt, ...) \ 41 dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 42 #define adsp_info(_dsp, fmt, ...) \ 43 dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 44 #define adsp_dbg(_dsp, fmt, ...) \ 45 dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 46 47 #define ADSP1_CONTROL_1 0x00 48 #define ADSP1_CONTROL_2 0x02 49 #define ADSP1_CONTROL_3 0x03 50 #define ADSP1_CONTROL_4 0x04 51 #define ADSP1_CONTROL_5 0x06 52 #define ADSP1_CONTROL_6 0x07 53 #define ADSP1_CONTROL_7 0x08 54 #define ADSP1_CONTROL_8 0x09 55 #define ADSP1_CONTROL_9 0x0A 56 #define ADSP1_CONTROL_10 0x0B 57 #define ADSP1_CONTROL_11 0x0C 58 #define ADSP1_CONTROL_12 0x0D 59 #define ADSP1_CONTROL_13 0x0F 60 #define ADSP1_CONTROL_14 0x10 61 #define ADSP1_CONTROL_15 0x11 62 #define ADSP1_CONTROL_16 0x12 63 #define ADSP1_CONTROL_17 0x13 64 #define ADSP1_CONTROL_18 0x14 65 #define ADSP1_CONTROL_19 0x16 66 #define ADSP1_CONTROL_20 0x17 67 #define ADSP1_CONTROL_21 0x18 68 #define ADSP1_CONTROL_22 0x1A 69 #define ADSP1_CONTROL_23 0x1B 70 #define ADSP1_CONTROL_24 0x1C 71 #define ADSP1_CONTROL_25 0x1E 72 #define ADSP1_CONTROL_26 0x20 73 #define ADSP1_CONTROL_27 0x21 74 #define ADSP1_CONTROL_28 0x22 75 #define ADSP1_CONTROL_29 0x23 76 #define ADSP1_CONTROL_30 0x24 77 #define ADSP1_CONTROL_31 0x26 78 79 /* 80 * ADSP1 Control 19 81 */ 82 #define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 83 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 84 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 85 86 87 /* 88 * ADSP1 Control 30 89 */ 90 #define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */ 91 #define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */ 92 #define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */ 93 #define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */ 94 #define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 95 #define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 96 #define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 97 #define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 98 #define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 99 #define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 100 #define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 101 #define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 102 #define ADSP1_START 0x0001 /* DSP1_START */ 103 #define ADSP1_START_MASK 0x0001 /* DSP1_START */ 104 #define ADSP1_START_SHIFT 0 /* DSP1_START */ 105 #define ADSP1_START_WIDTH 1 /* DSP1_START */ 106 107 /* 108 * ADSP1 Control 31 109 */ 110 #define ADSP1_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 111 #define ADSP1_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 112 #define ADSP1_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 113 114 #define ADSP2_CONTROL 0x0 115 #define ADSP2_CLOCKING 0x1 116 #define ADSP2_STATUS1 0x4 117 #define ADSP2_WDMA_CONFIG_1 0x30 118 #define ADSP2_WDMA_CONFIG_2 0x31 119 #define ADSP2_RDMA_CONFIG_1 0x34 120 121 /* 122 * ADSP2 Control 123 */ 124 125 #define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */ 126 #define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */ 127 #define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */ 128 #define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */ 129 #define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 130 #define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 131 #define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 132 #define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 133 #define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 134 #define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 135 #define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 136 #define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 137 #define ADSP2_START 0x0001 /* DSP1_START */ 138 #define ADSP2_START_MASK 0x0001 /* DSP1_START */ 139 #define ADSP2_START_SHIFT 0 /* DSP1_START */ 140 #define ADSP2_START_WIDTH 1 /* DSP1_START */ 141 142 /* 143 * ADSP2 clocking 144 */ 145 #define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 146 #define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 147 #define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 148 149 /* 150 * ADSP2 Status 1 151 */ 152 #define ADSP2_RAM_RDY 0x0001 153 #define ADSP2_RAM_RDY_MASK 0x0001 154 #define ADSP2_RAM_RDY_SHIFT 0 155 #define ADSP2_RAM_RDY_WIDTH 1 156 157 struct wm_adsp_buf { 158 struct list_head list; 159 void *buf; 160 }; 161 162 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len, 163 struct list_head *list) 164 { 165 struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL); 166 167 if (buf == NULL) 168 return NULL; 169 170 buf->buf = kmemdup(src, len, GFP_KERNEL | GFP_DMA); 171 if (!buf->buf) { 172 kfree(buf); 173 return NULL; 174 } 175 176 if (list) 177 list_add_tail(&buf->list, list); 178 179 return buf; 180 } 181 182 static void wm_adsp_buf_free(struct list_head *list) 183 { 184 while (!list_empty(list)) { 185 struct wm_adsp_buf *buf = list_first_entry(list, 186 struct wm_adsp_buf, 187 list); 188 list_del(&buf->list); 189 kfree(buf->buf); 190 kfree(buf); 191 } 192 } 193 194 #define WM_ADSP_NUM_FW 4 195 196 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { 197 "MBC/VSS", "Tx", "Tx Speaker", "Rx ANC" 198 }; 199 200 static struct { 201 const char *file; 202 } wm_adsp_fw[WM_ADSP_NUM_FW] = { 203 { .file = "mbc-vss" }, 204 { .file = "tx" }, 205 { .file = "tx-spk" }, 206 { .file = "rx-anc" }, 207 }; 208 209 static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 210 struct snd_ctl_elem_value *ucontrol) 211 { 212 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 213 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 214 struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec); 215 216 ucontrol->value.integer.value[0] = adsp[e->shift_l].fw; 217 218 return 0; 219 } 220 221 static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, 222 struct snd_ctl_elem_value *ucontrol) 223 { 224 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 225 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 226 struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec); 227 228 if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw) 229 return 0; 230 231 if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW) 232 return -EINVAL; 233 234 if (adsp[e->shift_l].running) 235 return -EBUSY; 236 237 adsp[e->shift_l].fw = ucontrol->value.integer.value[0]; 238 239 return 0; 240 } 241 242 static const struct soc_enum wm_adsp_fw_enum[] = { 243 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 244 SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 245 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 246 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 247 }; 248 249 const struct snd_kcontrol_new wm_adsp_fw_controls[] = { 250 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], 251 wm_adsp_fw_get, wm_adsp_fw_put), 252 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], 253 wm_adsp_fw_get, wm_adsp_fw_put), 254 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], 255 wm_adsp_fw_get, wm_adsp_fw_put), 256 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], 257 wm_adsp_fw_get, wm_adsp_fw_put), 258 }; 259 EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); 260 261 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, 262 int type) 263 { 264 int i; 265 266 for (i = 0; i < dsp->num_mems; i++) 267 if (dsp->mem[i].type == type) 268 return &dsp->mem[i]; 269 270 return NULL; 271 } 272 273 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region, 274 unsigned int offset) 275 { 276 switch (region->type) { 277 case WMFW_ADSP1_PM: 278 return region->base + (offset * 3); 279 case WMFW_ADSP1_DM: 280 return region->base + (offset * 2); 281 case WMFW_ADSP2_XM: 282 return region->base + (offset * 2); 283 case WMFW_ADSP2_YM: 284 return region->base + (offset * 2); 285 case WMFW_ADSP1_ZM: 286 return region->base + (offset * 2); 287 default: 288 WARN_ON(NULL != "Unknown memory region type"); 289 return offset; 290 } 291 } 292 293 static int wm_adsp_load(struct wm_adsp *dsp) 294 { 295 LIST_HEAD(buf_list); 296 const struct firmware *firmware; 297 struct regmap *regmap = dsp->regmap; 298 unsigned int pos = 0; 299 const struct wmfw_header *header; 300 const struct wmfw_adsp1_sizes *adsp1_sizes; 301 const struct wmfw_adsp2_sizes *adsp2_sizes; 302 const struct wmfw_footer *footer; 303 const struct wmfw_region *region; 304 const struct wm_adsp_region *mem; 305 const char *region_name; 306 char *file, *text; 307 struct wm_adsp_buf *buf; 308 unsigned int reg; 309 int regions = 0; 310 int ret, offset, type, sizes; 311 312 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 313 if (file == NULL) 314 return -ENOMEM; 315 316 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num, 317 wm_adsp_fw[dsp->fw].file); 318 file[PAGE_SIZE - 1] = '\0'; 319 320 ret = request_firmware(&firmware, file, dsp->dev); 321 if (ret != 0) { 322 adsp_err(dsp, "Failed to request '%s'\n", file); 323 goto out; 324 } 325 ret = -EINVAL; 326 327 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 328 if (pos >= firmware->size) { 329 adsp_err(dsp, "%s: file too short, %zu bytes\n", 330 file, firmware->size); 331 goto out_fw; 332 } 333 334 header = (void*)&firmware->data[0]; 335 336 if (memcmp(&header->magic[0], "WMFW", 4) != 0) { 337 adsp_err(dsp, "%s: invalid magic\n", file); 338 goto out_fw; 339 } 340 341 if (header->ver != 0) { 342 adsp_err(dsp, "%s: unknown file format %d\n", 343 file, header->ver); 344 goto out_fw; 345 } 346 347 if (header->core != dsp->type) { 348 adsp_err(dsp, "%s: invalid core %d != %d\n", 349 file, header->core, dsp->type); 350 goto out_fw; 351 } 352 353 switch (dsp->type) { 354 case WMFW_ADSP1: 355 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 356 adsp1_sizes = (void *)&(header[1]); 357 footer = (void *)&(adsp1_sizes[1]); 358 sizes = sizeof(*adsp1_sizes); 359 360 adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", 361 file, le32_to_cpu(adsp1_sizes->dm), 362 le32_to_cpu(adsp1_sizes->pm), 363 le32_to_cpu(adsp1_sizes->zm)); 364 break; 365 366 case WMFW_ADSP2: 367 pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer); 368 adsp2_sizes = (void *)&(header[1]); 369 footer = (void *)&(adsp2_sizes[1]); 370 sizes = sizeof(*adsp2_sizes); 371 372 adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", 373 file, le32_to_cpu(adsp2_sizes->xm), 374 le32_to_cpu(adsp2_sizes->ym), 375 le32_to_cpu(adsp2_sizes->pm), 376 le32_to_cpu(adsp2_sizes->zm)); 377 break; 378 379 default: 380 BUG_ON(NULL == "Unknown DSP type"); 381 goto out_fw; 382 } 383 384 if (le32_to_cpu(header->len) != sizeof(*header) + 385 sizes + sizeof(*footer)) { 386 adsp_err(dsp, "%s: unexpected header length %d\n", 387 file, le32_to_cpu(header->len)); 388 goto out_fw; 389 } 390 391 adsp_dbg(dsp, "%s: timestamp %llu\n", file, 392 le64_to_cpu(footer->timestamp)); 393 394 while (pos < firmware->size && 395 pos - firmware->size > sizeof(*region)) { 396 region = (void *)&(firmware->data[pos]); 397 region_name = "Unknown"; 398 reg = 0; 399 text = NULL; 400 offset = le32_to_cpu(region->offset) & 0xffffff; 401 type = be32_to_cpu(region->type) & 0xff; 402 mem = wm_adsp_find_region(dsp, type); 403 404 switch (type) { 405 case WMFW_NAME_TEXT: 406 region_name = "Firmware name"; 407 text = kzalloc(le32_to_cpu(region->len) + 1, 408 GFP_KERNEL); 409 break; 410 case WMFW_INFO_TEXT: 411 region_name = "Information"; 412 text = kzalloc(le32_to_cpu(region->len) + 1, 413 GFP_KERNEL); 414 break; 415 case WMFW_ABSOLUTE: 416 region_name = "Absolute"; 417 reg = offset; 418 break; 419 case WMFW_ADSP1_PM: 420 BUG_ON(!mem); 421 region_name = "PM"; 422 reg = wm_adsp_region_to_reg(mem, offset); 423 break; 424 case WMFW_ADSP1_DM: 425 BUG_ON(!mem); 426 region_name = "DM"; 427 reg = wm_adsp_region_to_reg(mem, offset); 428 break; 429 case WMFW_ADSP2_XM: 430 BUG_ON(!mem); 431 region_name = "XM"; 432 reg = wm_adsp_region_to_reg(mem, offset); 433 break; 434 case WMFW_ADSP2_YM: 435 BUG_ON(!mem); 436 region_name = "YM"; 437 reg = wm_adsp_region_to_reg(mem, offset); 438 break; 439 case WMFW_ADSP1_ZM: 440 BUG_ON(!mem); 441 region_name = "ZM"; 442 reg = wm_adsp_region_to_reg(mem, offset); 443 break; 444 default: 445 adsp_warn(dsp, 446 "%s.%d: Unknown region type %x at %d(%x)\n", 447 file, regions, type, pos, pos); 448 break; 449 } 450 451 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 452 regions, le32_to_cpu(region->len), offset, 453 region_name); 454 455 if (text) { 456 memcpy(text, region->data, le32_to_cpu(region->len)); 457 adsp_info(dsp, "%s: %s\n", file, text); 458 kfree(text); 459 } 460 461 if (reg) { 462 buf = wm_adsp_buf_alloc(region->data, 463 le32_to_cpu(region->len), 464 &buf_list); 465 if (!buf) { 466 adsp_err(dsp, "Out of memory\n"); 467 return -ENOMEM; 468 } 469 470 ret = regmap_raw_write_async(regmap, reg, buf->buf, 471 le32_to_cpu(region->len)); 472 if (ret != 0) { 473 adsp_err(dsp, 474 "%s.%d: Failed to write %d bytes at %d in %s: %d\n", 475 file, regions, 476 le32_to_cpu(region->len), offset, 477 region_name, ret); 478 goto out_fw; 479 } 480 } 481 482 pos += le32_to_cpu(region->len) + sizeof(*region); 483 regions++; 484 } 485 486 ret = regmap_async_complete(regmap); 487 if (ret != 0) { 488 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 489 goto out_fw; 490 } 491 492 if (pos > firmware->size) 493 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 494 file, regions, pos - firmware->size); 495 496 out_fw: 497 regmap_async_complete(regmap); 498 wm_adsp_buf_free(&buf_list); 499 release_firmware(firmware); 500 out: 501 kfree(file); 502 503 return ret; 504 } 505 506 static int wm_adsp_setup_algs(struct wm_adsp *dsp) 507 { 508 struct regmap *regmap = dsp->regmap; 509 struct wmfw_adsp1_id_hdr adsp1_id; 510 struct wmfw_adsp2_id_hdr adsp2_id; 511 struct wmfw_adsp1_alg_hdr *adsp1_alg; 512 struct wmfw_adsp2_alg_hdr *adsp2_alg; 513 void *alg, *buf; 514 struct wm_adsp_alg_region *region; 515 const struct wm_adsp_region *mem; 516 unsigned int pos, term; 517 size_t algs, buf_size; 518 __be32 val; 519 int i, ret; 520 521 switch (dsp->type) { 522 case WMFW_ADSP1: 523 mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM); 524 break; 525 case WMFW_ADSP2: 526 mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM); 527 break; 528 default: 529 mem = NULL; 530 break; 531 } 532 533 if (mem == NULL) { 534 BUG_ON(mem != NULL); 535 return -EINVAL; 536 } 537 538 switch (dsp->type) { 539 case WMFW_ADSP1: 540 ret = regmap_raw_read(regmap, mem->base, &adsp1_id, 541 sizeof(adsp1_id)); 542 if (ret != 0) { 543 adsp_err(dsp, "Failed to read algorithm info: %d\n", 544 ret); 545 return ret; 546 } 547 548 buf = &adsp1_id; 549 buf_size = sizeof(adsp1_id); 550 551 algs = be32_to_cpu(adsp1_id.algs); 552 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 553 be32_to_cpu(adsp1_id.fw.id), 554 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, 555 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, 556 be32_to_cpu(adsp1_id.fw.ver) & 0xff, 557 algs); 558 559 pos = sizeof(adsp1_id) / 2; 560 term = pos + ((sizeof(*adsp1_alg) * algs) / 2); 561 break; 562 563 case WMFW_ADSP2: 564 ret = regmap_raw_read(regmap, mem->base, &adsp2_id, 565 sizeof(adsp2_id)); 566 if (ret != 0) { 567 adsp_err(dsp, "Failed to read algorithm info: %d\n", 568 ret); 569 return ret; 570 } 571 572 buf = &adsp2_id; 573 buf_size = sizeof(adsp2_id); 574 575 algs = be32_to_cpu(adsp2_id.algs); 576 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 577 be32_to_cpu(adsp2_id.fw.id), 578 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, 579 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, 580 be32_to_cpu(adsp2_id.fw.ver) & 0xff, 581 algs); 582 583 pos = sizeof(adsp2_id) / 2; 584 term = pos + ((sizeof(*adsp2_alg) * algs) / 2); 585 break; 586 587 default: 588 BUG_ON(NULL == "Unknown DSP type"); 589 return -EINVAL; 590 } 591 592 if (algs == 0) { 593 adsp_err(dsp, "No algorithms\n"); 594 return -EINVAL; 595 } 596 597 if (algs > 1024) { 598 adsp_err(dsp, "Algorithm count %zx excessive\n", algs); 599 print_hex_dump_bytes(dev_name(dsp->dev), DUMP_PREFIX_OFFSET, 600 buf, buf_size); 601 return -EINVAL; 602 } 603 604 /* Read the terminator first to validate the length */ 605 ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val)); 606 if (ret != 0) { 607 adsp_err(dsp, "Failed to read algorithm list end: %d\n", 608 ret); 609 return ret; 610 } 611 612 if (be32_to_cpu(val) != 0xbedead) 613 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n", 614 term, be32_to_cpu(val)); 615 616 alg = kzalloc((term - pos) * 2, GFP_KERNEL | GFP_DMA); 617 if (!alg) 618 return -ENOMEM; 619 620 ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2); 621 if (ret != 0) { 622 adsp_err(dsp, "Failed to read algorithm list: %d\n", 623 ret); 624 goto out; 625 } 626 627 adsp1_alg = alg; 628 adsp2_alg = alg; 629 630 for (i = 0; i < algs; i++) { 631 switch (dsp->type) { 632 case WMFW_ADSP1: 633 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", 634 i, be32_to_cpu(adsp1_alg[i].alg.id), 635 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, 636 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, 637 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, 638 be32_to_cpu(adsp1_alg[i].dm), 639 be32_to_cpu(adsp1_alg[i].zm)); 640 641 region = kzalloc(sizeof(*region), GFP_KERNEL); 642 if (!region) 643 return -ENOMEM; 644 region->type = WMFW_ADSP1_DM; 645 region->alg = be32_to_cpu(adsp1_alg[i].alg.id); 646 region->base = be32_to_cpu(adsp1_alg[i].dm); 647 list_add_tail(®ion->list, &dsp->alg_regions); 648 649 region = kzalloc(sizeof(*region), GFP_KERNEL); 650 if (!region) 651 return -ENOMEM; 652 region->type = WMFW_ADSP1_ZM; 653 region->alg = be32_to_cpu(adsp1_alg[i].alg.id); 654 region->base = be32_to_cpu(adsp1_alg[i].zm); 655 list_add_tail(®ion->list, &dsp->alg_regions); 656 break; 657 658 case WMFW_ADSP2: 659 adsp_info(dsp, 660 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", 661 i, be32_to_cpu(adsp2_alg[i].alg.id), 662 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, 663 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, 664 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, 665 be32_to_cpu(adsp2_alg[i].xm), 666 be32_to_cpu(adsp2_alg[i].ym), 667 be32_to_cpu(adsp2_alg[i].zm)); 668 669 region = kzalloc(sizeof(*region), GFP_KERNEL); 670 if (!region) 671 return -ENOMEM; 672 region->type = WMFW_ADSP2_XM; 673 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 674 region->base = be32_to_cpu(adsp2_alg[i].xm); 675 list_add_tail(®ion->list, &dsp->alg_regions); 676 677 region = kzalloc(sizeof(*region), GFP_KERNEL); 678 if (!region) 679 return -ENOMEM; 680 region->type = WMFW_ADSP2_YM; 681 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 682 region->base = be32_to_cpu(adsp2_alg[i].ym); 683 list_add_tail(®ion->list, &dsp->alg_regions); 684 685 region = kzalloc(sizeof(*region), GFP_KERNEL); 686 if (!region) 687 return -ENOMEM; 688 region->type = WMFW_ADSP2_ZM; 689 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 690 region->base = be32_to_cpu(adsp2_alg[i].zm); 691 list_add_tail(®ion->list, &dsp->alg_regions); 692 break; 693 } 694 } 695 696 out: 697 kfree(alg); 698 return ret; 699 } 700 701 static int wm_adsp_load_coeff(struct wm_adsp *dsp) 702 { 703 LIST_HEAD(buf_list); 704 struct regmap *regmap = dsp->regmap; 705 struct wmfw_coeff_hdr *hdr; 706 struct wmfw_coeff_item *blk; 707 const struct firmware *firmware; 708 const struct wm_adsp_region *mem; 709 struct wm_adsp_alg_region *alg_region; 710 const char *region_name; 711 int ret, pos, blocks, type, offset, reg; 712 char *file; 713 struct wm_adsp_buf *buf; 714 int tmp; 715 716 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 717 if (file == NULL) 718 return -ENOMEM; 719 720 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num, 721 wm_adsp_fw[dsp->fw].file); 722 file[PAGE_SIZE - 1] = '\0'; 723 724 ret = request_firmware(&firmware, file, dsp->dev); 725 if (ret != 0) { 726 adsp_warn(dsp, "Failed to request '%s'\n", file); 727 ret = 0; 728 goto out; 729 } 730 ret = -EINVAL; 731 732 if (sizeof(*hdr) >= firmware->size) { 733 adsp_err(dsp, "%s: file too short, %zu bytes\n", 734 file, firmware->size); 735 goto out_fw; 736 } 737 738 hdr = (void*)&firmware->data[0]; 739 if (memcmp(hdr->magic, "WMDR", 4) != 0) { 740 adsp_err(dsp, "%s: invalid magic\n", file); 741 goto out_fw; 742 } 743 744 switch (be32_to_cpu(hdr->rev) & 0xff) { 745 case 1: 746 break; 747 default: 748 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n", 749 file, be32_to_cpu(hdr->rev) & 0xff); 750 ret = -EINVAL; 751 goto out_fw; 752 } 753 754 adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, 755 (le32_to_cpu(hdr->ver) >> 16) & 0xff, 756 (le32_to_cpu(hdr->ver) >> 8) & 0xff, 757 le32_to_cpu(hdr->ver) & 0xff); 758 759 pos = le32_to_cpu(hdr->len); 760 761 blocks = 0; 762 while (pos < firmware->size && 763 pos - firmware->size > sizeof(*blk)) { 764 blk = (void*)(&firmware->data[pos]); 765 766 type = le16_to_cpu(blk->type); 767 offset = le16_to_cpu(blk->offset); 768 769 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", 770 file, blocks, le32_to_cpu(blk->id), 771 (le32_to_cpu(blk->ver) >> 16) & 0xff, 772 (le32_to_cpu(blk->ver) >> 8) & 0xff, 773 le32_to_cpu(blk->ver) & 0xff); 774 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", 775 file, blocks, le32_to_cpu(blk->len), offset, type); 776 777 reg = 0; 778 region_name = "Unknown"; 779 switch (type) { 780 case (WMFW_NAME_TEXT << 8): 781 case (WMFW_INFO_TEXT << 8): 782 break; 783 case (WMFW_ABSOLUTE << 8): 784 region_name = "register"; 785 reg = offset; 786 break; 787 788 case WMFW_ADSP1_DM: 789 case WMFW_ADSP1_ZM: 790 case WMFW_ADSP2_XM: 791 case WMFW_ADSP2_YM: 792 adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", 793 file, blocks, le32_to_cpu(blk->len), 794 type, le32_to_cpu(blk->id)); 795 796 mem = wm_adsp_find_region(dsp, type); 797 if (!mem) { 798 adsp_err(dsp, "No base for region %x\n", type); 799 break; 800 } 801 802 reg = 0; 803 list_for_each_entry(alg_region, 804 &dsp->alg_regions, list) { 805 if (le32_to_cpu(blk->id) == alg_region->alg && 806 type == alg_region->type) { 807 reg = alg_region->base; 808 reg = wm_adsp_region_to_reg(mem, 809 reg); 810 reg += offset; 811 } 812 } 813 814 if (reg == 0) 815 adsp_err(dsp, "No %x for algorithm %x\n", 816 type, le32_to_cpu(blk->id)); 817 break; 818 819 default: 820 adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n", 821 file, blocks, type, pos); 822 break; 823 } 824 825 if (reg) { 826 buf = wm_adsp_buf_alloc(blk->data, 827 le32_to_cpu(blk->len), 828 &buf_list); 829 if (!buf) { 830 adsp_err(dsp, "Out of memory\n"); 831 ret = -ENOMEM; 832 goto out_fw; 833 } 834 835 adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", 836 file, blocks, le32_to_cpu(blk->len), 837 reg); 838 ret = regmap_raw_write_async(regmap, reg, buf->buf, 839 le32_to_cpu(blk->len)); 840 if (ret != 0) { 841 adsp_err(dsp, 842 "%s.%d: Failed to write to %x in %s\n", 843 file, blocks, reg, region_name); 844 } 845 } 846 847 tmp = le32_to_cpu(blk->len) % 4; 848 if (tmp) 849 pos += le32_to_cpu(blk->len) + (4 - tmp) + sizeof(*blk); 850 else 851 pos += le32_to_cpu(blk->len) + sizeof(*blk); 852 853 blocks++; 854 } 855 856 ret = regmap_async_complete(regmap); 857 if (ret != 0) 858 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 859 860 if (pos > firmware->size) 861 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 862 file, blocks, pos - firmware->size); 863 864 out_fw: 865 release_firmware(firmware); 866 wm_adsp_buf_free(&buf_list); 867 out: 868 kfree(file); 869 return ret; 870 } 871 872 int wm_adsp1_init(struct wm_adsp *adsp) 873 { 874 INIT_LIST_HEAD(&adsp->alg_regions); 875 876 return 0; 877 } 878 EXPORT_SYMBOL_GPL(wm_adsp1_init); 879 880 int wm_adsp1_event(struct snd_soc_dapm_widget *w, 881 struct snd_kcontrol *kcontrol, 882 int event) 883 { 884 struct snd_soc_codec *codec = w->codec; 885 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 886 struct wm_adsp *dsp = &dsps[w->shift]; 887 int ret; 888 int val; 889 890 switch (event) { 891 case SND_SOC_DAPM_POST_PMU: 892 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 893 ADSP1_SYS_ENA, ADSP1_SYS_ENA); 894 895 /* 896 * For simplicity set the DSP clock rate to be the 897 * SYSCLK rate rather than making it configurable. 898 */ 899 if(dsp->sysclk_reg) { 900 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); 901 if (ret != 0) { 902 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", 903 ret); 904 return ret; 905 } 906 907 val = (val & dsp->sysclk_mask) 908 >> dsp->sysclk_shift; 909 910 ret = regmap_update_bits(dsp->regmap, 911 dsp->base + ADSP1_CONTROL_31, 912 ADSP1_CLK_SEL_MASK, val); 913 if (ret != 0) { 914 adsp_err(dsp, "Failed to set clock rate: %d\n", 915 ret); 916 return ret; 917 } 918 } 919 920 ret = wm_adsp_load(dsp); 921 if (ret != 0) 922 goto err; 923 924 ret = wm_adsp_setup_algs(dsp); 925 if (ret != 0) 926 goto err; 927 928 ret = wm_adsp_load_coeff(dsp); 929 if (ret != 0) 930 goto err; 931 932 /* Start the core running */ 933 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 934 ADSP1_CORE_ENA | ADSP1_START, 935 ADSP1_CORE_ENA | ADSP1_START); 936 break; 937 938 case SND_SOC_DAPM_PRE_PMD: 939 /* Halt the core */ 940 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 941 ADSP1_CORE_ENA | ADSP1_START, 0); 942 943 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, 944 ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); 945 946 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 947 ADSP1_SYS_ENA, 0); 948 break; 949 950 default: 951 break; 952 } 953 954 return 0; 955 956 err: 957 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 958 ADSP1_SYS_ENA, 0); 959 return ret; 960 } 961 EXPORT_SYMBOL_GPL(wm_adsp1_event); 962 963 static int wm_adsp2_ena(struct wm_adsp *dsp) 964 { 965 unsigned int val; 966 int ret, count; 967 968 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 969 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 970 if (ret != 0) 971 return ret; 972 973 /* Wait for the RAM to start, should be near instantaneous */ 974 count = 0; 975 do { 976 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, 977 &val); 978 if (ret != 0) 979 return ret; 980 } while (!(val & ADSP2_RAM_RDY) && ++count < 10); 981 982 if (!(val & ADSP2_RAM_RDY)) { 983 adsp_err(dsp, "Failed to start DSP RAM\n"); 984 return -EBUSY; 985 } 986 987 adsp_dbg(dsp, "RAM ready after %d polls\n", count); 988 adsp_info(dsp, "RAM ready after %d polls\n", count); 989 990 return 0; 991 } 992 993 int wm_adsp2_event(struct snd_soc_dapm_widget *w, 994 struct snd_kcontrol *kcontrol, int event) 995 { 996 struct snd_soc_codec *codec = w->codec; 997 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 998 struct wm_adsp *dsp = &dsps[w->shift]; 999 struct wm_adsp_alg_region *alg_region; 1000 unsigned int val; 1001 int ret; 1002 1003 switch (event) { 1004 case SND_SOC_DAPM_POST_PMU: 1005 /* 1006 * For simplicity set the DSP clock rate to be the 1007 * SYSCLK rate rather than making it configurable. 1008 */ 1009 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); 1010 if (ret != 0) { 1011 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", 1012 ret); 1013 return ret; 1014 } 1015 val = (val & ARIZONA_SYSCLK_FREQ_MASK) 1016 >> ARIZONA_SYSCLK_FREQ_SHIFT; 1017 1018 ret = regmap_update_bits(dsp->regmap, 1019 dsp->base + ADSP2_CLOCKING, 1020 ADSP2_CLK_SEL_MASK, val); 1021 if (ret != 0) { 1022 adsp_err(dsp, "Failed to set clock rate: %d\n", 1023 ret); 1024 return ret; 1025 } 1026 1027 if (dsp->dvfs) { 1028 ret = regmap_read(dsp->regmap, 1029 dsp->base + ADSP2_CLOCKING, &val); 1030 if (ret != 0) { 1031 dev_err(dsp->dev, 1032 "Failed to read clocking: %d\n", ret); 1033 return ret; 1034 } 1035 1036 if ((val & ADSP2_CLK_SEL_MASK) >= 3) { 1037 ret = regulator_enable(dsp->dvfs); 1038 if (ret != 0) { 1039 dev_err(dsp->dev, 1040 "Failed to enable supply: %d\n", 1041 ret); 1042 return ret; 1043 } 1044 1045 ret = regulator_set_voltage(dsp->dvfs, 1046 1800000, 1047 1800000); 1048 if (ret != 0) { 1049 dev_err(dsp->dev, 1050 "Failed to raise supply: %d\n", 1051 ret); 1052 return ret; 1053 } 1054 } 1055 } 1056 1057 ret = wm_adsp2_ena(dsp); 1058 if (ret != 0) 1059 return ret; 1060 1061 ret = wm_adsp_load(dsp); 1062 if (ret != 0) 1063 goto err; 1064 1065 ret = wm_adsp_setup_algs(dsp); 1066 if (ret != 0) 1067 goto err; 1068 1069 ret = wm_adsp_load_coeff(dsp); 1070 if (ret != 0) 1071 goto err; 1072 1073 ret = regmap_update_bits(dsp->regmap, 1074 dsp->base + ADSP2_CONTROL, 1075 ADSP2_CORE_ENA | ADSP2_START, 1076 ADSP2_CORE_ENA | ADSP2_START); 1077 if (ret != 0) 1078 goto err; 1079 1080 dsp->running = true; 1081 break; 1082 1083 case SND_SOC_DAPM_PRE_PMD: 1084 dsp->running = false; 1085 1086 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 1087 ADSP2_SYS_ENA | ADSP2_CORE_ENA | 1088 ADSP2_START, 0); 1089 1090 /* Make sure DMAs are quiesced */ 1091 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); 1092 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); 1093 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); 1094 1095 if (dsp->dvfs) { 1096 ret = regulator_set_voltage(dsp->dvfs, 1200000, 1097 1800000); 1098 if (ret != 0) 1099 dev_warn(dsp->dev, 1100 "Failed to lower supply: %d\n", 1101 ret); 1102 1103 ret = regulator_disable(dsp->dvfs); 1104 if (ret != 0) 1105 dev_err(dsp->dev, 1106 "Failed to enable supply: %d\n", 1107 ret); 1108 } 1109 1110 while (!list_empty(&dsp->alg_regions)) { 1111 alg_region = list_first_entry(&dsp->alg_regions, 1112 struct wm_adsp_alg_region, 1113 list); 1114 list_del(&alg_region->list); 1115 kfree(alg_region); 1116 } 1117 break; 1118 1119 default: 1120 break; 1121 } 1122 1123 return 0; 1124 err: 1125 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 1126 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 1127 return ret; 1128 } 1129 EXPORT_SYMBOL_GPL(wm_adsp2_event); 1130 1131 int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) 1132 { 1133 int ret; 1134 1135 /* 1136 * Disable the DSP memory by default when in reset for a small 1137 * power saving. 1138 */ 1139 ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL, 1140 ADSP2_MEM_ENA, 0); 1141 if (ret != 0) { 1142 adsp_err(adsp, "Failed to clear memory retention: %d\n", ret); 1143 return ret; 1144 } 1145 1146 INIT_LIST_HEAD(&adsp->alg_regions); 1147 1148 if (dvfs) { 1149 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); 1150 if (IS_ERR(adsp->dvfs)) { 1151 ret = PTR_ERR(adsp->dvfs); 1152 dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); 1153 return ret; 1154 } 1155 1156 ret = regulator_enable(adsp->dvfs); 1157 if (ret != 0) { 1158 dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", 1159 ret); 1160 return ret; 1161 } 1162 1163 ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); 1164 if (ret != 0) { 1165 dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", 1166 ret); 1167 return ret; 1168 } 1169 1170 ret = regulator_disable(adsp->dvfs); 1171 if (ret != 0) { 1172 dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", 1173 ret); 1174 return ret; 1175 } 1176 } 1177 1178 return 0; 1179 } 1180 EXPORT_SYMBOL_GPL(wm_adsp2_init); 1181