wm_adsp.c 29 KB

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