wm_adsp.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * wm_adsp.c -- Wolfson ADSP support
  4. *
  5. * Copyright 2012 Wolfson Microelectronics plc
  6. *
  7. * Author: Mark Brown <[email protected]>
  8. */
  9. #include <linux/ctype.h>
  10. #include <linux/module.h>
  11. #include <linux/moduleparam.h>
  12. #include <linux/init.h>
  13. #include <linux/delay.h>
  14. #include <linux/firmware.h>
  15. #include <linux/list.h>
  16. #include <linux/pm.h>
  17. #include <linux/pm_runtime.h>
  18. #include <linux/regmap.h>
  19. #include <linux/regulator/consumer.h>
  20. #include <linux/slab.h>
  21. #include <linux/workqueue.h>
  22. #include <linux/debugfs.h>
  23. #include <sound/core.h>
  24. #include <sound/pcm.h>
  25. #include <sound/pcm_params.h>
  26. #include <sound/soc.h>
  27. #include <sound/jack.h>
  28. #include <sound/initval.h>
  29. #include <sound/tlv.h>
  30. #include "wm_adsp.h"
  31. #define adsp_crit(_dsp, fmt, ...) \
  32. dev_crit(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
  33. #define adsp_err(_dsp, fmt, ...) \
  34. dev_err(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
  35. #define adsp_warn(_dsp, fmt, ...) \
  36. dev_warn(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
  37. #define adsp_info(_dsp, fmt, ...) \
  38. dev_info(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
  39. #define adsp_dbg(_dsp, fmt, ...) \
  40. dev_dbg(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
  41. #define compr_err(_obj, fmt, ...) \
  42. adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
  43. ##__VA_ARGS__)
  44. #define compr_dbg(_obj, fmt, ...) \
  45. adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
  46. ##__VA_ARGS__)
  47. #define ADSP_MAX_STD_CTRL_SIZE 512
  48. static const struct cs_dsp_client_ops wm_adsp1_client_ops;
  49. static const struct cs_dsp_client_ops wm_adsp2_client_ops;
  50. #define WM_ADSP_FW_MBC_VSS 0
  51. #define WM_ADSP_FW_HIFI 1
  52. #define WM_ADSP_FW_TX 2
  53. #define WM_ADSP_FW_TX_SPK 3
  54. #define WM_ADSP_FW_RX 4
  55. #define WM_ADSP_FW_RX_ANC 5
  56. #define WM_ADSP_FW_CTRL 6
  57. #define WM_ADSP_FW_ASR 7
  58. #define WM_ADSP_FW_TRACE 8
  59. #define WM_ADSP_FW_SPK_PROT 9
  60. #define WM_ADSP_FW_SPK_CALI 10
  61. #define WM_ADSP_FW_SPK_DIAG 11
  62. #define WM_ADSP_FW_MISC 12
  63. #define WM_ADSP_NUM_FW 13
  64. static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
  65. [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
  66. [WM_ADSP_FW_HIFI] = "MasterHiFi",
  67. [WM_ADSP_FW_TX] = "Tx",
  68. [WM_ADSP_FW_TX_SPK] = "Tx Speaker",
  69. [WM_ADSP_FW_RX] = "Rx",
  70. [WM_ADSP_FW_RX_ANC] = "Rx ANC",
  71. [WM_ADSP_FW_CTRL] = "Voice Ctrl",
  72. [WM_ADSP_FW_ASR] = "ASR Assist",
  73. [WM_ADSP_FW_TRACE] = "Dbg Trace",
  74. [WM_ADSP_FW_SPK_PROT] = "Protection",
  75. [WM_ADSP_FW_SPK_CALI] = "Calibration",
  76. [WM_ADSP_FW_SPK_DIAG] = "Diagnostic",
  77. [WM_ADSP_FW_MISC] = "Misc",
  78. };
  79. struct wm_adsp_system_config_xm_hdr {
  80. __be32 sys_enable;
  81. __be32 fw_id;
  82. __be32 fw_rev;
  83. __be32 boot_status;
  84. __be32 watchdog;
  85. __be32 dma_buffer_size;
  86. __be32 rdma[6];
  87. __be32 wdma[8];
  88. __be32 build_job_name[3];
  89. __be32 build_job_number;
  90. } __packed;
  91. struct wm_halo_system_config_xm_hdr {
  92. __be32 halo_heartbeat;
  93. __be32 build_job_name[3];
  94. __be32 build_job_number;
  95. } __packed;
  96. struct wm_adsp_alg_xm_struct {
  97. __be32 magic;
  98. __be32 smoothing;
  99. __be32 threshold;
  100. __be32 host_buf_ptr;
  101. __be32 start_seq;
  102. __be32 high_water_mark;
  103. __be32 low_water_mark;
  104. __be64 smoothed_power;
  105. } __packed;
  106. struct wm_adsp_host_buf_coeff_v1 {
  107. __be32 host_buf_ptr; /* Host buffer pointer */
  108. __be32 versions; /* Version numbers */
  109. __be32 name[4]; /* The buffer name */
  110. } __packed;
  111. struct wm_adsp_buffer {
  112. __be32 buf1_base; /* Base addr of first buffer area */
  113. __be32 buf1_size; /* Size of buf1 area in DSP words */
  114. __be32 buf2_base; /* Base addr of 2nd buffer area */
  115. __be32 buf1_buf2_size; /* Size of buf1+buf2 in DSP words */
  116. __be32 buf3_base; /* Base addr of buf3 area */
  117. __be32 buf_total_size; /* Size of buf1+buf2+buf3 in DSP words */
  118. __be32 high_water_mark; /* Point at which IRQ is asserted */
  119. __be32 irq_count; /* bits 1-31 count IRQ assertions */
  120. __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */
  121. __be32 next_write_index; /* word index of next write */
  122. __be32 next_read_index; /* word index of next read */
  123. __be32 error; /* error if any */
  124. __be32 oldest_block_index; /* word index of oldest surviving */
  125. __be32 requested_rewind; /* how many blocks rewind was done */
  126. __be32 reserved_space; /* internal */
  127. __be32 min_free; /* min free space since stream start */
  128. __be32 blocks_written[2]; /* total blocks written (64 bit) */
  129. __be32 words_written[2]; /* total words written (64 bit) */
  130. } __packed;
  131. struct wm_adsp_compr;
  132. struct wm_adsp_compr_buf {
  133. struct list_head list;
  134. struct wm_adsp *dsp;
  135. struct wm_adsp_compr *compr;
  136. struct wm_adsp_buffer_region *regions;
  137. u32 host_buf_ptr;
  138. u32 error;
  139. u32 irq_count;
  140. int read_index;
  141. int avail;
  142. int host_buf_mem_type;
  143. char *name;
  144. };
  145. struct wm_adsp_compr {
  146. struct list_head list;
  147. struct wm_adsp *dsp;
  148. struct wm_adsp_compr_buf *buf;
  149. struct snd_compr_stream *stream;
  150. struct snd_compressed_buffer size;
  151. u32 *raw_buf;
  152. unsigned int copied_total;
  153. unsigned int sample_rate;
  154. const char *name;
  155. };
  156. #define WM_ADSP_MIN_FRAGMENTS 1
  157. #define WM_ADSP_MAX_FRAGMENTS 256
  158. #define WM_ADSP_MIN_FRAGMENT_SIZE (16 * CS_DSP_DATA_WORD_SIZE)
  159. #define WM_ADSP_MAX_FRAGMENT_SIZE (4096 * CS_DSP_DATA_WORD_SIZE)
  160. #define WM_ADSP_ALG_XM_STRUCT_MAGIC 0x49aec7
  161. #define HOST_BUFFER_FIELD(field) \
  162. (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
  163. #define ALG_XM_FIELD(field) \
  164. (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
  165. #define HOST_BUF_COEFF_SUPPORTED_COMPAT_VER 1
  166. #define HOST_BUF_COEFF_COMPAT_VER_MASK 0xFF00
  167. #define HOST_BUF_COEFF_COMPAT_VER_SHIFT 8
  168. static int wm_adsp_buffer_init(struct wm_adsp *dsp);
  169. static int wm_adsp_buffer_free(struct wm_adsp *dsp);
  170. struct wm_adsp_buffer_region {
  171. unsigned int offset;
  172. unsigned int cumulative_size;
  173. unsigned int mem_type;
  174. unsigned int base_addr;
  175. };
  176. struct wm_adsp_buffer_region_def {
  177. unsigned int mem_type;
  178. unsigned int base_offset;
  179. unsigned int size_offset;
  180. };
  181. static const struct wm_adsp_buffer_region_def default_regions[] = {
  182. {
  183. .mem_type = WMFW_ADSP2_XM,
  184. .base_offset = HOST_BUFFER_FIELD(buf1_base),
  185. .size_offset = HOST_BUFFER_FIELD(buf1_size),
  186. },
  187. {
  188. .mem_type = WMFW_ADSP2_XM,
  189. .base_offset = HOST_BUFFER_FIELD(buf2_base),
  190. .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size),
  191. },
  192. {
  193. .mem_type = WMFW_ADSP2_YM,
  194. .base_offset = HOST_BUFFER_FIELD(buf3_base),
  195. .size_offset = HOST_BUFFER_FIELD(buf_total_size),
  196. },
  197. };
  198. struct wm_adsp_fw_caps {
  199. u32 id;
  200. struct snd_codec_desc desc;
  201. int num_regions;
  202. const struct wm_adsp_buffer_region_def *region_defs;
  203. };
  204. static const struct wm_adsp_fw_caps ctrl_caps[] = {
  205. {
  206. .id = SND_AUDIOCODEC_BESPOKE,
  207. .desc = {
  208. .max_ch = 8,
  209. .sample_rates = { 16000 },
  210. .num_sample_rates = 1,
  211. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  212. },
  213. .num_regions = ARRAY_SIZE(default_regions),
  214. .region_defs = default_regions,
  215. },
  216. };
  217. static const struct wm_adsp_fw_caps trace_caps[] = {
  218. {
  219. .id = SND_AUDIOCODEC_BESPOKE,
  220. .desc = {
  221. .max_ch = 8,
  222. .sample_rates = {
  223. 4000, 8000, 11025, 12000, 16000, 22050,
  224. 24000, 32000, 44100, 48000, 64000, 88200,
  225. 96000, 176400, 192000
  226. },
  227. .num_sample_rates = 15,
  228. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  229. },
  230. .num_regions = ARRAY_SIZE(default_regions),
  231. .region_defs = default_regions,
  232. },
  233. };
  234. static const struct {
  235. const char *file;
  236. int compr_direction;
  237. int num_caps;
  238. const struct wm_adsp_fw_caps *caps;
  239. bool voice_trigger;
  240. } wm_adsp_fw[WM_ADSP_NUM_FW] = {
  241. [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
  242. [WM_ADSP_FW_HIFI] = { .file = "hifi" },
  243. [WM_ADSP_FW_TX] = { .file = "tx" },
  244. [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" },
  245. [WM_ADSP_FW_RX] = { .file = "rx" },
  246. [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" },
  247. [WM_ADSP_FW_CTRL] = {
  248. .file = "ctrl",
  249. .compr_direction = SND_COMPRESS_CAPTURE,
  250. .num_caps = ARRAY_SIZE(ctrl_caps),
  251. .caps = ctrl_caps,
  252. .voice_trigger = true,
  253. },
  254. [WM_ADSP_FW_ASR] = { .file = "asr" },
  255. [WM_ADSP_FW_TRACE] = {
  256. .file = "trace",
  257. .compr_direction = SND_COMPRESS_CAPTURE,
  258. .num_caps = ARRAY_SIZE(trace_caps),
  259. .caps = trace_caps,
  260. },
  261. [WM_ADSP_FW_SPK_PROT] = {
  262. .file = "spk-prot",
  263. .compr_direction = SND_COMPRESS_CAPTURE,
  264. .num_caps = ARRAY_SIZE(trace_caps),
  265. .caps = trace_caps,
  266. },
  267. [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" },
  268. [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" },
  269. [WM_ADSP_FW_MISC] = { .file = "misc" },
  270. };
  271. struct wm_coeff_ctl {
  272. const char *name;
  273. struct cs_dsp_coeff_ctl *cs_ctl;
  274. struct soc_bytes_ext bytes_ext;
  275. struct work_struct work;
  276. };
  277. int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
  278. struct snd_ctl_elem_value *ucontrol)
  279. {
  280. struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
  281. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  282. struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
  283. ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
  284. return 0;
  285. }
  286. EXPORT_SYMBOL_GPL(wm_adsp_fw_get);
  287. int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
  288. struct snd_ctl_elem_value *ucontrol)
  289. {
  290. struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
  291. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  292. struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
  293. int ret = 1;
  294. if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
  295. return 0;
  296. if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
  297. return -EINVAL;
  298. mutex_lock(&dsp[e->shift_l].cs_dsp.pwr_lock);
  299. if (dsp[e->shift_l].cs_dsp.booted || !list_empty(&dsp[e->shift_l].compr_list))
  300. ret = -EBUSY;
  301. else
  302. dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
  303. mutex_unlock(&dsp[e->shift_l].cs_dsp.pwr_lock);
  304. return ret;
  305. }
  306. EXPORT_SYMBOL_GPL(wm_adsp_fw_put);
  307. const struct soc_enum wm_adsp_fw_enum[] = {
  308. SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
  309. SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
  310. SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
  311. SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
  312. SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
  313. SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
  314. SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
  315. };
  316. EXPORT_SYMBOL_GPL(wm_adsp_fw_enum);
  317. static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
  318. {
  319. return container_of(ext, struct wm_coeff_ctl, bytes_ext);
  320. }
  321. static int wm_coeff_info(struct snd_kcontrol *kctl,
  322. struct snd_ctl_elem_info *uinfo)
  323. {
  324. struct soc_bytes_ext *bytes_ext =
  325. (struct soc_bytes_ext *)kctl->private_value;
  326. struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
  327. struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
  328. switch (cs_ctl->type) {
  329. case WMFW_CTL_TYPE_ACKED:
  330. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  331. uinfo->value.integer.min = CS_DSP_ACKED_CTL_MIN_VALUE;
  332. uinfo->value.integer.max = CS_DSP_ACKED_CTL_MAX_VALUE;
  333. uinfo->value.integer.step = 1;
  334. uinfo->count = 1;
  335. break;
  336. default:
  337. uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
  338. uinfo->count = cs_ctl->len;
  339. break;
  340. }
  341. return 0;
  342. }
  343. static int wm_coeff_put(struct snd_kcontrol *kctl,
  344. struct snd_ctl_elem_value *ucontrol)
  345. {
  346. struct snd_soc_component *component = snd_soc_kcontrol_component(kctl);
  347. struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
  348. struct soc_bytes_ext *bytes_ext =
  349. (struct soc_bytes_ext *)kctl->private_value;
  350. struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
  351. struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
  352. char *p = ucontrol->value.bytes.data;
  353. int ret = 0;
  354. if (!dsp->hibernate) {
  355. mutex_lock(&cs_ctl->dsp->pwr_lock);
  356. ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, p, cs_ctl->len);
  357. mutex_unlock(&cs_ctl->dsp->pwr_lock);
  358. }
  359. return ret;
  360. }
  361. static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
  362. const unsigned int __user *bytes, unsigned int size)
  363. {
  364. struct snd_soc_component *component = snd_soc_kcontrol_component(kctl);
  365. struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
  366. struct soc_bytes_ext *bytes_ext =
  367. (struct soc_bytes_ext *)kctl->private_value;
  368. struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
  369. struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
  370. int ret = 0;
  371. if (!dsp->hibernate) {
  372. mutex_lock(&cs_ctl->dsp->pwr_lock);
  373. if (copy_from_user(cs_ctl->cache, bytes, size))
  374. ret = -EFAULT;
  375. else
  376. ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, cs_ctl->cache, size);
  377. mutex_unlock(&cs_ctl->dsp->pwr_lock);
  378. }
  379. return ret;
  380. }
  381. static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
  382. struct snd_ctl_elem_value *ucontrol)
  383. {
  384. struct snd_soc_component *component = snd_soc_kcontrol_component(kctl);
  385. struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
  386. struct soc_bytes_ext *bytes_ext =
  387. (struct soc_bytes_ext *)kctl->private_value;
  388. struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
  389. struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
  390. unsigned int val = ucontrol->value.integer.value[0];
  391. int ret;
  392. if (val == 0 || dsp->hibernate)
  393. return 0; /* 0 means no event */
  394. mutex_lock(&cs_ctl->dsp->pwr_lock);
  395. if (cs_ctl->enabled)
  396. ret = cs_dsp_coeff_write_acked_control(cs_ctl, val);
  397. else
  398. ret = -EPERM;
  399. mutex_unlock(&cs_ctl->dsp->pwr_lock);
  400. return ret;
  401. }
  402. static int wm_coeff_get(struct snd_kcontrol *kctl,
  403. struct snd_ctl_elem_value *ucontrol)
  404. {
  405. struct snd_soc_component *component = snd_soc_kcontrol_component(kctl);
  406. struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
  407. struct soc_bytes_ext *bytes_ext =
  408. (struct soc_bytes_ext *)kctl->private_value;
  409. struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
  410. struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
  411. char *p = ucontrol->value.bytes.data;
  412. int ret = 0;
  413. if (!dsp->hibernate) {
  414. mutex_lock(&cs_ctl->dsp->pwr_lock);
  415. ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, p, cs_ctl->len);
  416. mutex_unlock(&cs_ctl->dsp->pwr_lock);
  417. }
  418. return ret;
  419. }
  420. static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
  421. unsigned int __user *bytes, unsigned int size)
  422. {
  423. struct snd_soc_component *component = snd_soc_kcontrol_component(kctl);
  424. struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
  425. struct soc_bytes_ext *bytes_ext =
  426. (struct soc_bytes_ext *)kctl->private_value;
  427. struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
  428. struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
  429. int ret = 0;
  430. if (!dsp->hibernate) {
  431. mutex_lock(&cs_ctl->dsp->pwr_lock);
  432. ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, cs_ctl->cache, size);
  433. if (!ret && copy_to_user(bytes, cs_ctl->cache, size))
  434. ret = -EFAULT;
  435. mutex_unlock(&cs_ctl->dsp->pwr_lock);
  436. }
  437. return ret;
  438. }
  439. static int wm_coeff_get_acked(struct snd_kcontrol *kcontrol,
  440. struct snd_ctl_elem_value *ucontrol)
  441. {
  442. /*
  443. * Although it's not useful to read an acked control, we must satisfy
  444. * user-side assumptions that all controls are readable and that a
  445. * write of the same value should be filtered out (it's valid to send
  446. * the same event number again to the firmware). We therefore return 0,
  447. * meaning "no event" so valid event numbers will always be a change
  448. */
  449. ucontrol->value.integer.value[0] = 0;
  450. return 0;
  451. }
  452. static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
  453. {
  454. unsigned int out, rd, wr, vol;
  455. if (len > ADSP_MAX_STD_CTRL_SIZE) {
  456. rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ;
  457. wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE;
  458. vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
  459. out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
  460. } else {
  461. rd = SNDRV_CTL_ELEM_ACCESS_READ;
  462. wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
  463. vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
  464. out = 0;
  465. }
  466. if (in) {
  467. out |= rd;
  468. if (in & WMFW_CTL_FLAG_WRITEABLE)
  469. out |= wr;
  470. if (in & WMFW_CTL_FLAG_VOLATILE)
  471. out |= vol;
  472. } else {
  473. out |= rd | wr | vol;
  474. }
  475. return out;
  476. }
  477. static void wm_adsp_ctl_work(struct work_struct *work)
  478. {
  479. struct wm_coeff_ctl *ctl = container_of(work,
  480. struct wm_coeff_ctl,
  481. work);
  482. struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
  483. struct wm_adsp *dsp = container_of(cs_ctl->dsp,
  484. struct wm_adsp,
  485. cs_dsp);
  486. struct snd_kcontrol_new *kcontrol;
  487. kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
  488. if (!kcontrol)
  489. return;
  490. kcontrol->name = ctl->name;
  491. kcontrol->info = wm_coeff_info;
  492. kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
  493. kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
  494. kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
  495. kcontrol->access = wmfw_convert_flags(cs_ctl->flags, cs_ctl->len);
  496. switch (cs_ctl->type) {
  497. case WMFW_CTL_TYPE_ACKED:
  498. kcontrol->get = wm_coeff_get_acked;
  499. kcontrol->put = wm_coeff_put_acked;
  500. break;
  501. default:
  502. if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
  503. ctl->bytes_ext.max = cs_ctl->len;
  504. ctl->bytes_ext.get = wm_coeff_tlv_get;
  505. ctl->bytes_ext.put = wm_coeff_tlv_put;
  506. } else {
  507. kcontrol->get = wm_coeff_get;
  508. kcontrol->put = wm_coeff_put;
  509. }
  510. break;
  511. }
  512. snd_soc_add_component_controls(dsp->component, kcontrol, 1);
  513. kfree(kcontrol);
  514. }
  515. static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl)
  516. {
  517. struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp);
  518. struct cs_dsp *cs_dsp = &dsp->cs_dsp;
  519. struct wm_coeff_ctl *ctl;
  520. char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
  521. const char *region_name;
  522. int ret;
  523. if (cs_ctl->flags & WMFW_CTL_FLAG_SYS)
  524. return 0;
  525. region_name = cs_dsp_mem_region_name(cs_ctl->alg_region.type);
  526. if (!region_name) {
  527. adsp_err(dsp, "Unknown region type: %d\n", cs_ctl->alg_region.type);
  528. return -EINVAL;
  529. }
  530. switch (cs_dsp->fw_ver) {
  531. case 0:
  532. case 1:
  533. ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
  534. "%s %s %x", cs_dsp->name, region_name,
  535. cs_ctl->alg_region.alg);
  536. break;
  537. case 2:
  538. ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
  539. "%s%c %.12s %x", cs_dsp->name, *region_name,
  540. wm_adsp_fw_text[dsp->fw], cs_ctl->alg_region.alg);
  541. break;
  542. default:
  543. ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
  544. "%s %.12s %x", cs_dsp->name,
  545. wm_adsp_fw_text[dsp->fw], cs_ctl->alg_region.alg);
  546. break;
  547. }
  548. if (cs_ctl->subname) {
  549. int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
  550. int skip = 0;
  551. if (dsp->component->name_prefix)
  552. avail -= strlen(dsp->component->name_prefix) + 1;
  553. /* Truncate the subname from the start if it is too long */
  554. if (cs_ctl->subname_len > avail)
  555. skip = cs_ctl->subname_len - avail;
  556. snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret,
  557. " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip);
  558. }
  559. ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
  560. if (!ctl)
  561. return -ENOMEM;
  562. ctl->cs_ctl = cs_ctl;
  563. ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
  564. if (!ctl->name) {
  565. ret = -ENOMEM;
  566. goto err_ctl;
  567. }
  568. cs_ctl->priv = ctl;
  569. INIT_WORK(&ctl->work, wm_adsp_ctl_work);
  570. schedule_work(&ctl->work);
  571. return 0;
  572. err_ctl:
  573. kfree(ctl);
  574. return ret;
  575. }
  576. static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
  577. {
  578. struct wm_coeff_ctl *ctl = cs_ctl->priv;
  579. cancel_work_sync(&ctl->work);
  580. kfree(ctl->name);
  581. kfree(ctl);
  582. }
  583. int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
  584. unsigned int alg, void *buf, size_t len)
  585. {
  586. struct cs_dsp_coeff_ctl *cs_ctl;
  587. struct wm_coeff_ctl *ctl;
  588. struct snd_kcontrol *kcontrol;
  589. char ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
  590. int ret;
  591. if (dsp->hibernate)
  592. return 0;
  593. mutex_lock(&dsp->cs_dsp.pwr_lock);
  594. cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
  595. ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
  596. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  597. if (ret)
  598. return ret;
  599. if (cs_ctl->flags & WMFW_CTL_FLAG_SYS)
  600. return 0;
  601. ctl = cs_ctl->priv;
  602. if (dsp->component->name_prefix)
  603. snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s",
  604. dsp->component->name_prefix, ctl->name);
  605. else
  606. snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s",
  607. ctl->name);
  608. kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl_name);
  609. if (!kcontrol) {
  610. adsp_dbg(dsp, "Can't find kcontrol %s\n", ctl_name);
  611. return -EINVAL;
  612. }
  613. snd_ctl_notify(dsp->component->card->snd_card,
  614. SNDRV_CTL_EVENT_MASK_VALUE, &kcontrol->id);
  615. return 0;
  616. }
  617. EXPORT_SYMBOL_GPL(wm_adsp_write_ctl);
  618. int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
  619. unsigned int alg, void *buf, size_t len)
  620. {
  621. int ret = 0;
  622. if (!dsp->hibernate) {
  623. mutex_lock(&dsp->cs_dsp.pwr_lock);
  624. ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg),
  625. 0, buf, len);
  626. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  627. }
  628. return ret;
  629. }
  630. EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
  631. static void wm_adsp_release_firmware_files(struct wm_adsp *dsp,
  632. const struct firmware *wmfw_firmware,
  633. char *wmfw_filename,
  634. const struct firmware *coeff_firmware,
  635. char *coeff_filename)
  636. {
  637. if (wmfw_firmware)
  638. release_firmware(wmfw_firmware);
  639. kfree(wmfw_filename);
  640. if (coeff_firmware)
  641. release_firmware(coeff_firmware);
  642. kfree(coeff_filename);
  643. }
  644. static int wm_adsp_request_firmware_file(struct wm_adsp *dsp,
  645. const struct firmware **firmware, char **filename,
  646. const char *dir, const char *system_name,
  647. const char *asoc_component_prefix,
  648. const char *filetype)
  649. {
  650. struct cs_dsp *cs_dsp = &dsp->cs_dsp;
  651. char *s, c;
  652. int ret = 0;
  653. if (system_name && asoc_component_prefix)
  654. *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, dsp->part,
  655. dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name,
  656. asoc_component_prefix, filetype);
  657. else if (system_name)
  658. *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part,
  659. dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name,
  660. filetype);
  661. else
  662. *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, dsp->fwf_name,
  663. wm_adsp_fw[dsp->fw].file, filetype);
  664. if (*filename == NULL)
  665. return -ENOMEM;
  666. /*
  667. * Make sure that filename is lower-case and any non alpha-numeric
  668. * characters except full stop and forward slash are replaced with
  669. * hyphens.
  670. */
  671. s = *filename;
  672. while (*s) {
  673. c = *s;
  674. if (isalnum(c))
  675. *s = tolower(c);
  676. else if ((c != '.') && (c != '/'))
  677. *s = '-';
  678. s++;
  679. }
  680. ret = firmware_request_nowarn(firmware, *filename, cs_dsp->dev);
  681. if (ret != 0) {
  682. adsp_dbg(dsp, "Failed to request '%s'\n", *filename);
  683. kfree(*filename);
  684. *filename = NULL;
  685. }
  686. return ret;
  687. }
  688. static const char *cirrus_dir = "cirrus/";
  689. static int wm_adsp_request_firmware_files(struct wm_adsp *dsp,
  690. const struct firmware **wmfw_firmware,
  691. char **wmfw_filename,
  692. const struct firmware **coeff_firmware,
  693. char **coeff_filename)
  694. {
  695. const char *system_name = dsp->system_name;
  696. const char *asoc_component_prefix = dsp->component->name_prefix;
  697. int ret = 0;
  698. if (system_name && asoc_component_prefix) {
  699. if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename,
  700. cirrus_dir, system_name,
  701. asoc_component_prefix, "wmfw")) {
  702. adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename);
  703. wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
  704. cirrus_dir, system_name,
  705. asoc_component_prefix, "bin");
  706. return 0;
  707. }
  708. }
  709. if (system_name) {
  710. if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename,
  711. cirrus_dir, system_name,
  712. NULL, "wmfw")) {
  713. adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename);
  714. if (asoc_component_prefix)
  715. wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
  716. cirrus_dir, system_name,
  717. asoc_component_prefix, "bin");
  718. if (!*coeff_firmware)
  719. wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
  720. cirrus_dir, system_name,
  721. NULL, "bin");
  722. return 0;
  723. }
  724. }
  725. if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename,
  726. "", NULL, NULL, "wmfw")) {
  727. adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename);
  728. wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
  729. "", NULL, NULL, "bin");
  730. return 0;
  731. }
  732. ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename,
  733. cirrus_dir, NULL, NULL, "wmfw");
  734. if (!ret) {
  735. adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename);
  736. wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename,
  737. cirrus_dir, NULL, NULL, "bin");
  738. return 0;
  739. }
  740. adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n",
  741. cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file,
  742. system_name, asoc_component_prefix);
  743. return -ENOENT;
  744. }
  745. static int wm_adsp_common_init(struct wm_adsp *dsp)
  746. {
  747. char *p;
  748. INIT_LIST_HEAD(&dsp->compr_list);
  749. INIT_LIST_HEAD(&dsp->buffer_list);
  750. if (!dsp->fwf_name) {
  751. p = devm_kstrdup(dsp->cs_dsp.dev, dsp->cs_dsp.name, GFP_KERNEL);
  752. if (!p)
  753. return -ENOMEM;
  754. dsp->fwf_name = p;
  755. for (; *p != 0; ++p)
  756. *p = tolower(*p);
  757. }
  758. return 0;
  759. }
  760. int wm_adsp1_init(struct wm_adsp *dsp)
  761. {
  762. int ret;
  763. dsp->cs_dsp.client_ops = &wm_adsp1_client_ops;
  764. ret = cs_dsp_adsp1_init(&dsp->cs_dsp);
  765. if (ret)
  766. return ret;
  767. return wm_adsp_common_init(dsp);
  768. }
  769. EXPORT_SYMBOL_GPL(wm_adsp1_init);
  770. int wm_adsp1_event(struct snd_soc_dapm_widget *w,
  771. struct snd_kcontrol *kcontrol,
  772. int event)
  773. {
  774. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  775. struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
  776. struct wm_adsp *dsp = &dsps[w->shift];
  777. int ret = 0;
  778. char *wmfw_filename = NULL;
  779. const struct firmware *wmfw_firmware = NULL;
  780. char *coeff_filename = NULL;
  781. const struct firmware *coeff_firmware = NULL;
  782. dsp->component = component;
  783. switch (event) {
  784. case SND_SOC_DAPM_POST_PMU:
  785. ret = wm_adsp_request_firmware_files(dsp,
  786. &wmfw_firmware, &wmfw_filename,
  787. &coeff_firmware, &coeff_filename);
  788. if (ret)
  789. break;
  790. ret = cs_dsp_adsp1_power_up(&dsp->cs_dsp,
  791. wmfw_firmware, wmfw_filename,
  792. coeff_firmware, coeff_filename,
  793. wm_adsp_fw_text[dsp->fw]);
  794. wm_adsp_release_firmware_files(dsp,
  795. wmfw_firmware, wmfw_filename,
  796. coeff_firmware, coeff_filename);
  797. break;
  798. case SND_SOC_DAPM_PRE_PMD:
  799. cs_dsp_adsp1_power_down(&dsp->cs_dsp);
  800. break;
  801. default:
  802. break;
  803. }
  804. return ret;
  805. }
  806. EXPORT_SYMBOL_GPL(wm_adsp1_event);
  807. int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq)
  808. {
  809. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  810. struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
  811. struct wm_adsp *dsp = &dsps[w->shift];
  812. return cs_dsp_set_dspclk(&dsp->cs_dsp, freq);
  813. }
  814. EXPORT_SYMBOL_GPL(wm_adsp2_set_dspclk);
  815. int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
  816. struct snd_ctl_elem_value *ucontrol)
  817. {
  818. struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
  819. struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
  820. struct soc_mixer_control *mc =
  821. (struct soc_mixer_control *)kcontrol->private_value;
  822. struct wm_adsp *dsp = &dsps[mc->shift - 1];
  823. ucontrol->value.integer.value[0] = dsp->preloaded;
  824. return 0;
  825. }
  826. EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get);
  827. int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
  828. struct snd_ctl_elem_value *ucontrol)
  829. {
  830. struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
  831. struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
  832. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  833. struct soc_mixer_control *mc =
  834. (struct soc_mixer_control *)kcontrol->private_value;
  835. struct wm_adsp *dsp = &dsps[mc->shift - 1];
  836. char preload[32];
  837. if (dsp->preloaded == ucontrol->value.integer.value[0])
  838. return 0;
  839. snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name);
  840. if (ucontrol->value.integer.value[0] || dsp->toggle_preload)
  841. snd_soc_component_force_enable_pin(component, preload);
  842. else
  843. snd_soc_component_disable_pin(component, preload);
  844. snd_soc_dapm_sync(dapm);
  845. flush_work(&dsp->boot_work);
  846. dsp->preloaded = ucontrol->value.integer.value[0];
  847. if (dsp->toggle_preload) {
  848. snd_soc_component_disable_pin(component, preload);
  849. snd_soc_dapm_sync(dapm);
  850. }
  851. return 1;
  852. }
  853. EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
  854. static void wm_adsp_boot_work(struct work_struct *work)
  855. {
  856. struct wm_adsp *dsp = container_of(work,
  857. struct wm_adsp,
  858. boot_work);
  859. int ret = 0;
  860. char *wmfw_filename = NULL;
  861. const struct firmware *wmfw_firmware = NULL;
  862. char *coeff_filename = NULL;
  863. const struct firmware *coeff_firmware = NULL;
  864. ret = wm_adsp_request_firmware_files(dsp,
  865. &wmfw_firmware, &wmfw_filename,
  866. &coeff_firmware, &coeff_filename);
  867. if (ret)
  868. return;
  869. cs_dsp_power_up(&dsp->cs_dsp,
  870. wmfw_firmware, wmfw_filename,
  871. coeff_firmware, coeff_filename,
  872. wm_adsp_fw_text[dsp->fw]);
  873. wm_adsp_release_firmware_files(dsp,
  874. wmfw_firmware, wmfw_filename,
  875. coeff_firmware, coeff_filename);
  876. }
  877. int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
  878. struct snd_kcontrol *kcontrol, int event)
  879. {
  880. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  881. struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
  882. struct wm_adsp *dsp = &dsps[w->shift];
  883. switch (event) {
  884. case SND_SOC_DAPM_PRE_PMU:
  885. queue_work(system_unbound_wq, &dsp->boot_work);
  886. break;
  887. case SND_SOC_DAPM_PRE_PMD:
  888. cs_dsp_power_down(&dsp->cs_dsp);
  889. break;
  890. default:
  891. break;
  892. }
  893. return 0;
  894. }
  895. EXPORT_SYMBOL_GPL(wm_adsp_early_event);
  896. static int wm_adsp_event_post_run(struct cs_dsp *cs_dsp)
  897. {
  898. struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp);
  899. if (wm_adsp_fw[dsp->fw].num_caps != 0)
  900. return wm_adsp_buffer_init(dsp);
  901. return 0;
  902. }
  903. static void wm_adsp_event_post_stop(struct cs_dsp *cs_dsp)
  904. {
  905. struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp);
  906. if (wm_adsp_fw[dsp->fw].num_caps != 0)
  907. wm_adsp_buffer_free(dsp);
  908. dsp->fatal_error = false;
  909. }
  910. int wm_adsp_event(struct snd_soc_dapm_widget *w,
  911. struct snd_kcontrol *kcontrol, int event)
  912. {
  913. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  914. struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
  915. struct wm_adsp *dsp = &dsps[w->shift];
  916. int ret = 0;
  917. switch (event) {
  918. case SND_SOC_DAPM_POST_PMU:
  919. flush_work(&dsp->boot_work);
  920. ret = cs_dsp_run(&dsp->cs_dsp);
  921. break;
  922. case SND_SOC_DAPM_PRE_PMD:
  923. cs_dsp_stop(&dsp->cs_dsp);
  924. break;
  925. default:
  926. break;
  927. }
  928. return ret;
  929. }
  930. EXPORT_SYMBOL_GPL(wm_adsp_event);
  931. int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component)
  932. {
  933. char preload[32];
  934. snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name);
  935. snd_soc_component_disable_pin(component, preload);
  936. cs_dsp_init_debugfs(&dsp->cs_dsp, component->debugfs_root);
  937. dsp->component = component;
  938. return 0;
  939. }
  940. EXPORT_SYMBOL_GPL(wm_adsp2_component_probe);
  941. int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component)
  942. {
  943. cs_dsp_cleanup_debugfs(&dsp->cs_dsp);
  944. return 0;
  945. }
  946. EXPORT_SYMBOL_GPL(wm_adsp2_component_remove);
  947. int wm_adsp2_init(struct wm_adsp *dsp)
  948. {
  949. int ret;
  950. INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
  951. dsp->sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr);
  952. dsp->cs_dsp.client_ops = &wm_adsp2_client_ops;
  953. ret = cs_dsp_adsp2_init(&dsp->cs_dsp);
  954. if (ret)
  955. return ret;
  956. return wm_adsp_common_init(dsp);
  957. }
  958. EXPORT_SYMBOL_GPL(wm_adsp2_init);
  959. int wm_halo_init(struct wm_adsp *dsp)
  960. {
  961. int ret;
  962. INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
  963. dsp->sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr);
  964. dsp->cs_dsp.client_ops = &wm_adsp2_client_ops;
  965. ret = cs_dsp_halo_init(&dsp->cs_dsp);
  966. if (ret)
  967. return ret;
  968. return wm_adsp_common_init(dsp);
  969. }
  970. EXPORT_SYMBOL_GPL(wm_halo_init);
  971. void wm_adsp2_remove(struct wm_adsp *dsp)
  972. {
  973. cs_dsp_remove(&dsp->cs_dsp);
  974. }
  975. EXPORT_SYMBOL_GPL(wm_adsp2_remove);
  976. static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
  977. {
  978. return compr->buf != NULL;
  979. }
  980. static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
  981. {
  982. struct wm_adsp_compr_buf *buf = NULL, *tmp;
  983. if (compr->dsp->fatal_error)
  984. return -EINVAL;
  985. list_for_each_entry(tmp, &compr->dsp->buffer_list, list) {
  986. if (!tmp->name || !strcmp(compr->name, tmp->name)) {
  987. buf = tmp;
  988. break;
  989. }
  990. }
  991. if (!buf)
  992. return -EINVAL;
  993. compr->buf = buf;
  994. buf->compr = compr;
  995. return 0;
  996. }
  997. static void wm_adsp_compr_detach(struct wm_adsp_compr *compr)
  998. {
  999. if (!compr)
  1000. return;
  1001. /* Wake the poll so it can see buffer is no longer attached */
  1002. if (compr->stream)
  1003. snd_compr_fragment_elapsed(compr->stream);
  1004. if (wm_adsp_compr_attached(compr)) {
  1005. compr->buf->compr = NULL;
  1006. compr->buf = NULL;
  1007. }
  1008. }
  1009. int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
  1010. {
  1011. struct wm_adsp_compr *compr, *tmp;
  1012. struct snd_soc_pcm_runtime *rtd = stream->private_data;
  1013. int ret = 0;
  1014. mutex_lock(&dsp->cs_dsp.pwr_lock);
  1015. if (wm_adsp_fw[dsp->fw].num_caps == 0) {
  1016. adsp_err(dsp, "%s: Firmware does not support compressed API\n",
  1017. asoc_rtd_to_codec(rtd, 0)->name);
  1018. ret = -ENXIO;
  1019. goto out;
  1020. }
  1021. if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
  1022. adsp_err(dsp, "%s: Firmware does not support stream direction\n",
  1023. asoc_rtd_to_codec(rtd, 0)->name);
  1024. ret = -EINVAL;
  1025. goto out;
  1026. }
  1027. list_for_each_entry(tmp, &dsp->compr_list, list) {
  1028. if (!strcmp(tmp->name, asoc_rtd_to_codec(rtd, 0)->name)) {
  1029. adsp_err(dsp, "%s: Only a single stream supported per dai\n",
  1030. asoc_rtd_to_codec(rtd, 0)->name);
  1031. ret = -EBUSY;
  1032. goto out;
  1033. }
  1034. }
  1035. compr = kzalloc(sizeof(*compr), GFP_KERNEL);
  1036. if (!compr) {
  1037. ret = -ENOMEM;
  1038. goto out;
  1039. }
  1040. compr->dsp = dsp;
  1041. compr->stream = stream;
  1042. compr->name = asoc_rtd_to_codec(rtd, 0)->name;
  1043. list_add_tail(&compr->list, &dsp->compr_list);
  1044. stream->runtime->private_data = compr;
  1045. out:
  1046. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  1047. return ret;
  1048. }
  1049. EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
  1050. int wm_adsp_compr_free(struct snd_soc_component *component,
  1051. struct snd_compr_stream *stream)
  1052. {
  1053. struct wm_adsp_compr *compr = stream->runtime->private_data;
  1054. struct wm_adsp *dsp = compr->dsp;
  1055. mutex_lock(&dsp->cs_dsp.pwr_lock);
  1056. wm_adsp_compr_detach(compr);
  1057. list_del(&compr->list);
  1058. kfree(compr->raw_buf);
  1059. kfree(compr);
  1060. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  1061. return 0;
  1062. }
  1063. EXPORT_SYMBOL_GPL(wm_adsp_compr_free);
  1064. static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
  1065. struct snd_compr_params *params)
  1066. {
  1067. struct wm_adsp_compr *compr = stream->runtime->private_data;
  1068. struct wm_adsp *dsp = compr->dsp;
  1069. const struct wm_adsp_fw_caps *caps;
  1070. const struct snd_codec_desc *desc;
  1071. int i, j;
  1072. if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE ||
  1073. params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE ||
  1074. params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
  1075. params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
  1076. params->buffer.fragment_size % CS_DSP_DATA_WORD_SIZE) {
  1077. compr_err(compr, "Invalid buffer fragsize=%d fragments=%d\n",
  1078. params->buffer.fragment_size,
  1079. params->buffer.fragments);
  1080. return -EINVAL;
  1081. }
  1082. for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) {
  1083. caps = &wm_adsp_fw[dsp->fw].caps[i];
  1084. desc = &caps->desc;
  1085. if (caps->id != params->codec.id)
  1086. continue;
  1087. if (stream->direction == SND_COMPRESS_PLAYBACK) {
  1088. if (desc->max_ch < params->codec.ch_out)
  1089. continue;
  1090. } else {
  1091. if (desc->max_ch < params->codec.ch_in)
  1092. continue;
  1093. }
  1094. if (!(desc->formats & (1 << params->codec.format)))
  1095. continue;
  1096. for (j = 0; j < desc->num_sample_rates; ++j)
  1097. if (desc->sample_rates[j] == params->codec.sample_rate)
  1098. return 0;
  1099. }
  1100. compr_err(compr, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
  1101. params->codec.id, params->codec.ch_in, params->codec.ch_out,
  1102. params->codec.sample_rate, params->codec.format);
  1103. return -EINVAL;
  1104. }
  1105. static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
  1106. {
  1107. return compr->size.fragment_size / CS_DSP_DATA_WORD_SIZE;
  1108. }
  1109. int wm_adsp_compr_set_params(struct snd_soc_component *component,
  1110. struct snd_compr_stream *stream,
  1111. struct snd_compr_params *params)
  1112. {
  1113. struct wm_adsp_compr *compr = stream->runtime->private_data;
  1114. unsigned int size;
  1115. int ret;
  1116. ret = wm_adsp_compr_check_params(stream, params);
  1117. if (ret)
  1118. return ret;
  1119. compr->size = params->buffer;
  1120. compr_dbg(compr, "fragment_size=%d fragments=%d\n",
  1121. compr->size.fragment_size, compr->size.fragments);
  1122. size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
  1123. compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
  1124. if (!compr->raw_buf)
  1125. return -ENOMEM;
  1126. compr->sample_rate = params->codec.sample_rate;
  1127. return 0;
  1128. }
  1129. EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
  1130. int wm_adsp_compr_get_caps(struct snd_soc_component *component,
  1131. struct snd_compr_stream *stream,
  1132. struct snd_compr_caps *caps)
  1133. {
  1134. struct wm_adsp_compr *compr = stream->runtime->private_data;
  1135. int fw = compr->dsp->fw;
  1136. int i;
  1137. if (wm_adsp_fw[fw].caps) {
  1138. for (i = 0; i < wm_adsp_fw[fw].num_caps; i++)
  1139. caps->codecs[i] = wm_adsp_fw[fw].caps[i].id;
  1140. caps->num_codecs = i;
  1141. caps->direction = wm_adsp_fw[fw].compr_direction;
  1142. caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE;
  1143. caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE;
  1144. caps->min_fragments = WM_ADSP_MIN_FRAGMENTS;
  1145. caps->max_fragments = WM_ADSP_MAX_FRAGMENTS;
  1146. }
  1147. return 0;
  1148. }
  1149. EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
  1150. static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
  1151. unsigned int field_offset, u32 *data)
  1152. {
  1153. return cs_dsp_read_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type,
  1154. buf->host_buf_ptr + field_offset, data);
  1155. }
  1156. static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
  1157. unsigned int field_offset, u32 data)
  1158. {
  1159. return cs_dsp_write_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type,
  1160. buf->host_buf_ptr + field_offset,
  1161. data);
  1162. }
  1163. static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
  1164. {
  1165. const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
  1166. struct wm_adsp_buffer_region *region;
  1167. u32 offset = 0;
  1168. int i, ret;
  1169. buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions),
  1170. GFP_KERNEL);
  1171. if (!buf->regions)
  1172. return -ENOMEM;
  1173. for (i = 0; i < caps->num_regions; ++i) {
  1174. region = &buf->regions[i];
  1175. region->offset = offset;
  1176. region->mem_type = caps->region_defs[i].mem_type;
  1177. ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
  1178. &region->base_addr);
  1179. if (ret < 0)
  1180. goto err;
  1181. ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
  1182. &offset);
  1183. if (ret < 0)
  1184. goto err;
  1185. region->cumulative_size = offset;
  1186. compr_dbg(buf,
  1187. "region=%d type=%d base=%08x off=%08x size=%08x\n",
  1188. i, region->mem_type, region->base_addr,
  1189. region->offset, region->cumulative_size);
  1190. }
  1191. return 0;
  1192. err:
  1193. kfree(buf->regions);
  1194. return ret;
  1195. }
  1196. static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)
  1197. {
  1198. buf->irq_count = 0xFFFFFFFF;
  1199. buf->read_index = -1;
  1200. buf->avail = 0;
  1201. }
  1202. static struct wm_adsp_compr_buf *wm_adsp_buffer_alloc(struct wm_adsp *dsp)
  1203. {
  1204. struct wm_adsp_compr_buf *buf;
  1205. buf = kzalloc(sizeof(*buf), GFP_KERNEL);
  1206. if (!buf)
  1207. return NULL;
  1208. buf->dsp = dsp;
  1209. wm_adsp_buffer_clear(buf);
  1210. return buf;
  1211. }
  1212. static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
  1213. {
  1214. struct cs_dsp_alg_region *alg_region;
  1215. struct wm_adsp_compr_buf *buf;
  1216. u32 xmalg, addr, magic;
  1217. int i, ret;
  1218. alg_region = cs_dsp_find_alg_region(&dsp->cs_dsp, WMFW_ADSP2_XM, dsp->cs_dsp.fw_id);
  1219. if (!alg_region) {
  1220. adsp_err(dsp, "No algorithm region found\n");
  1221. return -EINVAL;
  1222. }
  1223. xmalg = dsp->sys_config_size / sizeof(__be32);
  1224. addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
  1225. ret = cs_dsp_read_data_word(&dsp->cs_dsp, WMFW_ADSP2_XM, addr, &magic);
  1226. if (ret < 0)
  1227. return ret;
  1228. if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
  1229. return -ENODEV;
  1230. buf = wm_adsp_buffer_alloc(dsp);
  1231. if (!buf)
  1232. return -ENOMEM;
  1233. addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
  1234. for (i = 0; i < 5; ++i) {
  1235. ret = cs_dsp_read_data_word(&dsp->cs_dsp, WMFW_ADSP2_XM, addr,
  1236. &buf->host_buf_ptr);
  1237. if (ret < 0)
  1238. goto err;
  1239. if (buf->host_buf_ptr)
  1240. break;
  1241. usleep_range(1000, 2000);
  1242. }
  1243. if (!buf->host_buf_ptr) {
  1244. ret = -EIO;
  1245. goto err;
  1246. }
  1247. buf->host_buf_mem_type = WMFW_ADSP2_XM;
  1248. ret = wm_adsp_buffer_populate(buf);
  1249. if (ret < 0)
  1250. goto err;
  1251. list_add_tail(&buf->list, &dsp->buffer_list);
  1252. compr_dbg(buf, "legacy host_buf_ptr=%x\n", buf->host_buf_ptr);
  1253. return 0;
  1254. err:
  1255. kfree(buf);
  1256. return ret;
  1257. }
  1258. static int wm_adsp_buffer_parse_coeff(struct cs_dsp_coeff_ctl *cs_ctl)
  1259. {
  1260. struct wm_adsp_host_buf_coeff_v1 coeff_v1;
  1261. struct wm_adsp_compr_buf *buf;
  1262. struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp);
  1263. unsigned int version = 0;
  1264. int ret, i;
  1265. for (i = 0; i < 5; ++i) {
  1266. ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, &coeff_v1,
  1267. min(cs_ctl->len, sizeof(coeff_v1)));
  1268. if (ret < 0)
  1269. return ret;
  1270. if (coeff_v1.host_buf_ptr)
  1271. break;
  1272. usleep_range(1000, 2000);
  1273. }
  1274. if (!coeff_v1.host_buf_ptr) {
  1275. adsp_err(dsp, "Failed to acquire host buffer\n");
  1276. return -EIO;
  1277. }
  1278. buf = wm_adsp_buffer_alloc(dsp);
  1279. if (!buf)
  1280. return -ENOMEM;
  1281. buf->host_buf_mem_type = cs_ctl->alg_region.type;
  1282. buf->host_buf_ptr = be32_to_cpu(coeff_v1.host_buf_ptr);
  1283. ret = wm_adsp_buffer_populate(buf);
  1284. if (ret < 0)
  1285. goto err;
  1286. /*
  1287. * v0 host_buffer coefficients didn't have versioning, so if the
  1288. * control is one word, assume version 0.
  1289. */
  1290. if (cs_ctl->len == 4)
  1291. goto done;
  1292. version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK;
  1293. version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
  1294. if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
  1295. adsp_err(dsp,
  1296. "Host buffer coeff ver %u > supported version %u\n",
  1297. version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
  1298. ret = -EINVAL;
  1299. goto err;
  1300. }
  1301. cs_dsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
  1302. buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", dsp->part,
  1303. (char *)&coeff_v1.name);
  1304. done:
  1305. list_add_tail(&buf->list, &dsp->buffer_list);
  1306. compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
  1307. buf->host_buf_ptr, version);
  1308. return version;
  1309. err:
  1310. kfree(buf);
  1311. return ret;
  1312. }
  1313. static int wm_adsp_buffer_init(struct wm_adsp *dsp)
  1314. {
  1315. struct cs_dsp_coeff_ctl *cs_ctl;
  1316. int ret;
  1317. list_for_each_entry(cs_ctl, &dsp->cs_dsp.ctl_list, list) {
  1318. if (cs_ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
  1319. continue;
  1320. if (!cs_ctl->enabled)
  1321. continue;
  1322. ret = wm_adsp_buffer_parse_coeff(cs_ctl);
  1323. if (ret < 0) {
  1324. adsp_err(dsp, "Failed to parse coeff: %d\n", ret);
  1325. goto error;
  1326. } else if (ret == 0) {
  1327. /* Only one buffer supported for version 0 */
  1328. return 0;
  1329. }
  1330. }
  1331. if (list_empty(&dsp->buffer_list)) {
  1332. /* Fall back to legacy support */
  1333. ret = wm_adsp_buffer_parse_legacy(dsp);
  1334. if (ret == -ENODEV)
  1335. adsp_info(dsp, "Legacy support not available\n");
  1336. else if (ret)
  1337. adsp_warn(dsp, "Failed to parse legacy: %d\n", ret);
  1338. }
  1339. return 0;
  1340. error:
  1341. wm_adsp_buffer_free(dsp);
  1342. return ret;
  1343. }
  1344. static int wm_adsp_buffer_free(struct wm_adsp *dsp)
  1345. {
  1346. struct wm_adsp_compr_buf *buf, *tmp;
  1347. list_for_each_entry_safe(buf, tmp, &dsp->buffer_list, list) {
  1348. wm_adsp_compr_detach(buf->compr);
  1349. kfree(buf->name);
  1350. kfree(buf->regions);
  1351. list_del(&buf->list);
  1352. kfree(buf);
  1353. }
  1354. return 0;
  1355. }
  1356. static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
  1357. {
  1358. int ret;
  1359. ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
  1360. if (ret < 0) {
  1361. compr_err(buf, "Failed to check buffer error: %d\n", ret);
  1362. return ret;
  1363. }
  1364. if (buf->error != 0) {
  1365. compr_err(buf, "Buffer error occurred: %d\n", buf->error);
  1366. return -EIO;
  1367. }
  1368. return 0;
  1369. }
  1370. int wm_adsp_compr_trigger(struct snd_soc_component *component,
  1371. struct snd_compr_stream *stream, int cmd)
  1372. {
  1373. struct wm_adsp_compr *compr = stream->runtime->private_data;
  1374. struct wm_adsp *dsp = compr->dsp;
  1375. int ret = 0;
  1376. compr_dbg(compr, "Trigger: %d\n", cmd);
  1377. mutex_lock(&dsp->cs_dsp.pwr_lock);
  1378. switch (cmd) {
  1379. case SNDRV_PCM_TRIGGER_START:
  1380. if (!wm_adsp_compr_attached(compr)) {
  1381. ret = wm_adsp_compr_attach(compr);
  1382. if (ret < 0) {
  1383. compr_err(compr, "Failed to link buffer and stream: %d\n",
  1384. ret);
  1385. break;
  1386. }
  1387. }
  1388. ret = wm_adsp_buffer_get_error(compr->buf);
  1389. if (ret < 0)
  1390. break;
  1391. /* Trigger the IRQ at one fragment of data */
  1392. ret = wm_adsp_buffer_write(compr->buf,
  1393. HOST_BUFFER_FIELD(high_water_mark),
  1394. wm_adsp_compr_frag_words(compr));
  1395. if (ret < 0) {
  1396. compr_err(compr, "Failed to set high water mark: %d\n",
  1397. ret);
  1398. break;
  1399. }
  1400. break;
  1401. case SNDRV_PCM_TRIGGER_STOP:
  1402. if (wm_adsp_compr_attached(compr))
  1403. wm_adsp_buffer_clear(compr->buf);
  1404. break;
  1405. default:
  1406. ret = -EINVAL;
  1407. break;
  1408. }
  1409. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  1410. return ret;
  1411. }
  1412. EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
  1413. static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
  1414. {
  1415. int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
  1416. return buf->regions[last_region].cumulative_size;
  1417. }
  1418. static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
  1419. {
  1420. u32 next_read_index, next_write_index;
  1421. int write_index, read_index, avail;
  1422. int ret;
  1423. /* Only sync read index if we haven't already read a valid index */
  1424. if (buf->read_index < 0) {
  1425. ret = wm_adsp_buffer_read(buf,
  1426. HOST_BUFFER_FIELD(next_read_index),
  1427. &next_read_index);
  1428. if (ret < 0)
  1429. return ret;
  1430. read_index = sign_extend32(next_read_index, 23);
  1431. if (read_index < 0) {
  1432. compr_dbg(buf, "Avail check on unstarted stream\n");
  1433. return 0;
  1434. }
  1435. buf->read_index = read_index;
  1436. }
  1437. ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
  1438. &next_write_index);
  1439. if (ret < 0)
  1440. return ret;
  1441. write_index = sign_extend32(next_write_index, 23);
  1442. avail = write_index - buf->read_index;
  1443. if (avail < 0)
  1444. avail += wm_adsp_buffer_size(buf);
  1445. compr_dbg(buf, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
  1446. buf->read_index, write_index, avail * CS_DSP_DATA_WORD_SIZE);
  1447. buf->avail = avail;
  1448. return 0;
  1449. }
  1450. int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
  1451. {
  1452. struct wm_adsp_compr_buf *buf;
  1453. struct wm_adsp_compr *compr;
  1454. int ret = 0;
  1455. mutex_lock(&dsp->cs_dsp.pwr_lock);
  1456. if (list_empty(&dsp->buffer_list)) {
  1457. ret = -ENODEV;
  1458. goto out;
  1459. }
  1460. adsp_dbg(dsp, "Handling buffer IRQ\n");
  1461. list_for_each_entry(buf, &dsp->buffer_list, list) {
  1462. compr = buf->compr;
  1463. ret = wm_adsp_buffer_get_error(buf);
  1464. if (ret < 0)
  1465. goto out_notify; /* Wake poll to report error */
  1466. ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
  1467. &buf->irq_count);
  1468. if (ret < 0) {
  1469. compr_err(buf, "Failed to get irq_count: %d\n", ret);
  1470. goto out;
  1471. }
  1472. ret = wm_adsp_buffer_update_avail(buf);
  1473. if (ret < 0) {
  1474. compr_err(buf, "Error reading avail: %d\n", ret);
  1475. goto out;
  1476. }
  1477. if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
  1478. ret = WM_ADSP_COMPR_VOICE_TRIGGER;
  1479. out_notify:
  1480. if (compr && compr->stream)
  1481. snd_compr_fragment_elapsed(compr->stream);
  1482. }
  1483. out:
  1484. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  1485. return ret;
  1486. }
  1487. EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
  1488. static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
  1489. {
  1490. if (buf->irq_count & 0x01)
  1491. return 0;
  1492. compr_dbg(buf, "Enable IRQ(0x%x) for next fragment\n", buf->irq_count);
  1493. buf->irq_count |= 0x01;
  1494. return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
  1495. buf->irq_count);
  1496. }
  1497. int wm_adsp_compr_pointer(struct snd_soc_component *component,
  1498. struct snd_compr_stream *stream,
  1499. struct snd_compr_tstamp *tstamp)
  1500. {
  1501. struct wm_adsp_compr *compr = stream->runtime->private_data;
  1502. struct wm_adsp *dsp = compr->dsp;
  1503. struct wm_adsp_compr_buf *buf;
  1504. int ret = 0;
  1505. compr_dbg(compr, "Pointer request\n");
  1506. mutex_lock(&dsp->cs_dsp.pwr_lock);
  1507. buf = compr->buf;
  1508. if (dsp->fatal_error || !buf || buf->error) {
  1509. snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
  1510. ret = -EIO;
  1511. goto out;
  1512. }
  1513. if (buf->avail < wm_adsp_compr_frag_words(compr)) {
  1514. ret = wm_adsp_buffer_update_avail(buf);
  1515. if (ret < 0) {
  1516. compr_err(compr, "Error reading avail: %d\n", ret);
  1517. goto out;
  1518. }
  1519. /*
  1520. * If we really have less than 1 fragment available tell the
  1521. * DSP to inform us once a whole fragment is available.
  1522. */
  1523. if (buf->avail < wm_adsp_compr_frag_words(compr)) {
  1524. ret = wm_adsp_buffer_get_error(buf);
  1525. if (ret < 0) {
  1526. if (buf->error)
  1527. snd_compr_stop_error(stream,
  1528. SNDRV_PCM_STATE_XRUN);
  1529. goto out;
  1530. }
  1531. ret = wm_adsp_buffer_reenable_irq(buf);
  1532. if (ret < 0) {
  1533. compr_err(compr, "Failed to re-enable buffer IRQ: %d\n",
  1534. ret);
  1535. goto out;
  1536. }
  1537. }
  1538. }
  1539. tstamp->copied_total = compr->copied_total;
  1540. tstamp->copied_total += buf->avail * CS_DSP_DATA_WORD_SIZE;
  1541. tstamp->sampling_rate = compr->sample_rate;
  1542. out:
  1543. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  1544. return ret;
  1545. }
  1546. EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
  1547. static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
  1548. {
  1549. struct wm_adsp_compr_buf *buf = compr->buf;
  1550. unsigned int adsp_addr;
  1551. int mem_type, nwords, max_read;
  1552. int i, ret;
  1553. /* Calculate read parameters */
  1554. for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
  1555. if (buf->read_index < buf->regions[i].cumulative_size)
  1556. break;
  1557. if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
  1558. return -EINVAL;
  1559. mem_type = buf->regions[i].mem_type;
  1560. adsp_addr = buf->regions[i].base_addr +
  1561. (buf->read_index - buf->regions[i].offset);
  1562. max_read = wm_adsp_compr_frag_words(compr);
  1563. nwords = buf->regions[i].cumulative_size - buf->read_index;
  1564. if (nwords > target)
  1565. nwords = target;
  1566. if (nwords > buf->avail)
  1567. nwords = buf->avail;
  1568. if (nwords > max_read)
  1569. nwords = max_read;
  1570. if (!nwords)
  1571. return 0;
  1572. /* Read data from DSP */
  1573. ret = cs_dsp_read_raw_data_block(&buf->dsp->cs_dsp, mem_type, adsp_addr,
  1574. nwords, (__be32 *)compr->raw_buf);
  1575. if (ret < 0)
  1576. return ret;
  1577. cs_dsp_remove_padding(compr->raw_buf, nwords);
  1578. /* update read index to account for words read */
  1579. buf->read_index += nwords;
  1580. if (buf->read_index == wm_adsp_buffer_size(buf))
  1581. buf->read_index = 0;
  1582. ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
  1583. buf->read_index);
  1584. if (ret < 0)
  1585. return ret;
  1586. /* update avail to account for words read */
  1587. buf->avail -= nwords;
  1588. return nwords;
  1589. }
  1590. static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
  1591. char __user *buf, size_t count)
  1592. {
  1593. struct wm_adsp *dsp = compr->dsp;
  1594. int ntotal = 0;
  1595. int nwords, nbytes;
  1596. compr_dbg(compr, "Requested read of %zu bytes\n", count);
  1597. if (dsp->fatal_error || !compr->buf || compr->buf->error) {
  1598. snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
  1599. return -EIO;
  1600. }
  1601. count /= CS_DSP_DATA_WORD_SIZE;
  1602. do {
  1603. nwords = wm_adsp_buffer_capture_block(compr, count);
  1604. if (nwords < 0) {
  1605. compr_err(compr, "Failed to capture block: %d\n",
  1606. nwords);
  1607. return nwords;
  1608. }
  1609. nbytes = nwords * CS_DSP_DATA_WORD_SIZE;
  1610. compr_dbg(compr, "Read %d bytes\n", nbytes);
  1611. if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
  1612. compr_err(compr, "Failed to copy data to user: %d, %d\n",
  1613. ntotal, nbytes);
  1614. return -EFAULT;
  1615. }
  1616. count -= nwords;
  1617. ntotal += nbytes;
  1618. } while (nwords > 0 && count > 0);
  1619. compr->copied_total += ntotal;
  1620. return ntotal;
  1621. }
  1622. int wm_adsp_compr_copy(struct snd_soc_component *component,
  1623. struct snd_compr_stream *stream, char __user *buf,
  1624. size_t count)
  1625. {
  1626. struct wm_adsp_compr *compr = stream->runtime->private_data;
  1627. struct wm_adsp *dsp = compr->dsp;
  1628. int ret;
  1629. mutex_lock(&dsp->cs_dsp.pwr_lock);
  1630. if (stream->direction == SND_COMPRESS_CAPTURE)
  1631. ret = wm_adsp_compr_read(compr, buf, count);
  1632. else
  1633. ret = -ENOTSUPP;
  1634. mutex_unlock(&dsp->cs_dsp.pwr_lock);
  1635. return ret;
  1636. }
  1637. EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
  1638. static void wm_adsp_fatal_error(struct cs_dsp *cs_dsp)
  1639. {
  1640. struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp);
  1641. struct wm_adsp_compr *compr;
  1642. dsp->fatal_error = true;
  1643. list_for_each_entry(compr, &dsp->compr_list, list) {
  1644. if (compr->stream)
  1645. snd_compr_fragment_elapsed(compr->stream);
  1646. }
  1647. }
  1648. irqreturn_t wm_adsp2_bus_error(int irq, void *data)
  1649. {
  1650. struct wm_adsp *dsp = (struct wm_adsp *)data;
  1651. cs_dsp_adsp2_bus_error(&dsp->cs_dsp);
  1652. return IRQ_HANDLED;
  1653. }
  1654. EXPORT_SYMBOL_GPL(wm_adsp2_bus_error);
  1655. irqreturn_t wm_halo_bus_error(int irq, void *data)
  1656. {
  1657. struct wm_adsp *dsp = (struct wm_adsp *)data;
  1658. cs_dsp_halo_bus_error(&dsp->cs_dsp);
  1659. return IRQ_HANDLED;
  1660. }
  1661. EXPORT_SYMBOL_GPL(wm_halo_bus_error);
  1662. irqreturn_t wm_halo_wdt_expire(int irq, void *data)
  1663. {
  1664. struct wm_adsp *dsp = data;
  1665. cs_dsp_halo_wdt_expire(&dsp->cs_dsp);
  1666. return IRQ_HANDLED;
  1667. }
  1668. EXPORT_SYMBOL_GPL(wm_halo_wdt_expire);
  1669. static const struct cs_dsp_client_ops wm_adsp1_client_ops = {
  1670. .control_add = wm_adsp_control_add,
  1671. .control_remove = wm_adsp_control_remove,
  1672. };
  1673. static const struct cs_dsp_client_ops wm_adsp2_client_ops = {
  1674. .control_add = wm_adsp_control_add,
  1675. .control_remove = wm_adsp_control_remove,
  1676. .post_run = wm_adsp_event_post_run,
  1677. .post_stop = wm_adsp_event_post_stop,
  1678. .watchdog_expired = wm_adsp_fatal_error,
  1679. };
  1680. MODULE_LICENSE("GPL v2");