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