1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // |
3 | // Copyright(c) 2021-2022 Intel Corporation. All rights reserved. |
4 | // |
5 | // Author: Cezary Rojewski <cezary.rojewski@intel.com> |
6 | // |
7 | |
8 | #include <linux/pci.h> |
9 | #include <sound/hda_register.h> |
10 | #include <sound/hdaudio_ext.h> |
11 | #include "cldma.h" |
12 | #include "registers.h" |
13 | |
14 | /* Stream Registers */ |
15 | #define AZX_CL_SD_BASE 0x80 |
16 | #define AZX_SD_CTL_STRM_MASK GENMASK(23, 20) |
17 | #define AZX_SD_CTL_STRM(s) (((s)->stream_tag << 20) & AZX_SD_CTL_STRM_MASK) |
18 | #define AZX_SD_BDLPL_BDLPLBA_MASK GENMASK(31, 7) |
19 | #define AZX_SD_BDLPL_BDLPLBA(lb) ((lb) & AZX_SD_BDLPL_BDLPLBA_MASK) |
20 | |
21 | /* Software Position Based FIFO Capability Registers */ |
22 | #define AZX_CL_SPBFCS 0x20 |
23 | #define AZX_REG_CL_SPBFCTL (AZX_CL_SPBFCS + 0x4) |
24 | #define AZX_REG_CL_SD_SPIB (AZX_CL_SPBFCS + 0x8) |
25 | |
26 | #define AVS_CL_OP_INTERVAL_US 3 |
27 | #define AVS_CL_OP_TIMEOUT_US 300 |
28 | #define AVS_CL_IOC_TIMEOUT_MS 300 |
29 | #define AVS_CL_STREAM_INDEX 0 |
30 | |
31 | struct hda_cldma { |
32 | struct device *dev; |
33 | struct hdac_bus *bus; |
34 | void __iomem *dsp_ba; |
35 | |
36 | unsigned int buffer_size; |
37 | unsigned int num_periods; |
38 | unsigned int stream_tag; |
39 | void __iomem *sd_addr; |
40 | |
41 | struct snd_dma_buffer dmab_data; |
42 | struct snd_dma_buffer dmab_bdl; |
43 | struct delayed_work memcpy_work; |
44 | struct completion completion; |
45 | |
46 | /* runtime */ |
47 | void *position; |
48 | unsigned int remaining; |
49 | unsigned int sd_status; |
50 | }; |
51 | |
52 | static void cldma_memcpy_work(struct work_struct *work); |
53 | |
54 | struct hda_cldma code_loader = { |
55 | .stream_tag = AVS_CL_STREAM_INDEX + 1, |
56 | .memcpy_work = __DELAYED_WORK_INITIALIZER(code_loader.memcpy_work, cldma_memcpy_work, 0), |
57 | .completion = COMPLETION_INITIALIZER(code_loader.completion), |
58 | }; |
59 | |
60 | void hda_cldma_fill(struct hda_cldma *cl) |
61 | { |
62 | unsigned int size, offset; |
63 | |
64 | if (cl->remaining > cl->buffer_size) |
65 | size = cl->buffer_size; |
66 | else |
67 | size = cl->remaining; |
68 | |
69 | offset = snd_hdac_stream_readl(cl, CL_SD_SPIB); |
70 | if (offset + size > cl->buffer_size) { |
71 | unsigned int ss; |
72 | |
73 | ss = cl->buffer_size - offset; |
74 | memcpy(cl->dmab_data.area + offset, cl->position, ss); |
75 | offset = 0; |
76 | size -= ss; |
77 | cl->position += ss; |
78 | cl->remaining -= ss; |
79 | } |
80 | |
81 | memcpy(cl->dmab_data.area + offset, cl->position, size); |
82 | cl->position += size; |
83 | cl->remaining -= size; |
84 | |
85 | snd_hdac_stream_writel(cl, CL_SD_SPIB, offset + size); |
86 | } |
87 | |
88 | static void cldma_memcpy_work(struct work_struct *work) |
89 | { |
90 | struct hda_cldma *cl = container_of(work, struct hda_cldma, memcpy_work.work); |
91 | int ret; |
92 | |
93 | ret = hda_cldma_start(cl); |
94 | if (ret < 0) { |
95 | dev_err(cl->dev, "cldma set RUN failed: %d\n" , ret); |
96 | return; |
97 | } |
98 | |
99 | while (true) { |
100 | ret = wait_for_completion_timeout(x: &cl->completion, |
101 | timeout: msecs_to_jiffies(AVS_CL_IOC_TIMEOUT_MS)); |
102 | if (!ret) { |
103 | dev_err(cl->dev, "cldma IOC timeout\n" ); |
104 | break; |
105 | } |
106 | |
107 | if (!(cl->sd_status & SD_INT_COMPLETE)) { |
108 | dev_err(cl->dev, "cldma transfer error, SD status: 0x%08x\n" , |
109 | cl->sd_status); |
110 | break; |
111 | } |
112 | |
113 | if (!cl->remaining) |
114 | break; |
115 | |
116 | reinit_completion(x: &cl->completion); |
117 | hda_cldma_fill(cl); |
118 | /* enable CLDMA interrupt */ |
119 | snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, |
120 | AVS_ADSP_ADSPIC_CLDMA); |
121 | } |
122 | } |
123 | |
124 | void hda_cldma_transfer(struct hda_cldma *cl, unsigned long start_delay) |
125 | { |
126 | if (!cl->remaining) |
127 | return; |
128 | |
129 | reinit_completion(x: &cl->completion); |
130 | /* fill buffer with the first chunk before scheduling run */ |
131 | hda_cldma_fill(cl); |
132 | |
133 | schedule_delayed_work(dwork: &cl->memcpy_work, delay: start_delay); |
134 | } |
135 | |
136 | int hda_cldma_start(struct hda_cldma *cl) |
137 | { |
138 | unsigned int reg; |
139 | |
140 | /* enable interrupts */ |
141 | snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, |
142 | AVS_ADSP_ADSPIC_CLDMA); |
143 | snd_hdac_stream_updateb(cl, SD_CTL, SD_INT_MASK | SD_CTL_DMA_START, |
144 | SD_INT_MASK | SD_CTL_DMA_START); |
145 | |
146 | /* await DMA engine start */ |
147 | return snd_hdac_stream_readb_poll(cl, SD_CTL, reg, reg & SD_CTL_DMA_START, |
148 | AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); |
149 | } |
150 | |
151 | int hda_cldma_stop(struct hda_cldma *cl) |
152 | { |
153 | unsigned int reg; |
154 | int ret; |
155 | |
156 | /* disable interrupts */ |
157 | snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, 0); |
158 | snd_hdac_stream_updateb(cl, SD_CTL, SD_INT_MASK | SD_CTL_DMA_START, 0); |
159 | |
160 | /* await DMA engine stop */ |
161 | ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, !(reg & SD_CTL_DMA_START), |
162 | AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); |
163 | cancel_delayed_work_sync(dwork: &cl->memcpy_work); |
164 | |
165 | return ret; |
166 | } |
167 | |
168 | int hda_cldma_reset(struct hda_cldma *cl) |
169 | { |
170 | unsigned int reg; |
171 | int ret; |
172 | |
173 | ret = hda_cldma_stop(cl); |
174 | if (ret < 0) { |
175 | dev_err(cl->dev, "cldma stop failed: %d\n" , ret); |
176 | return ret; |
177 | } |
178 | |
179 | snd_hdac_stream_updateb(cl, SD_CTL, SD_CTL_STREAM_RESET, SD_CTL_STREAM_RESET); |
180 | ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, (reg & SD_CTL_STREAM_RESET), |
181 | AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); |
182 | if (ret < 0) { |
183 | dev_err(cl->dev, "cldma set SRST failed: %d\n" , ret); |
184 | return ret; |
185 | } |
186 | |
187 | snd_hdac_stream_updateb(cl, SD_CTL, SD_CTL_STREAM_RESET, 0); |
188 | ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, !(reg & SD_CTL_STREAM_RESET), |
189 | AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); |
190 | if (ret < 0) { |
191 | dev_err(cl->dev, "cldma unset SRST failed: %d\n" , ret); |
192 | return ret; |
193 | } |
194 | |
195 | return 0; |
196 | } |
197 | |
198 | void hda_cldma_set_data(struct hda_cldma *cl, void *data, unsigned int size) |
199 | { |
200 | /* setup runtime */ |
201 | cl->position = data; |
202 | cl->remaining = size; |
203 | } |
204 | |
205 | static void cldma_setup_bdle(struct hda_cldma *cl, u32 bdle_size) |
206 | { |
207 | struct snd_dma_buffer *dmab = &cl->dmab_data; |
208 | __le32 *bdl = (__le32 *)cl->dmab_bdl.area; |
209 | int remaining = cl->buffer_size; |
210 | int offset = 0; |
211 | |
212 | cl->num_periods = 0; |
213 | |
214 | while (remaining > 0) { |
215 | phys_addr_t addr; |
216 | int chunk; |
217 | |
218 | addr = snd_sgbuf_get_addr(dmab, offset); |
219 | bdl[0] = cpu_to_le32(lower_32_bits(addr)); |
220 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); |
221 | chunk = snd_sgbuf_get_chunk_size(dmab, ofs: offset, size: bdle_size); |
222 | bdl[2] = cpu_to_le32(chunk); |
223 | |
224 | remaining -= chunk; |
225 | /* set IOC only for the last entry */ |
226 | bdl[3] = (remaining > 0) ? 0 : cpu_to_le32(0x01); |
227 | |
228 | bdl += 4; |
229 | offset += chunk; |
230 | cl->num_periods++; |
231 | } |
232 | } |
233 | |
234 | void hda_cldma_setup(struct hda_cldma *cl) |
235 | { |
236 | dma_addr_t bdl_addr = cl->dmab_bdl.addr; |
237 | |
238 | cldma_setup_bdle(cl, bdle_size: cl->buffer_size / 2); |
239 | |
240 | snd_hdac_stream_writel(cl, SD_BDLPL, AZX_SD_BDLPL_BDLPLBA(lower_32_bits(bdl_addr))); |
241 | snd_hdac_stream_writel(cl, SD_BDLPU, upper_32_bits(bdl_addr)); |
242 | |
243 | snd_hdac_stream_writel(cl, SD_CBL, cl->buffer_size); |
244 | snd_hdac_stream_writeb(cl, SD_LVI, cl->num_periods - 1); |
245 | |
246 | snd_hdac_stream_updatel(cl, SD_CTL, AZX_SD_CTL_STRM_MASK, AZX_SD_CTL_STRM(cl)); |
247 | /* enable spib */ |
248 | snd_hdac_stream_writel(cl, CL_SPBFCTL, 1); |
249 | } |
250 | |
251 | static irqreturn_t cldma_irq_handler(int irq, void *dev_id) |
252 | { |
253 | struct hda_cldma *cl = dev_id; |
254 | u32 adspis; |
255 | |
256 | adspis = snd_hdac_adsp_readl(cl, AVS_ADSP_REG_ADSPIS); |
257 | if (adspis == UINT_MAX) |
258 | return IRQ_NONE; |
259 | if (!(adspis & AVS_ADSP_ADSPIS_CLDMA)) |
260 | return IRQ_NONE; |
261 | |
262 | cl->sd_status = snd_hdac_stream_readb(cl, SD_STS); |
263 | dev_warn(cl->dev, "%s sd_status: 0x%08x\n" , __func__, cl->sd_status); |
264 | |
265 | /* disable CLDMA interrupt */ |
266 | snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, 0); |
267 | |
268 | complete(&cl->completion); |
269 | |
270 | return IRQ_HANDLED; |
271 | } |
272 | |
273 | int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, |
274 | unsigned int buffer_size) |
275 | { |
276 | struct pci_dev *pci = to_pci_dev(bus->dev); |
277 | int ret; |
278 | |
279 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev: bus->dev, size: buffer_size, dmab: &cl->dmab_data); |
280 | if (ret < 0) |
281 | return ret; |
282 | |
283 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev: bus->dev, BDL_SIZE, dmab: &cl->dmab_bdl); |
284 | if (ret < 0) |
285 | goto alloc_err; |
286 | |
287 | cl->dev = bus->dev; |
288 | cl->bus = bus; |
289 | cl->dsp_ba = dsp_ba; |
290 | cl->buffer_size = buffer_size; |
291 | cl->sd_addr = dsp_ba + AZX_CL_SD_BASE; |
292 | |
293 | ret = pci_request_irq(dev: pci, nr: 0, handler: cldma_irq_handler, NULL, dev_id: cl, fmt: "CLDMA" ); |
294 | if (ret < 0) { |
295 | dev_err(cl->dev, "Failed to request CLDMA IRQ handler: %d\n" , ret); |
296 | goto req_err; |
297 | } |
298 | |
299 | return 0; |
300 | |
301 | req_err: |
302 | snd_dma_free_pages(dmab: &cl->dmab_bdl); |
303 | alloc_err: |
304 | snd_dma_free_pages(dmab: &cl->dmab_data); |
305 | |
306 | return ret; |
307 | } |
308 | |
309 | void hda_cldma_free(struct hda_cldma *cl) |
310 | { |
311 | struct pci_dev *pci = to_pci_dev(cl->dev); |
312 | |
313 | pci_free_irq(dev: pci, nr: 0, dev_id: cl); |
314 | snd_dma_free_pages(dmab: &cl->dmab_data); |
315 | snd_dma_free_pages(dmab: &cl->dmab_bdl); |
316 | } |
317 | |