Commit | Line | Data |
---|---|---|
a4b12990 MB |
1 | /* |
2 | * Intel Smart Sound Technology | |
3 | * | |
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License version | |
8 | * 2 as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | */ | |
16 | ||
17 | #ifndef __SOUND_SOC_SST_DSP_PRIV_H | |
18 | #define __SOUND_SOC_SST_DSP_PRIV_H | |
19 | ||
20 | #include <linux/kernel.h> | |
21 | #include <linux/types.h> | |
22 | #include <linux/interrupt.h> | |
23 | #include <linux/firmware.h> | |
24 | ||
25 | struct sst_mem_block; | |
26 | struct sst_module; | |
27 | struct sst_fw; | |
28 | ||
29 | /* | |
30 | * DSP Operations exported by platform Audio DSP driver. | |
31 | */ | |
32 | struct sst_ops { | |
33 | /* DSP core boot / reset */ | |
34 | void (*boot)(struct sst_dsp *); | |
35 | void (*reset)(struct sst_dsp *); | |
36 | ||
37 | /* Shim IO */ | |
38 | void (*write)(void __iomem *addr, u32 offset, u32 value); | |
39 | u32 (*read)(void __iomem *addr, u32 offset); | |
40 | void (*write64)(void __iomem *addr, u32 offset, u64 value); | |
41 | u64 (*read64)(void __iomem *addr, u32 offset); | |
42 | ||
43 | /* DSP I/DRAM IO */ | |
44 | void (*ram_read)(struct sst_dsp *sst, void *dest, void __iomem *src, | |
45 | size_t bytes); | |
46 | void (*ram_write)(struct sst_dsp *sst, void __iomem *dest, void *src, | |
47 | size_t bytes); | |
48 | ||
49 | void (*dump)(struct sst_dsp *); | |
50 | ||
51 | /* IRQ handlers */ | |
52 | irqreturn_t (*irq_handler)(int irq, void *context); | |
53 | ||
54 | /* SST init and free */ | |
55 | int (*init)(struct sst_dsp *sst, struct sst_pdata *pdata); | |
56 | void (*free)(struct sst_dsp *sst); | |
57 | ||
58 | /* FW module parser/loader */ | |
59 | int (*parse_fw)(struct sst_fw *sst_fw); | |
60 | }; | |
61 | ||
62 | /* | |
63 | * Audio DSP memory offsets and addresses. | |
64 | */ | |
65 | struct sst_addr { | |
66 | u32 lpe_base; | |
67 | u32 shim_offset; | |
68 | u32 iram_offset; | |
69 | u32 dram_offset; | |
70 | void __iomem *lpe; | |
71 | void __iomem *shim; | |
72 | void __iomem *pci_cfg; | |
73 | void __iomem *fw_ext; | |
74 | }; | |
75 | ||
76 | /* | |
77 | * Audio DSP Mailbox configuration. | |
78 | */ | |
79 | struct sst_mailbox { | |
80 | void __iomem *in_base; | |
81 | void __iomem *out_base; | |
82 | size_t in_size; | |
83 | size_t out_size; | |
84 | }; | |
85 | ||
86 | /* | |
87 | * Audio DSP Firmware data types. | |
88 | */ | |
89 | enum sst_data_type { | |
90 | SST_DATA_M = 0, /* module block data */ | |
91 | SST_DATA_P = 1, /* peristant data (text, data) */ | |
92 | SST_DATA_S = 2, /* scratch data (usually buffers) */ | |
93 | }; | |
94 | ||
95 | /* | |
96 | * Audio DSP memory block types. | |
97 | */ | |
98 | enum sst_mem_type { | |
99 | SST_MEM_IRAM = 0, | |
100 | SST_MEM_DRAM = 1, | |
101 | SST_MEM_ANY = 2, | |
102 | SST_MEM_CACHE= 3, | |
103 | }; | |
104 | ||
105 | /* | |
106 | * Audio DSP Generic Firmware File. | |
107 | * | |
108 | * SST Firmware files can consist of 1..N modules. This generic structure is | |
109 | * used to manage each firmware file and it's modules regardless of SST firmware | |
110 | * type. A SST driver may load multiple FW files. | |
111 | */ | |
112 | struct sst_fw { | |
113 | struct sst_dsp *dsp; | |
114 | ||
115 | /* base addresses of FW file data */ | |
116 | dma_addr_t dmable_fw_paddr; /* physical address of fw data */ | |
117 | void *dma_buf; /* virtual address of fw data */ | |
118 | u32 size; /* size of fw data */ | |
119 | ||
120 | /* lists */ | |
121 | struct list_head list; /* DSP list of FW */ | |
122 | struct list_head module_list; /* FW list of modules */ | |
123 | ||
124 | void *private; /* core doesn't touch this */ | |
125 | }; | |
126 | ||
127 | /* | |
128 | * Audio DSP Generic Module data. | |
129 | * | |
130 | * This is used to dsecribe any sections of persistent (text and data) and | |
131 | * scratch (buffers) of module data in ADSP memory space. | |
132 | */ | |
133 | struct sst_module_data { | |
134 | ||
135 | enum sst_mem_type type; /* destination memory type */ | |
136 | enum sst_data_type data_type; /* type of module data */ | |
137 | ||
138 | u32 size; /* size in bytes */ | |
139 | u32 offset; /* offset in FW file */ | |
140 | u32 data_offset; /* offset in ADSP memory space */ | |
141 | void *data; /* module data */ | |
142 | }; | |
143 | ||
144 | /* | |
145 | * Audio DSP Generic Module Template. | |
146 | * | |
147 | * Used to define and register a new FW module. This data is extracted from | |
148 | * FW module header information. | |
149 | */ | |
150 | struct sst_module_template { | |
151 | u32 id; | |
152 | u32 entry; /* entry point */ | |
153 | struct sst_module_data s; /* scratch data */ | |
154 | struct sst_module_data p; /* peristant data */ | |
155 | }; | |
156 | ||
157 | /* | |
158 | * Audio DSP Generic Module. | |
159 | * | |
160 | * Each Firmware file can consist of 1..N modules. A module can span multiple | |
161 | * ADSP memory blocks. The simplest FW will be a file with 1 module. | |
162 | */ | |
163 | struct sst_module { | |
164 | struct sst_dsp *dsp; | |
165 | struct sst_fw *sst_fw; /* parent FW we belong too */ | |
166 | ||
167 | /* module configuration */ | |
168 | u32 id; | |
169 | u32 entry; /* module entry point */ | |
170 | u32 offset; /* module offset in firmware file */ | |
171 | u32 size; /* module size */ | |
172 | struct sst_module_data s; /* scratch data */ | |
173 | struct sst_module_data p; /* peristant data */ | |
174 | ||
175 | /* runtime */ | |
176 | u32 usage_count; /* can be unloaded if count == 0 */ | |
177 | void *private; /* core doesn't touch this */ | |
178 | ||
179 | /* lists */ | |
180 | struct list_head block_list; /* Module list of blocks in use */ | |
181 | struct list_head list; /* DSP list of modules */ | |
182 | struct list_head list_fw; /* FW list of modules */ | |
183 | }; | |
184 | ||
185 | /* | |
186 | * SST Memory Block operations. | |
187 | */ | |
188 | struct sst_block_ops { | |
189 | int (*enable)(struct sst_mem_block *block); | |
190 | int (*disable)(struct sst_mem_block *block); | |
191 | }; | |
192 | ||
193 | /* | |
194 | * SST Generic Memory Block. | |
195 | * | |
196 | * SST ADP memory has multiple IRAM and DRAM blocks. Some ADSP blocks can be | |
197 | * power gated. | |
198 | */ | |
199 | struct sst_mem_block { | |
200 | struct sst_dsp *dsp; | |
201 | struct sst_module *module; /* module that uses this block */ | |
202 | ||
203 | /* block config */ | |
204 | u32 offset; /* offset from base */ | |
205 | u32 size; /* block size */ | |
206 | u32 index; /* block index 0..N */ | |
207 | enum sst_mem_type type; /* block memory type IRAM/DRAM */ | |
208 | struct sst_block_ops *ops; /* block operations, if any */ | |
209 | ||
210 | /* block status */ | |
211 | enum sst_data_type data_type; /* data type held in this block */ | |
212 | u32 bytes_used; /* bytes in use by modules */ | |
213 | void *private; /* generic core does not touch this */ | |
214 | int users; /* number of modules using this block */ | |
215 | ||
216 | /* block lists */ | |
217 | struct list_head module_list; /* Module list of blocks */ | |
218 | struct list_head list; /* Map list of free/used blocks */ | |
219 | }; | |
220 | ||
221 | /* | |
222 | * Generic SST Shim Interface. | |
223 | */ | |
224 | struct sst_dsp { | |
225 | ||
226 | /* runtime */ | |
227 | struct sst_dsp_device *sst_dev; | |
228 | spinlock_t spinlock; /* IPC locking */ | |
229 | struct mutex mutex; /* DSP FW lock */ | |
230 | struct device *dev; | |
231 | void *thread_context; | |
232 | int irq; | |
233 | u32 id; | |
234 | ||
235 | /* list of free and used ADSP memory blocks */ | |
236 | struct list_head used_block_list; | |
237 | struct list_head free_block_list; | |
238 | ||
239 | /* operations */ | |
240 | struct sst_ops *ops; | |
241 | ||
242 | /* debug FS */ | |
243 | struct dentry *debugfs_root; | |
244 | ||
245 | /* base addresses */ | |
246 | struct sst_addr addr; | |
247 | ||
248 | /* mailbox */ | |
249 | struct sst_mailbox mailbox; | |
250 | ||
251 | /* SST FW files loaded and their modules */ | |
252 | struct list_head module_list; | |
253 | struct list_head fw_list; | |
254 | ||
255 | /* platform data */ | |
256 | struct sst_pdata *pdata; | |
257 | ||
258 | /* DMA FW loading */ | |
259 | struct sst_dma *dma; | |
260 | bool fw_use_dma; | |
261 | }; | |
262 | ||
263 | /* Size optimised DRAM/IRAM memcpy */ | |
264 | static inline void sst_dsp_write(struct sst_dsp *sst, void *src, | |
265 | u32 dest_offset, size_t bytes) | |
266 | { | |
267 | sst->ops->ram_write(sst, sst->addr.lpe + dest_offset, src, bytes); | |
268 | } | |
269 | ||
270 | static inline void sst_dsp_read(struct sst_dsp *sst, void *dest, | |
271 | u32 src_offset, size_t bytes) | |
272 | { | |
273 | sst->ops->ram_read(sst, dest, sst->addr.lpe + src_offset, bytes); | |
274 | } | |
275 | ||
276 | static inline void *sst_dsp_get_thread_context(struct sst_dsp *sst) | |
277 | { | |
278 | return sst->thread_context; | |
279 | } | |
280 | ||
281 | /* Create/Free FW files - can contain multiple modules */ | |
282 | struct sst_fw *sst_fw_new(struct sst_dsp *dsp, | |
283 | const struct firmware *fw, void *private); | |
284 | void sst_fw_free(struct sst_fw *sst_fw); | |
285 | void sst_fw_free_all(struct sst_dsp *dsp); | |
286 | ||
287 | /* Create/Free firmware modules */ | |
288 | struct sst_module *sst_module_new(struct sst_fw *sst_fw, | |
289 | struct sst_module_template *template, void *private); | |
290 | void sst_module_free(struct sst_module *sst_module); | |
291 | int sst_module_insert(struct sst_module *sst_module); | |
292 | int sst_module_remove(struct sst_module *sst_module); | |
293 | int sst_module_insert_fixed_block(struct sst_module *module, | |
294 | struct sst_module_data *data); | |
295 | struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id); | |
296 | ||
297 | /* allocate/free pesistent/scratch memory regions managed by drv */ | |
298 | struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp); | |
299 | void sst_mem_block_free_scratch(struct sst_dsp *dsp, | |
300 | struct sst_module *scratch); | |
301 | int sst_block_module_remove(struct sst_module *module); | |
302 | ||
303 | /* Register the DSPs memory blocks - would be nice to read from ACPI */ | |
304 | struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, | |
305 | u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index, | |
306 | void *private); | |
307 | void sst_mem_block_unregister_all(struct sst_dsp *dsp); | |
308 | ||
309 | #endif |