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 <sound/core.h> 27 #include <sound/pcm.h> 28 #include <sound/pcm_params.h> 29 #include <sound/soc.h> 30 #include <sound/jack.h> 31 #include <sound/initval.h> 32 #include <sound/tlv.h> 33 34 #include <linux/mfd/arizona/registers.h> 35 36 #include "arizona.h" 37 #include "wm_adsp.h" 38 39 #define adsp_crit(_dsp, fmt, ...) \ 40 dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 41 #define adsp_err(_dsp, fmt, ...) \ 42 dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 43 #define adsp_warn(_dsp, fmt, ...) \ 44 dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 45 #define adsp_info(_dsp, fmt, ...) \ 46 dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 47 #define adsp_dbg(_dsp, fmt, ...) \ 48 dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) 49 50 #define ADSP1_CONTROL_1 0x00 51 #define ADSP1_CONTROL_2 0x02 52 #define ADSP1_CONTROL_3 0x03 53 #define ADSP1_CONTROL_4 0x04 54 #define ADSP1_CONTROL_5 0x06 55 #define ADSP1_CONTROL_6 0x07 56 #define ADSP1_CONTROL_7 0x08 57 #define ADSP1_CONTROL_8 0x09 58 #define ADSP1_CONTROL_9 0x0A 59 #define ADSP1_CONTROL_10 0x0B 60 #define ADSP1_CONTROL_11 0x0C 61 #define ADSP1_CONTROL_12 0x0D 62 #define ADSP1_CONTROL_13 0x0F 63 #define ADSP1_CONTROL_14 0x10 64 #define ADSP1_CONTROL_15 0x11 65 #define ADSP1_CONTROL_16 0x12 66 #define ADSP1_CONTROL_17 0x13 67 #define ADSP1_CONTROL_18 0x14 68 #define ADSP1_CONTROL_19 0x16 69 #define ADSP1_CONTROL_20 0x17 70 #define ADSP1_CONTROL_21 0x18 71 #define ADSP1_CONTROL_22 0x1A 72 #define ADSP1_CONTROL_23 0x1B 73 #define ADSP1_CONTROL_24 0x1C 74 #define ADSP1_CONTROL_25 0x1E 75 #define ADSP1_CONTROL_26 0x20 76 #define ADSP1_CONTROL_27 0x21 77 #define ADSP1_CONTROL_28 0x22 78 #define ADSP1_CONTROL_29 0x23 79 #define ADSP1_CONTROL_30 0x24 80 #define ADSP1_CONTROL_31 0x26 81 82 /* 83 * ADSP1 Control 19 84 */ 85 #define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 86 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 87 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ 88 89 90 /* 91 * ADSP1 Control 30 92 */ 93 #define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */ 94 #define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */ 95 #define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */ 96 #define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */ 97 #define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 98 #define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 99 #define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 100 #define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 101 #define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 102 #define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 103 #define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 104 #define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 105 #define ADSP1_START 0x0001 /* DSP1_START */ 106 #define ADSP1_START_MASK 0x0001 /* DSP1_START */ 107 #define ADSP1_START_SHIFT 0 /* DSP1_START */ 108 #define ADSP1_START_WIDTH 1 /* DSP1_START */ 109 110 /* 111 * ADSP1 Control 31 112 */ 113 #define ADSP1_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 114 #define ADSP1_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 115 #define ADSP1_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 116 117 #define ADSP2_CONTROL 0x0 118 #define ADSP2_CLOCKING 0x1 119 #define ADSP2_STATUS1 0x4 120 #define ADSP2_WDMA_CONFIG_1 0x30 121 #define ADSP2_WDMA_CONFIG_2 0x31 122 #define ADSP2_RDMA_CONFIG_1 0x34 123 124 /* 125 * ADSP2 Control 126 */ 127 128 #define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */ 129 #define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */ 130 #define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */ 131 #define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */ 132 #define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ 133 #define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ 134 #define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ 135 #define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ 136 #define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ 137 #define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ 138 #define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ 139 #define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ 140 #define ADSP2_START 0x0001 /* DSP1_START */ 141 #define ADSP2_START_MASK 0x0001 /* DSP1_START */ 142 #define ADSP2_START_SHIFT 0 /* DSP1_START */ 143 #define ADSP2_START_WIDTH 1 /* DSP1_START */ 144 145 /* 146 * ADSP2 clocking 147 */ 148 #define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ 149 #define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ 150 #define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ 151 152 /* 153 * ADSP2 Status 1 154 */ 155 #define ADSP2_RAM_RDY 0x0001 156 #define ADSP2_RAM_RDY_MASK 0x0001 157 #define ADSP2_RAM_RDY_SHIFT 0 158 #define ADSP2_RAM_RDY_WIDTH 1 159 160 struct wm_adsp_buf { 161 struct list_head list; 162 void *buf; 163 }; 164 165 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len, 166 struct list_head *list) 167 { 168 struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL); 169 170 if (buf == NULL) 171 return NULL; 172 173 buf->buf = vmalloc(len); 174 if (!buf->buf) { 175 vfree(buf); 176 return NULL; 177 } 178 memcpy(buf->buf, src, len); 179 180 if (list) 181 list_add_tail(&buf->list, list); 182 183 return buf; 184 } 185 186 static void wm_adsp_buf_free(struct list_head *list) 187 { 188 while (!list_empty(list)) { 189 struct wm_adsp_buf *buf = list_first_entry(list, 190 struct wm_adsp_buf, 191 list); 192 list_del(&buf->list); 193 vfree(buf->buf); 194 kfree(buf); 195 } 196 } 197 198 #define WM_ADSP_NUM_FW 4 199 200 #define WM_ADSP_FW_MBC_VSS 0 201 #define WM_ADSP_FW_TX 1 202 #define WM_ADSP_FW_TX_SPK 2 203 #define WM_ADSP_FW_RX_ANC 3 204 205 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { 206 [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", 207 [WM_ADSP_FW_TX] = "Tx", 208 [WM_ADSP_FW_TX_SPK] = "Tx Speaker", 209 [WM_ADSP_FW_RX_ANC] = "Rx ANC", 210 }; 211 212 static struct { 213 const char *file; 214 } wm_adsp_fw[WM_ADSP_NUM_FW] = { 215 [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" }, 216 [WM_ADSP_FW_TX] = { .file = "tx" }, 217 [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" }, 218 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, 219 }; 220 221 struct wm_coeff_ctl_ops { 222 int (*xget)(struct snd_kcontrol *kcontrol, 223 struct snd_ctl_elem_value *ucontrol); 224 int (*xput)(struct snd_kcontrol *kcontrol, 225 struct snd_ctl_elem_value *ucontrol); 226 int (*xinfo)(struct snd_kcontrol *kcontrol, 227 struct snd_ctl_elem_info *uinfo); 228 }; 229 230 struct wm_coeff_ctl { 231 const char *name; 232 struct wm_adsp_alg_region region; 233 struct wm_coeff_ctl_ops ops; 234 struct wm_adsp *adsp; 235 void *private; 236 unsigned int enabled:1; 237 struct list_head list; 238 void *cache; 239 size_t len; 240 unsigned int set:1; 241 struct snd_kcontrol *kcontrol; 242 }; 243 244 static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 245 struct snd_ctl_elem_value *ucontrol) 246 { 247 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 248 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 249 struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec); 250 251 ucontrol->value.integer.value[0] = adsp[e->shift_l].fw; 252 253 return 0; 254 } 255 256 static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, 257 struct snd_ctl_elem_value *ucontrol) 258 { 259 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 260 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 261 struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec); 262 263 if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw) 264 return 0; 265 266 if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW) 267 return -EINVAL; 268 269 if (adsp[e->shift_l].running) 270 return -EBUSY; 271 272 adsp[e->shift_l].fw = ucontrol->value.integer.value[0]; 273 274 return 0; 275 } 276 277 static const struct soc_enum wm_adsp_fw_enum[] = { 278 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 279 SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 280 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 281 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 282 }; 283 284 const struct snd_kcontrol_new wm_adsp1_fw_controls[] = { 285 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], 286 wm_adsp_fw_get, wm_adsp_fw_put), 287 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], 288 wm_adsp_fw_get, wm_adsp_fw_put), 289 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], 290 wm_adsp_fw_get, wm_adsp_fw_put), 291 }; 292 EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls); 293 294 #if IS_ENABLED(CONFIG_SND_SOC_ARIZONA) 295 static const struct soc_enum wm_adsp2_rate_enum[] = { 296 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1, 297 ARIZONA_DSP1_RATE_SHIFT, 0xf, 298 ARIZONA_RATE_ENUM_SIZE, 299 arizona_rate_text, arizona_rate_val), 300 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1, 301 ARIZONA_DSP1_RATE_SHIFT, 0xf, 302 ARIZONA_RATE_ENUM_SIZE, 303 arizona_rate_text, arizona_rate_val), 304 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1, 305 ARIZONA_DSP1_RATE_SHIFT, 0xf, 306 ARIZONA_RATE_ENUM_SIZE, 307 arizona_rate_text, arizona_rate_val), 308 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1, 309 ARIZONA_DSP1_RATE_SHIFT, 0xf, 310 ARIZONA_RATE_ENUM_SIZE, 311 arizona_rate_text, arizona_rate_val), 312 }; 313 314 const struct snd_kcontrol_new wm_adsp2_fw_controls[] = { 315 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], 316 wm_adsp_fw_get, wm_adsp_fw_put), 317 SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]), 318 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], 319 wm_adsp_fw_get, wm_adsp_fw_put), 320 SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]), 321 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], 322 wm_adsp_fw_get, wm_adsp_fw_put), 323 SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]), 324 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], 325 wm_adsp_fw_get, wm_adsp_fw_put), 326 SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]), 327 }; 328 EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls); 329 #endif 330 331 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, 332 int type) 333 { 334 int i; 335 336 for (i = 0; i < dsp->num_mems; i++) 337 if (dsp->mem[i].type == type) 338 return &dsp->mem[i]; 339 340 return NULL; 341 } 342 343 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region, 344 unsigned int offset) 345 { 346 if (WARN_ON(!region)) 347 return offset; 348 switch (region->type) { 349 case WMFW_ADSP1_PM: 350 return region->base + (offset * 3); 351 case WMFW_ADSP1_DM: 352 return region->base + (offset * 2); 353 case WMFW_ADSP2_XM: 354 return region->base + (offset * 2); 355 case WMFW_ADSP2_YM: 356 return region->base + (offset * 2); 357 case WMFW_ADSP1_ZM: 358 return region->base + (offset * 2); 359 default: 360 WARN(1, "Unknown memory region type"); 361 return offset; 362 } 363 } 364 365 static int wm_coeff_info(struct snd_kcontrol *kcontrol, 366 struct snd_ctl_elem_info *uinfo) 367 { 368 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 369 370 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 371 uinfo->count = ctl->len; 372 return 0; 373 } 374 375 static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, 376 const void *buf, size_t len) 377 { 378 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 379 struct wm_adsp_alg_region *region = &ctl->region; 380 const struct wm_adsp_region *mem; 381 struct wm_adsp *adsp = ctl->adsp; 382 void *scratch; 383 int ret; 384 unsigned int reg; 385 386 mem = wm_adsp_find_region(adsp, region->type); 387 if (!mem) { 388 adsp_err(adsp, "No base for region %x\n", 389 region->type); 390 return -EINVAL; 391 } 392 393 reg = ctl->region.base; 394 reg = wm_adsp_region_to_reg(mem, reg); 395 396 scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA); 397 if (!scratch) 398 return -ENOMEM; 399 400 ret = regmap_raw_write(adsp->regmap, reg, scratch, 401 ctl->len); 402 if (ret) { 403 adsp_err(adsp, "Failed to write %zu bytes to %x: %d\n", 404 ctl->len, reg, ret); 405 kfree(scratch); 406 return ret; 407 } 408 adsp_dbg(adsp, "Wrote %zu bytes to %x\n", ctl->len, reg); 409 410 kfree(scratch); 411 412 return 0; 413 } 414 415 static int wm_coeff_put(struct snd_kcontrol *kcontrol, 416 struct snd_ctl_elem_value *ucontrol) 417 { 418 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 419 char *p = ucontrol->value.bytes.data; 420 421 memcpy(ctl->cache, p, ctl->len); 422 423 if (!ctl->enabled) { 424 ctl->set = 1; 425 return 0; 426 } 427 428 return wm_coeff_write_control(kcontrol, p, ctl->len); 429 } 430 431 static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, 432 void *buf, size_t len) 433 { 434 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 435 struct wm_adsp_alg_region *region = &ctl->region; 436 const struct wm_adsp_region *mem; 437 struct wm_adsp *adsp = ctl->adsp; 438 void *scratch; 439 int ret; 440 unsigned int reg; 441 442 mem = wm_adsp_find_region(adsp, region->type); 443 if (!mem) { 444 adsp_err(adsp, "No base for region %x\n", 445 region->type); 446 return -EINVAL; 447 } 448 449 reg = ctl->region.base; 450 reg = wm_adsp_region_to_reg(mem, reg); 451 452 scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA); 453 if (!scratch) 454 return -ENOMEM; 455 456 ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len); 457 if (ret) { 458 adsp_err(adsp, "Failed to read %zu bytes from %x: %d\n", 459 ctl->len, reg, ret); 460 kfree(scratch); 461 return ret; 462 } 463 adsp_dbg(adsp, "Read %zu bytes from %x\n", ctl->len, reg); 464 465 memcpy(buf, scratch, ctl->len); 466 kfree(scratch); 467 468 return 0; 469 } 470 471 static int wm_coeff_get(struct snd_kcontrol *kcontrol, 472 struct snd_ctl_elem_value *ucontrol) 473 { 474 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 475 char *p = ucontrol->value.bytes.data; 476 477 memcpy(p, ctl->cache, ctl->len); 478 return 0; 479 } 480 481 struct wmfw_ctl_work { 482 struct wm_adsp *adsp; 483 struct wm_coeff_ctl *ctl; 484 struct work_struct work; 485 }; 486 487 static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl) 488 { 489 struct snd_kcontrol_new *kcontrol; 490 int ret; 491 492 if (!ctl || !ctl->name) 493 return -EINVAL; 494 495 kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); 496 if (!kcontrol) 497 return -ENOMEM; 498 kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 499 500 kcontrol->name = ctl->name; 501 kcontrol->info = wm_coeff_info; 502 kcontrol->get = wm_coeff_get; 503 kcontrol->put = wm_coeff_put; 504 kcontrol->private_value = (unsigned long)ctl; 505 506 ret = snd_soc_add_card_controls(adsp->card, 507 kcontrol, 1); 508 if (ret < 0) 509 goto err_kcontrol; 510 511 kfree(kcontrol); 512 513 ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card, 514 ctl->name); 515 516 list_add(&ctl->list, &adsp->ctl_list); 517 return 0; 518 519 err_kcontrol: 520 kfree(kcontrol); 521 return ret; 522 } 523 524 static int wm_adsp_load(struct wm_adsp *dsp) 525 { 526 LIST_HEAD(buf_list); 527 const struct firmware *firmware; 528 struct regmap *regmap = dsp->regmap; 529 unsigned int pos = 0; 530 const struct wmfw_header *header; 531 const struct wmfw_adsp1_sizes *adsp1_sizes; 532 const struct wmfw_adsp2_sizes *adsp2_sizes; 533 const struct wmfw_footer *footer; 534 const struct wmfw_region *region; 535 const struct wm_adsp_region *mem; 536 const char *region_name; 537 char *file, *text; 538 struct wm_adsp_buf *buf; 539 unsigned int reg; 540 int regions = 0; 541 int ret, offset, type, sizes; 542 543 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 544 if (file == NULL) 545 return -ENOMEM; 546 547 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num, 548 wm_adsp_fw[dsp->fw].file); 549 file[PAGE_SIZE - 1] = '\0'; 550 551 ret = request_firmware(&firmware, file, dsp->dev); 552 if (ret != 0) { 553 adsp_err(dsp, "Failed to request '%s'\n", file); 554 goto out; 555 } 556 ret = -EINVAL; 557 558 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 559 if (pos >= firmware->size) { 560 adsp_err(dsp, "%s: file too short, %zu bytes\n", 561 file, firmware->size); 562 goto out_fw; 563 } 564 565 header = (void*)&firmware->data[0]; 566 567 if (memcmp(&header->magic[0], "WMFW", 4) != 0) { 568 adsp_err(dsp, "%s: invalid magic\n", file); 569 goto out_fw; 570 } 571 572 if (header->ver != 0) { 573 adsp_err(dsp, "%s: unknown file format %d\n", 574 file, header->ver); 575 goto out_fw; 576 } 577 adsp_info(dsp, "Firmware version: %d\n", header->ver); 578 579 if (header->core != dsp->type) { 580 adsp_err(dsp, "%s: invalid core %d != %d\n", 581 file, header->core, dsp->type); 582 goto out_fw; 583 } 584 585 switch (dsp->type) { 586 case WMFW_ADSP1: 587 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 588 adsp1_sizes = (void *)&(header[1]); 589 footer = (void *)&(adsp1_sizes[1]); 590 sizes = sizeof(*adsp1_sizes); 591 592 adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", 593 file, le32_to_cpu(adsp1_sizes->dm), 594 le32_to_cpu(adsp1_sizes->pm), 595 le32_to_cpu(adsp1_sizes->zm)); 596 break; 597 598 case WMFW_ADSP2: 599 pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer); 600 adsp2_sizes = (void *)&(header[1]); 601 footer = (void *)&(adsp2_sizes[1]); 602 sizes = sizeof(*adsp2_sizes); 603 604 adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", 605 file, le32_to_cpu(adsp2_sizes->xm), 606 le32_to_cpu(adsp2_sizes->ym), 607 le32_to_cpu(adsp2_sizes->pm), 608 le32_to_cpu(adsp2_sizes->zm)); 609 break; 610 611 default: 612 WARN(1, "Unknown DSP type"); 613 goto out_fw; 614 } 615 616 if (le32_to_cpu(header->len) != sizeof(*header) + 617 sizes + sizeof(*footer)) { 618 adsp_err(dsp, "%s: unexpected header length %d\n", 619 file, le32_to_cpu(header->len)); 620 goto out_fw; 621 } 622 623 adsp_dbg(dsp, "%s: timestamp %llu\n", file, 624 le64_to_cpu(footer->timestamp)); 625 626 while (pos < firmware->size && 627 pos - firmware->size > sizeof(*region)) { 628 region = (void *)&(firmware->data[pos]); 629 region_name = "Unknown"; 630 reg = 0; 631 text = NULL; 632 offset = le32_to_cpu(region->offset) & 0xffffff; 633 type = be32_to_cpu(region->type) & 0xff; 634 mem = wm_adsp_find_region(dsp, type); 635 636 switch (type) { 637 case WMFW_NAME_TEXT: 638 region_name = "Firmware name"; 639 text = kzalloc(le32_to_cpu(region->len) + 1, 640 GFP_KERNEL); 641 break; 642 case WMFW_INFO_TEXT: 643 region_name = "Information"; 644 text = kzalloc(le32_to_cpu(region->len) + 1, 645 GFP_KERNEL); 646 break; 647 case WMFW_ABSOLUTE: 648 region_name = "Absolute"; 649 reg = offset; 650 break; 651 case WMFW_ADSP1_PM: 652 region_name = "PM"; 653 reg = wm_adsp_region_to_reg(mem, offset); 654 break; 655 case WMFW_ADSP1_DM: 656 region_name = "DM"; 657 reg = wm_adsp_region_to_reg(mem, offset); 658 break; 659 case WMFW_ADSP2_XM: 660 region_name = "XM"; 661 reg = wm_adsp_region_to_reg(mem, offset); 662 break; 663 case WMFW_ADSP2_YM: 664 region_name = "YM"; 665 reg = wm_adsp_region_to_reg(mem, offset); 666 break; 667 case WMFW_ADSP1_ZM: 668 region_name = "ZM"; 669 reg = wm_adsp_region_to_reg(mem, offset); 670 break; 671 default: 672 adsp_warn(dsp, 673 "%s.%d: Unknown region type %x at %d(%x)\n", 674 file, regions, type, pos, pos); 675 break; 676 } 677 678 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 679 regions, le32_to_cpu(region->len), offset, 680 region_name); 681 682 if (text) { 683 memcpy(text, region->data, le32_to_cpu(region->len)); 684 adsp_info(dsp, "%s: %s\n", file, text); 685 kfree(text); 686 } 687 688 if (reg) { 689 buf = wm_adsp_buf_alloc(region->data, 690 le32_to_cpu(region->len), 691 &buf_list); 692 if (!buf) { 693 adsp_err(dsp, "Out of memory\n"); 694 ret = -ENOMEM; 695 goto out_fw; 696 } 697 698 ret = regmap_raw_write_async(regmap, reg, buf->buf, 699 le32_to_cpu(region->len)); 700 if (ret != 0) { 701 adsp_err(dsp, 702 "%s.%d: Failed to write %d bytes at %d in %s: %d\n", 703 file, regions, 704 le32_to_cpu(region->len), offset, 705 region_name, ret); 706 goto out_fw; 707 } 708 } 709 710 pos += le32_to_cpu(region->len) + sizeof(*region); 711 regions++; 712 } 713 714 ret = regmap_async_complete(regmap); 715 if (ret != 0) { 716 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 717 goto out_fw; 718 } 719 720 if (pos > firmware->size) 721 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 722 file, regions, pos - firmware->size); 723 724 out_fw: 725 regmap_async_complete(regmap); 726 wm_adsp_buf_free(&buf_list); 727 release_firmware(firmware); 728 out: 729 kfree(file); 730 731 return ret; 732 } 733 734 static int wm_coeff_init_control_caches(struct wm_adsp *adsp) 735 { 736 struct wm_coeff_ctl *ctl; 737 int ret; 738 739 list_for_each_entry(ctl, &adsp->ctl_list, list) { 740 if (!ctl->enabled || ctl->set) 741 continue; 742 ret = wm_coeff_read_control(ctl->kcontrol, 743 ctl->cache, 744 ctl->len); 745 if (ret < 0) 746 return ret; 747 } 748 749 return 0; 750 } 751 752 static int wm_coeff_sync_controls(struct wm_adsp *adsp) 753 { 754 struct wm_coeff_ctl *ctl; 755 int ret; 756 757 list_for_each_entry(ctl, &adsp->ctl_list, list) { 758 if (!ctl->enabled) 759 continue; 760 if (ctl->set) { 761 ret = wm_coeff_write_control(ctl->kcontrol, 762 ctl->cache, 763 ctl->len); 764 if (ret < 0) 765 return ret; 766 } 767 } 768 769 return 0; 770 } 771 772 static void wm_adsp_ctl_work(struct work_struct *work) 773 { 774 struct wmfw_ctl_work *ctl_work = container_of(work, 775 struct wmfw_ctl_work, 776 work); 777 778 wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl); 779 kfree(ctl_work); 780 } 781 782 static int wm_adsp_create_control(struct wm_adsp *dsp, 783 const struct wm_adsp_alg_region *region) 784 785 { 786 struct wm_coeff_ctl *ctl; 787 struct wmfw_ctl_work *ctl_work; 788 char *name; 789 char *region_name; 790 int ret; 791 792 name = kmalloc(PAGE_SIZE, GFP_KERNEL); 793 if (!name) 794 return -ENOMEM; 795 796 switch (region->type) { 797 case WMFW_ADSP1_PM: 798 region_name = "PM"; 799 break; 800 case WMFW_ADSP1_DM: 801 region_name = "DM"; 802 break; 803 case WMFW_ADSP2_XM: 804 region_name = "XM"; 805 break; 806 case WMFW_ADSP2_YM: 807 region_name = "YM"; 808 break; 809 case WMFW_ADSP1_ZM: 810 region_name = "ZM"; 811 break; 812 default: 813 ret = -EINVAL; 814 goto err_name; 815 } 816 817 snprintf(name, PAGE_SIZE, "DSP%d %s %x", 818 dsp->num, region_name, region->alg); 819 820 list_for_each_entry(ctl, &dsp->ctl_list, 821 list) { 822 if (!strcmp(ctl->name, name)) { 823 if (!ctl->enabled) 824 ctl->enabled = 1; 825 goto found; 826 } 827 } 828 829 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); 830 if (!ctl) { 831 ret = -ENOMEM; 832 goto err_name; 833 } 834 ctl->region = *region; 835 ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); 836 if (!ctl->name) { 837 ret = -ENOMEM; 838 goto err_ctl; 839 } 840 ctl->enabled = 1; 841 ctl->set = 0; 842 ctl->ops.xget = wm_coeff_get; 843 ctl->ops.xput = wm_coeff_put; 844 ctl->adsp = dsp; 845 846 ctl->len = region->len; 847 ctl->cache = kzalloc(ctl->len, GFP_KERNEL); 848 if (!ctl->cache) { 849 ret = -ENOMEM; 850 goto err_ctl_name; 851 } 852 853 ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); 854 if (!ctl_work) { 855 ret = -ENOMEM; 856 goto err_ctl_cache; 857 } 858 859 ctl_work->adsp = dsp; 860 ctl_work->ctl = ctl; 861 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); 862 schedule_work(&ctl_work->work); 863 864 found: 865 kfree(name); 866 867 return 0; 868 869 err_ctl_cache: 870 kfree(ctl->cache); 871 err_ctl_name: 872 kfree(ctl->name); 873 err_ctl: 874 kfree(ctl); 875 err_name: 876 kfree(name); 877 return ret; 878 } 879 880 static int wm_adsp_setup_algs(struct wm_adsp *dsp) 881 { 882 struct regmap *regmap = dsp->regmap; 883 struct wmfw_adsp1_id_hdr adsp1_id; 884 struct wmfw_adsp2_id_hdr adsp2_id; 885 struct wmfw_adsp1_alg_hdr *adsp1_alg; 886 struct wmfw_adsp2_alg_hdr *adsp2_alg; 887 void *alg, *buf; 888 struct wm_adsp_alg_region *region; 889 const struct wm_adsp_region *mem; 890 unsigned int pos, term; 891 size_t algs, buf_size; 892 __be32 val; 893 int i, ret; 894 895 switch (dsp->type) { 896 case WMFW_ADSP1: 897 mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM); 898 break; 899 case WMFW_ADSP2: 900 mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM); 901 break; 902 default: 903 mem = NULL; 904 break; 905 } 906 907 if (WARN_ON(!mem)) 908 return -EINVAL; 909 910 switch (dsp->type) { 911 case WMFW_ADSP1: 912 ret = regmap_raw_read(regmap, mem->base, &adsp1_id, 913 sizeof(adsp1_id)); 914 if (ret != 0) { 915 adsp_err(dsp, "Failed to read algorithm info: %d\n", 916 ret); 917 return ret; 918 } 919 920 buf = &adsp1_id; 921 buf_size = sizeof(adsp1_id); 922 923 algs = be32_to_cpu(adsp1_id.algs); 924 dsp->fw_id = be32_to_cpu(adsp1_id.fw.id); 925 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 926 dsp->fw_id, 927 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, 928 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, 929 be32_to_cpu(adsp1_id.fw.ver) & 0xff, 930 algs); 931 932 region = kzalloc(sizeof(*region), GFP_KERNEL); 933 if (!region) 934 return -ENOMEM; 935 region->type = WMFW_ADSP1_ZM; 936 region->alg = be32_to_cpu(adsp1_id.fw.id); 937 region->base = be32_to_cpu(adsp1_id.zm); 938 list_add_tail(®ion->list, &dsp->alg_regions); 939 940 region = kzalloc(sizeof(*region), GFP_KERNEL); 941 if (!region) 942 return -ENOMEM; 943 region->type = WMFW_ADSP1_DM; 944 region->alg = be32_to_cpu(adsp1_id.fw.id); 945 region->base = be32_to_cpu(adsp1_id.dm); 946 list_add_tail(®ion->list, &dsp->alg_regions); 947 948 pos = sizeof(adsp1_id) / 2; 949 term = pos + ((sizeof(*adsp1_alg) * algs) / 2); 950 break; 951 952 case WMFW_ADSP2: 953 ret = regmap_raw_read(regmap, mem->base, &adsp2_id, 954 sizeof(adsp2_id)); 955 if (ret != 0) { 956 adsp_err(dsp, "Failed to read algorithm info: %d\n", 957 ret); 958 return ret; 959 } 960 961 buf = &adsp2_id; 962 buf_size = sizeof(adsp2_id); 963 964 algs = be32_to_cpu(adsp2_id.algs); 965 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); 966 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 967 dsp->fw_id, 968 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, 969 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, 970 be32_to_cpu(adsp2_id.fw.ver) & 0xff, 971 algs); 972 973 region = kzalloc(sizeof(*region), GFP_KERNEL); 974 if (!region) 975 return -ENOMEM; 976 region->type = WMFW_ADSP2_XM; 977 region->alg = be32_to_cpu(adsp2_id.fw.id); 978 region->base = be32_to_cpu(adsp2_id.xm); 979 list_add_tail(®ion->list, &dsp->alg_regions); 980 981 region = kzalloc(sizeof(*region), GFP_KERNEL); 982 if (!region) 983 return -ENOMEM; 984 region->type = WMFW_ADSP2_YM; 985 region->alg = be32_to_cpu(adsp2_id.fw.id); 986 region->base = be32_to_cpu(adsp2_id.ym); 987 list_add_tail(®ion->list, &dsp->alg_regions); 988 989 region = kzalloc(sizeof(*region), GFP_KERNEL); 990 if (!region) 991 return -ENOMEM; 992 region->type = WMFW_ADSP2_ZM; 993 region->alg = be32_to_cpu(adsp2_id.fw.id); 994 region->base = be32_to_cpu(adsp2_id.zm); 995 list_add_tail(®ion->list, &dsp->alg_regions); 996 997 pos = sizeof(adsp2_id) / 2; 998 term = pos + ((sizeof(*adsp2_alg) * algs) / 2); 999 break; 1000 1001 default: 1002 WARN(1, "Unknown DSP type"); 1003 return -EINVAL; 1004 } 1005 1006 if (algs == 0) { 1007 adsp_err(dsp, "No algorithms\n"); 1008 return -EINVAL; 1009 } 1010 1011 if (algs > 1024) { 1012 adsp_err(dsp, "Algorithm count %zx excessive\n", algs); 1013 print_hex_dump_bytes(dev_name(dsp->dev), DUMP_PREFIX_OFFSET, 1014 buf, buf_size); 1015 return -EINVAL; 1016 } 1017 1018 /* Read the terminator first to validate the length */ 1019 ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val)); 1020 if (ret != 0) { 1021 adsp_err(dsp, "Failed to read algorithm list end: %d\n", 1022 ret); 1023 return ret; 1024 } 1025 1026 if (be32_to_cpu(val) != 0xbedead) 1027 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n", 1028 term, be32_to_cpu(val)); 1029 1030 alg = kzalloc((term - pos) * 2, GFP_KERNEL | GFP_DMA); 1031 if (!alg) 1032 return -ENOMEM; 1033 1034 ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2); 1035 if (ret != 0) { 1036 adsp_err(dsp, "Failed to read algorithm list: %d\n", 1037 ret); 1038 goto out; 1039 } 1040 1041 adsp1_alg = alg; 1042 adsp2_alg = alg; 1043 1044 for (i = 0; i < algs; i++) { 1045 switch (dsp->type) { 1046 case WMFW_ADSP1: 1047 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", 1048 i, be32_to_cpu(adsp1_alg[i].alg.id), 1049 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, 1050 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, 1051 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, 1052 be32_to_cpu(adsp1_alg[i].dm), 1053 be32_to_cpu(adsp1_alg[i].zm)); 1054 1055 region = kzalloc(sizeof(*region), GFP_KERNEL); 1056 if (!region) { 1057 ret = -ENOMEM; 1058 goto out; 1059 } 1060 region->type = WMFW_ADSP1_DM; 1061 region->alg = be32_to_cpu(adsp1_alg[i].alg.id); 1062 region->base = be32_to_cpu(adsp1_alg[i].dm); 1063 region->len = 0; 1064 list_add_tail(®ion->list, &dsp->alg_regions); 1065 if (i + 1 < algs) { 1066 region->len = be32_to_cpu(adsp1_alg[i + 1].dm); 1067 region->len -= be32_to_cpu(adsp1_alg[i].dm); 1068 region->len *= 4; 1069 wm_adsp_create_control(dsp, region); 1070 } else { 1071 adsp_warn(dsp, "Missing length info for region DM with ID %x\n", 1072 be32_to_cpu(adsp1_alg[i].alg.id)); 1073 } 1074 1075 region = kzalloc(sizeof(*region), GFP_KERNEL); 1076 if (!region) { 1077 ret = -ENOMEM; 1078 goto out; 1079 } 1080 region->type = WMFW_ADSP1_ZM; 1081 region->alg = be32_to_cpu(adsp1_alg[i].alg.id); 1082 region->base = be32_to_cpu(adsp1_alg[i].zm); 1083 region->len = 0; 1084 list_add_tail(®ion->list, &dsp->alg_regions); 1085 if (i + 1 < algs) { 1086 region->len = be32_to_cpu(adsp1_alg[i + 1].zm); 1087 region->len -= be32_to_cpu(adsp1_alg[i].zm); 1088 region->len *= 4; 1089 wm_adsp_create_control(dsp, region); 1090 } else { 1091 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1092 be32_to_cpu(adsp1_alg[i].alg.id)); 1093 } 1094 break; 1095 1096 case WMFW_ADSP2: 1097 adsp_info(dsp, 1098 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", 1099 i, be32_to_cpu(adsp2_alg[i].alg.id), 1100 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, 1101 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, 1102 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, 1103 be32_to_cpu(adsp2_alg[i].xm), 1104 be32_to_cpu(adsp2_alg[i].ym), 1105 be32_to_cpu(adsp2_alg[i].zm)); 1106 1107 region = kzalloc(sizeof(*region), GFP_KERNEL); 1108 if (!region) { 1109 ret = -ENOMEM; 1110 goto out; 1111 } 1112 region->type = WMFW_ADSP2_XM; 1113 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 1114 region->base = be32_to_cpu(adsp2_alg[i].xm); 1115 region->len = 0; 1116 list_add_tail(®ion->list, &dsp->alg_regions); 1117 if (i + 1 < algs) { 1118 region->len = be32_to_cpu(adsp2_alg[i + 1].xm); 1119 region->len -= be32_to_cpu(adsp2_alg[i].xm); 1120 region->len *= 4; 1121 wm_adsp_create_control(dsp, region); 1122 } else { 1123 adsp_warn(dsp, "Missing length info for region XM with ID %x\n", 1124 be32_to_cpu(adsp2_alg[i].alg.id)); 1125 } 1126 1127 region = kzalloc(sizeof(*region), GFP_KERNEL); 1128 if (!region) { 1129 ret = -ENOMEM; 1130 goto out; 1131 } 1132 region->type = WMFW_ADSP2_YM; 1133 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 1134 region->base = be32_to_cpu(adsp2_alg[i].ym); 1135 region->len = 0; 1136 list_add_tail(®ion->list, &dsp->alg_regions); 1137 if (i + 1 < algs) { 1138 region->len = be32_to_cpu(adsp2_alg[i + 1].ym); 1139 region->len -= be32_to_cpu(adsp2_alg[i].ym); 1140 region->len *= 4; 1141 wm_adsp_create_control(dsp, region); 1142 } else { 1143 adsp_warn(dsp, "Missing length info for region YM with ID %x\n", 1144 be32_to_cpu(adsp2_alg[i].alg.id)); 1145 } 1146 1147 region = kzalloc(sizeof(*region), GFP_KERNEL); 1148 if (!region) { 1149 ret = -ENOMEM; 1150 goto out; 1151 } 1152 region->type = WMFW_ADSP2_ZM; 1153 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 1154 region->base = be32_to_cpu(adsp2_alg[i].zm); 1155 region->len = 0; 1156 list_add_tail(®ion->list, &dsp->alg_regions); 1157 if (i + 1 < algs) { 1158 region->len = be32_to_cpu(adsp2_alg[i + 1].zm); 1159 region->len -= be32_to_cpu(adsp2_alg[i].zm); 1160 region->len *= 4; 1161 wm_adsp_create_control(dsp, region); 1162 } else { 1163 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1164 be32_to_cpu(adsp2_alg[i].alg.id)); 1165 } 1166 break; 1167 } 1168 } 1169 1170 out: 1171 kfree(alg); 1172 return ret; 1173 } 1174 1175 static int wm_adsp_load_coeff(struct wm_adsp *dsp) 1176 { 1177 LIST_HEAD(buf_list); 1178 struct regmap *regmap = dsp->regmap; 1179 struct wmfw_coeff_hdr *hdr; 1180 struct wmfw_coeff_item *blk; 1181 const struct firmware *firmware; 1182 const struct wm_adsp_region *mem; 1183 struct wm_adsp_alg_region *alg_region; 1184 const char *region_name; 1185 int ret, pos, blocks, type, offset, reg; 1186 char *file; 1187 struct wm_adsp_buf *buf; 1188 int tmp; 1189 1190 file = kzalloc(PAGE_SIZE, GFP_KERNEL); 1191 if (file == NULL) 1192 return -ENOMEM; 1193 1194 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num, 1195 wm_adsp_fw[dsp->fw].file); 1196 file[PAGE_SIZE - 1] = '\0'; 1197 1198 ret = request_firmware(&firmware, file, dsp->dev); 1199 if (ret != 0) { 1200 adsp_warn(dsp, "Failed to request '%s'\n", file); 1201 ret = 0; 1202 goto out; 1203 } 1204 ret = -EINVAL; 1205 1206 if (sizeof(*hdr) >= firmware->size) { 1207 adsp_err(dsp, "%s: file too short, %zu bytes\n", 1208 file, firmware->size); 1209 goto out_fw; 1210 } 1211 1212 hdr = (void*)&firmware->data[0]; 1213 if (memcmp(hdr->magic, "WMDR", 4) != 0) { 1214 adsp_err(dsp, "%s: invalid magic\n", file); 1215 goto out_fw; 1216 } 1217 1218 switch (be32_to_cpu(hdr->rev) & 0xff) { 1219 case 1: 1220 break; 1221 default: 1222 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n", 1223 file, be32_to_cpu(hdr->rev) & 0xff); 1224 ret = -EINVAL; 1225 goto out_fw; 1226 } 1227 1228 adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, 1229 (le32_to_cpu(hdr->ver) >> 16) & 0xff, 1230 (le32_to_cpu(hdr->ver) >> 8) & 0xff, 1231 le32_to_cpu(hdr->ver) & 0xff); 1232 1233 pos = le32_to_cpu(hdr->len); 1234 1235 blocks = 0; 1236 while (pos < firmware->size && 1237 pos - firmware->size > sizeof(*blk)) { 1238 blk = (void*)(&firmware->data[pos]); 1239 1240 type = le16_to_cpu(blk->type); 1241 offset = le16_to_cpu(blk->offset); 1242 1243 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", 1244 file, blocks, le32_to_cpu(blk->id), 1245 (le32_to_cpu(blk->ver) >> 16) & 0xff, 1246 (le32_to_cpu(blk->ver) >> 8) & 0xff, 1247 le32_to_cpu(blk->ver) & 0xff); 1248 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", 1249 file, blocks, le32_to_cpu(blk->len), offset, type); 1250 1251 reg = 0; 1252 region_name = "Unknown"; 1253 switch (type) { 1254 case (WMFW_NAME_TEXT << 8): 1255 case (WMFW_INFO_TEXT << 8): 1256 break; 1257 case (WMFW_ABSOLUTE << 8): 1258 /* 1259 * Old files may use this for global 1260 * coefficients. 1261 */ 1262 if (le32_to_cpu(blk->id) == dsp->fw_id && 1263 offset == 0) { 1264 region_name = "global coefficients"; 1265 mem = wm_adsp_find_region(dsp, type); 1266 if (!mem) { 1267 adsp_err(dsp, "No ZM\n"); 1268 break; 1269 } 1270 reg = wm_adsp_region_to_reg(mem, 0); 1271 1272 } else { 1273 region_name = "register"; 1274 reg = offset; 1275 } 1276 break; 1277 1278 case WMFW_ADSP1_DM: 1279 case WMFW_ADSP1_ZM: 1280 case WMFW_ADSP2_XM: 1281 case WMFW_ADSP2_YM: 1282 adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", 1283 file, blocks, le32_to_cpu(blk->len), 1284 type, le32_to_cpu(blk->id)); 1285 1286 mem = wm_adsp_find_region(dsp, type); 1287 if (!mem) { 1288 adsp_err(dsp, "No base for region %x\n", type); 1289 break; 1290 } 1291 1292 reg = 0; 1293 list_for_each_entry(alg_region, 1294 &dsp->alg_regions, list) { 1295 if (le32_to_cpu(blk->id) == alg_region->alg && 1296 type == alg_region->type) { 1297 reg = alg_region->base; 1298 reg = wm_adsp_region_to_reg(mem, 1299 reg); 1300 reg += offset; 1301 break; 1302 } 1303 } 1304 1305 if (reg == 0) 1306 adsp_err(dsp, "No %x for algorithm %x\n", 1307 type, le32_to_cpu(blk->id)); 1308 break; 1309 1310 default: 1311 adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n", 1312 file, blocks, type, pos); 1313 break; 1314 } 1315 1316 if (reg) { 1317 buf = wm_adsp_buf_alloc(blk->data, 1318 le32_to_cpu(blk->len), 1319 &buf_list); 1320 if (!buf) { 1321 adsp_err(dsp, "Out of memory\n"); 1322 ret = -ENOMEM; 1323 goto out_fw; 1324 } 1325 1326 adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", 1327 file, blocks, le32_to_cpu(blk->len), 1328 reg); 1329 ret = regmap_raw_write_async(regmap, reg, buf->buf, 1330 le32_to_cpu(blk->len)); 1331 if (ret != 0) { 1332 adsp_err(dsp, 1333 "%s.%d: Failed to write to %x in %s: %d\n", 1334 file, blocks, reg, region_name, ret); 1335 } 1336 } 1337 1338 tmp = le32_to_cpu(blk->len) % 4; 1339 if (tmp) 1340 pos += le32_to_cpu(blk->len) + (4 - tmp) + sizeof(*blk); 1341 else 1342 pos += le32_to_cpu(blk->len) + sizeof(*blk); 1343 1344 blocks++; 1345 } 1346 1347 ret = regmap_async_complete(regmap); 1348 if (ret != 0) 1349 adsp_err(dsp, "Failed to complete async write: %d\n", ret); 1350 1351 if (pos > firmware->size) 1352 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 1353 file, blocks, pos - firmware->size); 1354 1355 out_fw: 1356 regmap_async_complete(regmap); 1357 release_firmware(firmware); 1358 wm_adsp_buf_free(&buf_list); 1359 out: 1360 kfree(file); 1361 return ret; 1362 } 1363 1364 int wm_adsp1_init(struct wm_adsp *adsp) 1365 { 1366 INIT_LIST_HEAD(&adsp->alg_regions); 1367 1368 return 0; 1369 } 1370 EXPORT_SYMBOL_GPL(wm_adsp1_init); 1371 1372 int wm_adsp1_event(struct snd_soc_dapm_widget *w, 1373 struct snd_kcontrol *kcontrol, 1374 int event) 1375 { 1376 struct snd_soc_codec *codec = w->codec; 1377 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1378 struct wm_adsp *dsp = &dsps[w->shift]; 1379 struct wm_adsp_alg_region *alg_region; 1380 struct wm_coeff_ctl *ctl; 1381 int ret; 1382 int val; 1383 1384 dsp->card = codec->component.card; 1385 1386 switch (event) { 1387 case SND_SOC_DAPM_POST_PMU: 1388 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1389 ADSP1_SYS_ENA, ADSP1_SYS_ENA); 1390 1391 /* 1392 * For simplicity set the DSP clock rate to be the 1393 * SYSCLK rate rather than making it configurable. 1394 */ 1395 if(dsp->sysclk_reg) { 1396 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); 1397 if (ret != 0) { 1398 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", 1399 ret); 1400 return ret; 1401 } 1402 1403 val = (val & dsp->sysclk_mask) 1404 >> dsp->sysclk_shift; 1405 1406 ret = regmap_update_bits(dsp->regmap, 1407 dsp->base + ADSP1_CONTROL_31, 1408 ADSP1_CLK_SEL_MASK, val); 1409 if (ret != 0) { 1410 adsp_err(dsp, "Failed to set clock rate: %d\n", 1411 ret); 1412 return ret; 1413 } 1414 } 1415 1416 ret = wm_adsp_load(dsp); 1417 if (ret != 0) 1418 goto err; 1419 1420 ret = wm_adsp_setup_algs(dsp); 1421 if (ret != 0) 1422 goto err; 1423 1424 ret = wm_adsp_load_coeff(dsp); 1425 if (ret != 0) 1426 goto err; 1427 1428 /* Initialize caches for enabled and unset controls */ 1429 ret = wm_coeff_init_control_caches(dsp); 1430 if (ret != 0) 1431 goto err; 1432 1433 /* Sync set controls */ 1434 ret = wm_coeff_sync_controls(dsp); 1435 if (ret != 0) 1436 goto err; 1437 1438 /* Start the core running */ 1439 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1440 ADSP1_CORE_ENA | ADSP1_START, 1441 ADSP1_CORE_ENA | ADSP1_START); 1442 break; 1443 1444 case SND_SOC_DAPM_PRE_PMD: 1445 /* Halt the core */ 1446 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1447 ADSP1_CORE_ENA | ADSP1_START, 0); 1448 1449 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, 1450 ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); 1451 1452 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1453 ADSP1_SYS_ENA, 0); 1454 1455 list_for_each_entry(ctl, &dsp->ctl_list, list) 1456 ctl->enabled = 0; 1457 1458 while (!list_empty(&dsp->alg_regions)) { 1459 alg_region = list_first_entry(&dsp->alg_regions, 1460 struct wm_adsp_alg_region, 1461 list); 1462 list_del(&alg_region->list); 1463 kfree(alg_region); 1464 } 1465 break; 1466 1467 default: 1468 break; 1469 } 1470 1471 return 0; 1472 1473 err: 1474 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1475 ADSP1_SYS_ENA, 0); 1476 return ret; 1477 } 1478 EXPORT_SYMBOL_GPL(wm_adsp1_event); 1479 1480 static int wm_adsp2_ena(struct wm_adsp *dsp) 1481 { 1482 unsigned int val; 1483 int ret, count; 1484 1485 ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL, 1486 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 1487 if (ret != 0) 1488 return ret; 1489 1490 /* Wait for the RAM to start, should be near instantaneous */ 1491 for (count = 0; count < 10; ++count) { 1492 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, 1493 &val); 1494 if (ret != 0) 1495 return ret; 1496 1497 if (val & ADSP2_RAM_RDY) 1498 break; 1499 1500 msleep(1); 1501 } 1502 1503 if (!(val & ADSP2_RAM_RDY)) { 1504 adsp_err(dsp, "Failed to start DSP RAM\n"); 1505 return -EBUSY; 1506 } 1507 1508 adsp_dbg(dsp, "RAM ready after %d polls\n", count); 1509 1510 return 0; 1511 } 1512 1513 static void wm_adsp2_boot_work(struct work_struct *work) 1514 { 1515 struct wm_adsp *dsp = container_of(work, 1516 struct wm_adsp, 1517 boot_work); 1518 int ret; 1519 unsigned int val; 1520 1521 /* 1522 * For simplicity set the DSP clock rate to be the 1523 * SYSCLK rate rather than making it configurable. 1524 */ 1525 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); 1526 if (ret != 0) { 1527 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); 1528 return; 1529 } 1530 val = (val & ARIZONA_SYSCLK_FREQ_MASK) 1531 >> ARIZONA_SYSCLK_FREQ_SHIFT; 1532 1533 ret = regmap_update_bits_async(dsp->regmap, 1534 dsp->base + ADSP2_CLOCKING, 1535 ADSP2_CLK_SEL_MASK, val); 1536 if (ret != 0) { 1537 adsp_err(dsp, "Failed to set clock rate: %d\n", ret); 1538 return; 1539 } 1540 1541 if (dsp->dvfs) { 1542 ret = regmap_read(dsp->regmap, 1543 dsp->base + ADSP2_CLOCKING, &val); 1544 if (ret != 0) { 1545 adsp_err(dsp, "Failed to read clocking: %d\n", ret); 1546 return; 1547 } 1548 1549 if ((val & ADSP2_CLK_SEL_MASK) >= 3) { 1550 ret = regulator_enable(dsp->dvfs); 1551 if (ret != 0) { 1552 adsp_err(dsp, 1553 "Failed to enable supply: %d\n", 1554 ret); 1555 return; 1556 } 1557 1558 ret = regulator_set_voltage(dsp->dvfs, 1559 1800000, 1560 1800000); 1561 if (ret != 0) { 1562 adsp_err(dsp, 1563 "Failed to raise supply: %d\n", 1564 ret); 1565 return; 1566 } 1567 } 1568 } 1569 1570 ret = wm_adsp2_ena(dsp); 1571 if (ret != 0) 1572 return; 1573 1574 ret = wm_adsp_load(dsp); 1575 if (ret != 0) 1576 goto err; 1577 1578 ret = wm_adsp_setup_algs(dsp); 1579 if (ret != 0) 1580 goto err; 1581 1582 ret = wm_adsp_load_coeff(dsp); 1583 if (ret != 0) 1584 goto err; 1585 1586 /* Initialize caches for enabled and unset controls */ 1587 ret = wm_coeff_init_control_caches(dsp); 1588 if (ret != 0) 1589 goto err; 1590 1591 /* Sync set controls */ 1592 ret = wm_coeff_sync_controls(dsp); 1593 if (ret != 0) 1594 goto err; 1595 1596 dsp->running = true; 1597 1598 return; 1599 1600 err: 1601 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 1602 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 1603 } 1604 1605 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 1606 struct snd_kcontrol *kcontrol, int event) 1607 { 1608 struct snd_soc_codec *codec = w->codec; 1609 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1610 struct wm_adsp *dsp = &dsps[w->shift]; 1611 1612 dsp->card = codec->component.card; 1613 1614 switch (event) { 1615 case SND_SOC_DAPM_PRE_PMU: 1616 queue_work(system_unbound_wq, &dsp->boot_work); 1617 break; 1618 default: 1619 break; 1620 } 1621 1622 return 0; 1623 } 1624 EXPORT_SYMBOL_GPL(wm_adsp2_early_event); 1625 1626 int wm_adsp2_event(struct snd_soc_dapm_widget *w, 1627 struct snd_kcontrol *kcontrol, int event) 1628 { 1629 struct snd_soc_codec *codec = w->codec; 1630 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1631 struct wm_adsp *dsp = &dsps[w->shift]; 1632 struct wm_adsp_alg_region *alg_region; 1633 struct wm_coeff_ctl *ctl; 1634 int ret; 1635 1636 switch (event) { 1637 case SND_SOC_DAPM_POST_PMU: 1638 flush_work(&dsp->boot_work); 1639 1640 if (!dsp->running) 1641 return -EIO; 1642 1643 ret = regmap_update_bits(dsp->regmap, 1644 dsp->base + ADSP2_CONTROL, 1645 ADSP2_CORE_ENA | ADSP2_START, 1646 ADSP2_CORE_ENA | ADSP2_START); 1647 if (ret != 0) 1648 goto err; 1649 break; 1650 1651 case SND_SOC_DAPM_PRE_PMD: 1652 dsp->running = false; 1653 1654 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 1655 ADSP2_SYS_ENA | ADSP2_CORE_ENA | 1656 ADSP2_START, 0); 1657 1658 /* Make sure DMAs are quiesced */ 1659 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); 1660 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); 1661 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); 1662 1663 if (dsp->dvfs) { 1664 ret = regulator_set_voltage(dsp->dvfs, 1200000, 1665 1800000); 1666 if (ret != 0) 1667 adsp_warn(dsp, 1668 "Failed to lower supply: %d\n", 1669 ret); 1670 1671 ret = regulator_disable(dsp->dvfs); 1672 if (ret != 0) 1673 adsp_err(dsp, 1674 "Failed to enable supply: %d\n", 1675 ret); 1676 } 1677 1678 list_for_each_entry(ctl, &dsp->ctl_list, list) 1679 ctl->enabled = 0; 1680 1681 while (!list_empty(&dsp->alg_regions)) { 1682 alg_region = list_first_entry(&dsp->alg_regions, 1683 struct wm_adsp_alg_region, 1684 list); 1685 list_del(&alg_region->list); 1686 kfree(alg_region); 1687 } 1688 1689 adsp_dbg(dsp, "Shutdown complete\n"); 1690 break; 1691 1692 default: 1693 break; 1694 } 1695 1696 return 0; 1697 err: 1698 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 1699 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); 1700 return ret; 1701 } 1702 EXPORT_SYMBOL_GPL(wm_adsp2_event); 1703 1704 int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) 1705 { 1706 int ret; 1707 1708 /* 1709 * Disable the DSP memory by default when in reset for a small 1710 * power saving. 1711 */ 1712 ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL, 1713 ADSP2_MEM_ENA, 0); 1714 if (ret != 0) { 1715 adsp_err(adsp, "Failed to clear memory retention: %d\n", ret); 1716 return ret; 1717 } 1718 1719 INIT_LIST_HEAD(&adsp->alg_regions); 1720 INIT_LIST_HEAD(&adsp->ctl_list); 1721 INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work); 1722 1723 if (dvfs) { 1724 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); 1725 if (IS_ERR(adsp->dvfs)) { 1726 ret = PTR_ERR(adsp->dvfs); 1727 adsp_err(adsp, "Failed to get DCVDD: %d\n", ret); 1728 return ret; 1729 } 1730 1731 ret = regulator_enable(adsp->dvfs); 1732 if (ret != 0) { 1733 adsp_err(adsp, "Failed to enable DCVDD: %d\n", ret); 1734 return ret; 1735 } 1736 1737 ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); 1738 if (ret != 0) { 1739 adsp_err(adsp, "Failed to initialise DVFS: %d\n", ret); 1740 return ret; 1741 } 1742 1743 ret = regulator_disable(adsp->dvfs); 1744 if (ret != 0) { 1745 adsp_err(adsp, "Failed to disable DCVDD: %d\n", ret); 1746 return ret; 1747 } 1748 } 1749 1750 return 0; 1751 } 1752 EXPORT_SYMBOL_GPL(wm_adsp2_init); 1753 1754 MODULE_LICENSE("GPL v2"); 1755