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