cs_dsp.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * cs_dsp.h -- Cirrus Logic DSP firmware support
  4. *
  5. * Based on sound/soc/codecs/wm_adsp.h
  6. *
  7. * Copyright 2012 Wolfson Microelectronics plc
  8. * Copyright (C) 2015-2021 Cirrus Logic, Inc. and
  9. * Cirrus Logic International Semiconductor Ltd.
  10. */
  11. #ifndef __CS_DSP_H
  12. #define __CS_DSP_H
  13. #include <linux/bits.h>
  14. #include <linux/device.h>
  15. #include <linux/firmware.h>
  16. #include <linux/list.h>
  17. #include <linux/regmap.h>
  18. #define CS_ADSP2_REGION_0 BIT(0)
  19. #define CS_ADSP2_REGION_1 BIT(1)
  20. #define CS_ADSP2_REGION_2 BIT(2)
  21. #define CS_ADSP2_REGION_3 BIT(3)
  22. #define CS_ADSP2_REGION_4 BIT(4)
  23. #define CS_ADSP2_REGION_5 BIT(5)
  24. #define CS_ADSP2_REGION_6 BIT(6)
  25. #define CS_ADSP2_REGION_7 BIT(7)
  26. #define CS_ADSP2_REGION_8 BIT(8)
  27. #define CS_ADSP2_REGION_9 BIT(9)
  28. #define CS_ADSP2_REGION_1_9 (CS_ADSP2_REGION_1 | \
  29. CS_ADSP2_REGION_2 | CS_ADSP2_REGION_3 | \
  30. CS_ADSP2_REGION_4 | CS_ADSP2_REGION_5 | \
  31. CS_ADSP2_REGION_6 | CS_ADSP2_REGION_7 | \
  32. CS_ADSP2_REGION_8 | CS_ADSP2_REGION_9)
  33. #define CS_ADSP2_REGION_ALL (CS_ADSP2_REGION_0 | CS_ADSP2_REGION_1_9)
  34. #define CS_DSP_DATA_WORD_SIZE 3
  35. #define CS_DSP_DATA_WORD_BITS (3 * BITS_PER_BYTE)
  36. #define CS_DSP_ACKED_CTL_TIMEOUT_MS 100
  37. #define CS_DSP_ACKED_CTL_N_QUICKPOLLS 10
  38. #define CS_DSP_ACKED_CTL_MIN_VALUE 0
  39. #define CS_DSP_ACKED_CTL_MAX_VALUE 0xFFFFFF
  40. /**
  41. * struct cs_dsp_region - Describes a logical memory region in DSP address space
  42. * @type: Memory region type
  43. * @base: Address of region
  44. */
  45. struct cs_dsp_region {
  46. int type;
  47. unsigned int base;
  48. };
  49. /**
  50. * struct cs_dsp_alg_region - Describes a logical algorithm region in DSP address space
  51. * @list: List node for internal use
  52. * @alg: Algorithm id
  53. * @ver: Expected algorithm version
  54. * @type: Memory region type
  55. * @base: Address of region
  56. */
  57. struct cs_dsp_alg_region {
  58. struct list_head list;
  59. unsigned int alg;
  60. unsigned int ver;
  61. int type;
  62. unsigned int base;
  63. };
  64. /**
  65. * struct cs_dsp_coeff_ctl - Describes a coefficient control
  66. * @list: List node for internal use
  67. * @dsp: DSP instance associated with this control
  68. * @cache: Cached value of the control
  69. * @fw_name: Name of the firmware
  70. * @subname: Name of the control parsed from the WMFW
  71. * @subname_len: Length of subname
  72. * @offset: Offset of control within alg_region in words
  73. * @len: Length of the cached value in bytes
  74. * @type: One of the WMFW_CTL_TYPE_ control types defined in wmfw.h
  75. * @flags: Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h
  76. * @set: Flag indicating the value has been written by the user
  77. * @enabled: Flag indicating whether control is enabled
  78. * @alg_region: Logical region associated with this control
  79. * @priv: For use by the client
  80. */
  81. struct cs_dsp_coeff_ctl {
  82. struct list_head list;
  83. struct cs_dsp *dsp;
  84. void *cache;
  85. const char *fw_name;
  86. /* Subname is needed to match with firmware */
  87. const char *subname;
  88. unsigned int subname_len;
  89. unsigned int offset;
  90. size_t len;
  91. unsigned int type;
  92. unsigned int flags;
  93. unsigned int set:1;
  94. unsigned int enabled:1;
  95. struct cs_dsp_alg_region alg_region;
  96. void *priv;
  97. };
  98. struct cs_dsp_ops;
  99. struct cs_dsp_client_ops;
  100. /**
  101. * struct cs_dsp - Configuration and state of a Cirrus Logic DSP
  102. * @name: The name of the DSP instance
  103. * @rev: Revision of the DSP
  104. * @num: DSP instance number
  105. * @type: Type of DSP
  106. * @dev: Driver model representation of the device
  107. * @regmap: Register map of the device
  108. * @ops: Function pointers for internal callbacks
  109. * @client_ops: Function pointers for client callbacks
  110. * @base: Address of the DSP registers
  111. * @base_sysinfo: Address of the sysinfo register (Halo only)
  112. * @sysclk_reg: Address of the sysclk register (ADSP1 only)
  113. * @sysclk_mask: Mask of frequency bits within sysclk register (ADSP1 only)
  114. * @sysclk_shift: Shift of frequency bits within sysclk register (ADSP1 only)
  115. * @alg_regions: List of currently loaded algorithm regions
  116. * @fw_file_name: Filename of the current firmware
  117. * @fw_name: Name of the current firmware
  118. * @fw_id: ID of the current firmware, obtained from the wmfw
  119. * @fw_id_version: Version of the firmware, obtained from the wmfw
  120. * @fw_vendor_id: Vendor of the firmware, obtained from the wmfw
  121. * @mem: DSP memory region descriptions
  122. * @num_mems: Number of memory regions in this DSP
  123. * @fw_ver: Version of the wmfw file format
  124. * @booted: Flag indicating DSP has been configured
  125. * @running: Flag indicating DSP is executing firmware
  126. * @ctl_list: Controls defined within the loaded DSP firmware
  127. * @lock_regions: Enable MPU traps on specified memory regions
  128. * @pwr_lock: Lock used to serialize accesses
  129. * @debugfs_root: Debugfs directory for this DSP instance
  130. * @wmfw_file_name: Filename of the currently loaded firmware
  131. * @bin_file_name: Filename of the currently loaded coefficients
  132. */
  133. struct cs_dsp {
  134. const char *name;
  135. int rev;
  136. int num;
  137. int type;
  138. struct device *dev;
  139. struct regmap *regmap;
  140. const struct cs_dsp_ops *ops;
  141. const struct cs_dsp_client_ops *client_ops;
  142. unsigned int base;
  143. unsigned int base_sysinfo;
  144. unsigned int sysclk_reg;
  145. unsigned int sysclk_mask;
  146. unsigned int sysclk_shift;
  147. struct list_head alg_regions;
  148. const char *fw_name;
  149. unsigned int fw_id;
  150. unsigned int fw_id_version;
  151. unsigned int fw_vendor_id;
  152. const struct cs_dsp_region *mem;
  153. int num_mems;
  154. int fw_ver;
  155. bool booted;
  156. bool running;
  157. struct list_head ctl_list;
  158. struct mutex pwr_lock;
  159. unsigned int lock_regions;
  160. #ifdef CONFIG_DEBUG_FS
  161. struct dentry *debugfs_root;
  162. char *wmfw_file_name;
  163. char *bin_file_name;
  164. #endif
  165. };
  166. /**
  167. * struct cs_dsp_client_ops - client callbacks
  168. * @control_add: Called under the pwr_lock when a control is created
  169. * @control_remove: Called under the pwr_lock when a control is destroyed
  170. * @pre_run: Called under the pwr_lock by cs_dsp_run() before the core is started
  171. * @post_run: Called under the pwr_lock by cs_dsp_run() after the core is started
  172. * @pre_stop: Called under the pwr_lock by cs_dsp_stop() before the core is stopped
  173. * @post_stop: Called under the pwr_lock by cs_dsp_stop() after the core is stopped
  174. * @watchdog_expired: Called when a watchdog expiry is detected
  175. *
  176. * These callbacks give the cs_dsp client an opportunity to respond to events
  177. * or to perform actions atomically.
  178. */
  179. struct cs_dsp_client_ops {
  180. int (*control_add)(struct cs_dsp_coeff_ctl *ctl);
  181. void (*control_remove)(struct cs_dsp_coeff_ctl *ctl);
  182. int (*pre_run)(struct cs_dsp *dsp);
  183. int (*post_run)(struct cs_dsp *dsp);
  184. void (*pre_stop)(struct cs_dsp *dsp);
  185. void (*post_stop)(struct cs_dsp *dsp);
  186. void (*watchdog_expired)(struct cs_dsp *dsp);
  187. };
  188. int cs_dsp_adsp1_init(struct cs_dsp *dsp);
  189. int cs_dsp_adsp2_init(struct cs_dsp *dsp);
  190. int cs_dsp_halo_init(struct cs_dsp *dsp);
  191. int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
  192. const struct firmware *wmfw_firmware, char *wmfw_filename,
  193. const struct firmware *coeff_firmware, char *coeff_filename,
  194. const char *fw_name);
  195. void cs_dsp_adsp1_power_down(struct cs_dsp *dsp);
  196. int cs_dsp_power_up(struct cs_dsp *dsp,
  197. const struct firmware *wmfw_firmware, char *wmfw_filename,
  198. const struct firmware *coeff_firmware, char *coeff_filename,
  199. const char *fw_name);
  200. void cs_dsp_power_down(struct cs_dsp *dsp);
  201. int cs_dsp_run(struct cs_dsp *dsp);
  202. void cs_dsp_stop(struct cs_dsp *dsp);
  203. void cs_dsp_remove(struct cs_dsp *dsp);
  204. int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq);
  205. void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp);
  206. void cs_dsp_halo_bus_error(struct cs_dsp *dsp);
  207. void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp);
  208. void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root);
  209. void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp);
  210. int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id);
  211. int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
  212. const void *buf, size_t len);
  213. int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
  214. void *buf, size_t len);
  215. struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type,
  216. unsigned int alg);
  217. int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr,
  218. unsigned int num_words, __be32 *data);
  219. int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data);
  220. int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data);
  221. void cs_dsp_remove_padding(u32 *buf, int nwords);
  222. int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware,
  223. const char *file);
  224. struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
  225. int type, unsigned int id);
  226. const char *cs_dsp_mem_region_name(unsigned int type);
  227. /**
  228. * struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP
  229. * @data: Pointer to underlying buffer memory
  230. * @max: Pointer to end of the buffer memory
  231. * @bytes: Number of bytes read/written into the memory chunk
  232. * @cache: Temporary holding data as it is formatted
  233. * @cachebits: Number of bits of data currently in cache
  234. */
  235. struct cs_dsp_chunk {
  236. u8 *data;
  237. u8 *max;
  238. int bytes;
  239. u32 cache;
  240. int cachebits;
  241. };
  242. /**
  243. * cs_dsp_chunk() - Create a DSP memory chunk
  244. * @data: Pointer to the buffer that will be used to store data
  245. * @size: Size of the buffer in bytes
  246. *
  247. * Return: A cs_dsp_chunk structure
  248. */
  249. static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size)
  250. {
  251. struct cs_dsp_chunk ch = {
  252. .data = data,
  253. .max = data + size,
  254. };
  255. return ch;
  256. }
  257. /**
  258. * cs_dsp_chunk_end() - Check if a DSP memory chunk is full
  259. * @ch: Pointer to the chunk structure
  260. *
  261. * Return: True if the whole buffer has been read/written
  262. */
  263. static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch)
  264. {
  265. return ch->data == ch->max;
  266. }
  267. /**
  268. * cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk
  269. * @ch: Pointer to the chunk structure
  270. *
  271. * Return: Number of bytes read/written to the buffer
  272. */
  273. static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch)
  274. {
  275. return ch->bytes;
  276. }
  277. /**
  278. * cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk
  279. * @ch: Pointer to the chunk structure
  280. *
  281. * Return: True if the given address is within the buffer
  282. */
  283. static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr)
  284. {
  285. return (u8 *)addr >= ch->data && (u8 *)addr < ch->max;
  286. }
  287. int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val);
  288. int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch);
  289. int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits);
  290. #endif