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