1 /*
2 * Copyright (C) 2021–2022 Beijing OSWare Technology Co., Ltd
3 * This file contains confidential and proprietary information of
4 * OSWare Technology Co., Ltd
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <linux/dmaengine.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/time.h>
22 #include <linux/delay.h>
23
24 #include "audio_driver_log.h"
25 #include "audio_platform_if.h"
26 #include "imx8mm_platform.h"
27 #include "sai_driver.h"
28 #include "osal_mem.h"
29 #include "imx8mm_common.h"
30
31 #define HDF_LOG_TAG imx8mm_dma_driver
DMATxComplete(void * arg)32 static void DMATxComplete(void *arg)
33 {
34 struct dma_tx_state state;
35 enum dma_status status;
36
37 struct PlatformData *platformData = (struct PlatformData *)arg;
38 struct PrivPlatformData *ppd = (struct PrivPlatformData *)platformData->dmaPrv;
39
40 ppd->tx_dma_pos += platformData->renderBufInfo.periodSize;
41 if (ppd->tx_dma_pos == platformData->renderBufInfo.cirBufSize) {
42 ppd->tx_dma_pos = 0;
43 }
44 #ifdef RING_BUFFER_DEBUG
45 AUDIO_DRIVER_LOG_INFO("dma tx complete. pos:%x", ppd->tx_dma_pos);
46 #endif
47 status = dmaengine_tx_status(ppd->dma_chan_tx, ppd->cookie_tx, &state);
48 }
49
DMADeinitTxBuff(struct PlatformData * platformData)50 int32_t DMADeinitTxBuff(struct PlatformData *platformData)
51 {
52 struct PrivPlatformData *ppd;
53 AUDIO_DRIVER_LOG_ERR("%s", __func__);
54 if (platformData == NULL) {
55 AUDIO_DRIVER_LOG_ERR("privplatform data is null");
56 return HDF_FAILURE;
57 }
58
59 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
60 if (ppd->dma_chan_tx) {
61 dmaengine_terminate_sync(ppd->dma_chan_tx);
62 dma_release_channel(ppd->dma_chan_tx);
63 ppd->dma_chan_tx = NULL;
64 dma_free_wc(&ppd->pdev->dev, platformData->renderBufInfo.cirBufSize,
65 platformData->renderBufInfo.virtAddr,
66 platformData->renderBufInfo.phyAddr);
67 platformData->renderBufInfo.phyAddr = 0;
68 platformData->renderBufInfo.virtAddr = NULL;
69 } else {
70 AUDIO_DRIVER_LOG_ERR("dma tx chan is null");
71 }
72
73 return HDF_SUCCESS;
74 }
75
DMAInitTxBuff(struct PlatformData * platformData)76 int32_t DMAInitTxBuff(struct PlatformData *platformData)
77 {
78 uint64_t buffSize;
79
80 struct device *dev = NULL;
81 struct PrivPlatformData *ppd = NULL;
82 gfp_t gfp_flags;
83
84 if (platformData == NULL) {
85 return HDF_FAILURE;
86 }
87
88 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
89 dev = &ppd->pdev->dev;
90
91 gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN;
92 if (platformData->renderBufInfo.virtAddr != NULL) {
93 return HDF_SUCCESS;
94 }
95
96 buffSize = platformData->renderBufInfo.cirBufMax;
97
98 if (buffSize < MIN_AIAO_BUFF_SIZE || buffSize > MAX_AIAO_BUFF_SIZE) {
99 AUDIO_DRIVER_LOG_ERR("buffsize error size:%d", buffSize);
100 return HDF_FAILURE;
101 }
102
103 platformData->renderBufInfo.phyAddr = 0;
104 platformData->renderBufInfo.virtAddr = dma_alloc_coherent(dev, buffSize,
105 (dma_addr_t *)&platformData->renderBufInfo.phyAddr, gfp_flags);
106 if (platformData->renderBufInfo.virtAddr == NULL) {
107 AUDIO_DRIVER_LOG_ERR("dma alloc failed");
108 return HDF_FAILURE;
109 }
110
111 platformData->renderBufInfo.cirBufSize = buffSize;
112 return HDF_SUCCESS;
113 }
114
DMAConfigTxBuff(struct PlatformData * platformData)115 int32_t DMAConfigTxBuff(struct PlatformData *platformData)
116 {
117 int32_t ret;
118 struct device *dev = NULL;
119 struct PrivPlatformData *ppd = NULL;
120 struct dma_slave_config slave_config = {};
121
122 if (platformData == NULL) {
123 return HDF_FAILURE;
124 }
125
126 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
127 dev = &ppd->pdev->dev;
128
129 ppd->dma_chan_tx = dma_request_slave_channel(dev, "tx");
130 if (!ppd->dma_chan_tx) {
131 AUDIO_DRIVER_LOG_ERR("slave channel failed");
132 return HDF_FAILURE;
133 }
134
135 slave_config.direction = DMA_MEM_TO_DEV;
136 slave_config.dst_addr = ppd->dma_addr_dst;
137 if (platformData->renderPcmInfo.bitWidth == BIT_WIDTH16) {
138 slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
139 } else if (platformData->renderPcmInfo.bitWidth == BIT_WIDTH32) {
140 slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
141 } else {
142 AUDIO_DRIVER_LOG_ERR("slave config biwidth is error");
143 return HDF_FAILURE;
144 }
145
146 slave_config.dst_maxburst = ppd->dma_maxburst_tx;
147
148 ret = dmaengine_slave_config(ppd->dma_chan_tx, &slave_config);
149 if (ret) {
150 AUDIO_DRIVER_LOG_ERR("slave config failed");
151 return HDF_FAILURE;
152 }
153
154 ppd->tx_dma_pos = 0;
155
156 return HDF_SUCCESS;
157 }
158
DMAEnableTx(const struct PlatformData * platformData)159 int32_t DMAEnableTx(const struct PlatformData *platformData)
160 {
161 struct PrivPlatformData *ppd = NULL;
162 enum dma_status status;
163 struct dma_tx_state state;
164 struct dma_async_tx_descriptor *desc;
165
166 AUDIO_DRIVER_LOG_ERR("%s", __func__);
167 if (platformData == NULL) {
168 AUDIO_DRIVER_LOG_ERR("input para is NULL");
169 return HDF_FAILURE;
170 }
171 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
172
173 desc = dmaengine_prep_dma_cyclic(ppd->dma_chan_tx,
174 platformData->renderBufInfo.phyAddr,
175 platformData->renderBufInfo.cirBufSize,
176 platformData->renderBufInfo.periodSize,
177 DMA_MEM_TO_DEV, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
178 if (!desc) {
179 AUDIO_DRIVER_LOG_ERR("failed to prepare slave DMA tx");
180 return HDF_FAILURE;
181 }
182 desc->callback = DMATxComplete;
183 desc->callback_param = (void*)platformData;
184
185 ppd->cookie_tx = dmaengine_submit(desc);
186
187 status = dmaengine_tx_status(ppd->dma_chan_tx, ppd->cookie_tx, &state);
188
189 dma_async_issue_pending(ppd->dma_chan_tx);
190
191 return HDF_SUCCESS;
192 }
193
DMADisableTx(struct PlatformData * platformData)194 int32_t DMADisableTx(struct PlatformData *platformData)
195 {
196 struct PrivPlatformData *ppd = NULL;
197 int32_t ret;
198 AUDIO_DRIVER_LOG_ERR("%s", __func__);
199 if (platformData == NULL) {
200 AUDIO_DRIVER_LOG_ERR("input para is NULL");
201 return HDF_FAILURE;
202 }
203 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
204
205 if (ppd->dma_chan_tx) {
206 dmaengine_terminate_all(ppd->dma_chan_tx);
207 } else {
208 AUDIO_DRIVER_LOG_ERR("dma chan not available");
209 }
210
211 ret = DMADeinitTxBuff(platformData);
212
213 return ret;
214 }
215
DMAPauseTx(struct PlatformData * platformData)216 int32_t DMAPauseTx(struct PlatformData *platformData)
217 {
218 struct PrivPlatformData *ppd = NULL;
219 AUDIO_DRIVER_LOG_ERR("%s", __func__);
220 if (platformData == NULL) {
221 AUDIO_DRIVER_LOG_ERR("input para is NULL");
222 return HDF_FAILURE;
223 }
224 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
225
226 if (ppd->dma_chan_tx) {
227 dmaengine_terminate_all(ppd->dma_chan_tx);
228 } else {
229 AUDIO_DRIVER_LOG_ERR("dma chan not available");
230 }
231
232 return HDF_SUCCESS;
233 }
234
DMARxComplete(void * arg)235 static void DMARxComplete(void *arg)
236 {
237 struct PlatformData *platformData = (struct PlatformData *)arg;
238 struct PrivPlatformData *ppd = (struct PrivPlatformData *)platformData->dmaPrv;
239 #ifdef RING_BUFFER_DEBUG
240 unsigned int owptr = ppd->rx_dma_pos;
241 #endif
242 ppd->rx_dma_pos += platformData->captureBufInfo.periodSize;
243 if (ppd->rx_dma_pos >= platformData->captureBufInfo.cirBufSize) {
244 ppd->rx_dma_pos -= platformData->captureBufInfo.cirBufSize;
245 }
246
247 #ifdef RING_BUFFER_DEBUG
248 AUDIO_DRIVER_LOG_INFO("dma rx complete. pos:%x", ppd->rx_dma_pos);
249
250 unsigned int wptr = 0, rptr = 0;
251 unsigned int free = 0, use = 0;
252 wptr = ppd->rx_dma_pos;
253 rptr = ppd->rx_read_pos;
254 if (wptr >= rptr) {
255 use = wptr - rptr;
256 free = platformData->captureBufInfo.cirBufSize - use;
257 } else {
258 free = rptr - wptr;
259 use = platformData->captureBufInfo.cirBufSize - free;
260 }
261 printk("[PRODUCTER]:virtAddr(0x%x) size=%u use=%u free=%u :rptr=%u owptr=%u cwptr=%u product=%d",
262 platformData->captureBufInfo.virtAddr, platformData->captureBufInfo.cirBufSize, use, free,
263 ppd->rx_read_pos, owptr, ppd->rx_dma_pos, platformData->captureBufInfo.periodSize);
264 #endif
265 }
266
DMADeinitRxBuff(struct PlatformData * platformData)267 int32_t DMADeinitRxBuff(struct PlatformData *platformData)
268 {
269 struct PrivPlatformData *ppd;
270 AUDIO_DRIVER_LOG_ERR("%s", __func__);
271 if (platformData == NULL) {
272 AUDIO_DRIVER_LOG_ERR("privplatform data is null");
273 return HDF_FAILURE;
274 }
275
276 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
277 if (ppd->dma_chan_rx) {
278 dmaengine_terminate_sync(ppd->dma_chan_rx);
279 dma_release_channel(ppd->dma_chan_rx);
280 ppd->dma_chan_rx = NULL;
281 dma_free_wc(&ppd->pdev->dev, platformData->captureBufInfo.cirBufSize,
282 platformData->captureBufInfo.virtAddr,
283 platformData->captureBufInfo.phyAddr);
284 platformData->captureBufInfo.phyAddr = 0;
285 platformData->captureBufInfo.virtAddr = NULL;
286 } else {
287 AUDIO_DRIVER_LOG_ERR("dma rx chan is null");
288 }
289
290 return HDF_SUCCESS;
291 }
292
DMAInitRxBuff(struct PlatformData * platformData)293 int32_t DMAInitRxBuff(struct PlatformData *platformData)
294 {
295 uint64_t buffSize;
296 struct device *dev = NULL;
297 struct PrivPlatformData *ppd = NULL;
298 gfp_t gfp_flags;
299
300 AUDIO_DRIVER_LOG_ERR("%s", __func__);
301 if (platformData == NULL) {
302 return HDF_FAILURE;
303 }
304 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
305 dev = &ppd->pdev->dev;
306
307 gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN;
308 if (platformData->captureBufInfo.virtAddr != NULL) {
309 return HDF_SUCCESS;
310 }
311
312 buffSize = platformData->captureBufInfo.cirBufMax;
313 if (buffSize < MIN_AIAO_BUFF_SIZE || buffSize > MAX_AIAO_BUFF_SIZE) {
314 return HDF_FAILURE;
315 }
316
317 platformData->captureBufInfo.phyAddr = 0;
318 platformData->captureBufInfo.virtAddr = dma_alloc_coherent(dev, buffSize,
319 (dma_addr_t *)&platformData->captureBufInfo.phyAddr, gfp_flags);
320 if (platformData->captureBufInfo.virtAddr == NULL) {
321 return HDF_FAILURE;
322 }
323 platformData->captureBufInfo.cirBufSize = buffSize;
324
325 return HDF_SUCCESS;
326 }
327
DMAConfigRxBuff(struct PlatformData * platformData)328 int32_t DMAConfigRxBuff(struct PlatformData *platformData)
329 {
330 int32_t ret;
331 struct device *dev = NULL;
332 struct PrivPlatformData *ppd = NULL;
333 struct dma_slave_config slave_config = {};
334
335 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
336 dev = &ppd->pdev->dev;
337
338 ppd->dma_chan_rx = dma_request_slave_channel(dev, "rx");
339 if (!ppd->dma_chan_rx) {
340 return HDF_FAILURE;
341 }
342
343 slave_config.direction = DMA_DEV_TO_MEM;
344 slave_config.src_addr = ppd->dma_addr_src;
345 if (platformData->capturePcmInfo.bitWidth == BIT_WIDTH16) {
346 slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
347 } else if (platformData->capturePcmInfo.bitWidth == BIT_WIDTH32) {
348 slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
349 } else {
350 return HDF_FAILURE;
351 }
352
353 slave_config.src_maxburst = ppd->dma_maxburst_rx;
354 ret = dmaengine_slave_config(ppd->dma_chan_rx, &slave_config);
355 if (ret) {
356 return HDF_FAILURE;
357 }
358
359 ppd->rx_dma_pos = 0;
360 ppd->rx_read_pos = 0;
361
362 return HDF_SUCCESS;
363 }
364
DMAEnableRx(const struct PlatformData * platformData)365 int32_t DMAEnableRx(const struct PlatformData *platformData)
366 {
367 struct PrivPlatformData *ppd = NULL;
368 struct dma_async_tx_descriptor *desc;
369
370 AUDIO_DRIVER_LOG_ERR("%s", __func__);
371 if (platformData == NULL) {
372 AUDIO_DRIVER_LOG_ERR("input para is NULL");
373 return HDF_FAILURE;
374 }
375 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
376
377 desc = dmaengine_prep_dma_cyclic(ppd->dma_chan_rx,
378 platformData->captureBufInfo.phyAddr,
379 platformData->captureBufInfo.cirBufSize,
380 platformData->captureBufInfo.periodSize,
381 DMA_DEV_TO_MEM, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
382 if (!desc) {
383 AUDIO_DRIVER_LOG_ERR("failed to prepare slave DMA rx");
384 return HDF_FAILURE;
385 }
386 desc->callback = DMARxComplete;
387 desc->callback_param = (void*)platformData;
388 ppd->cookie_rx = dmaengine_submit(desc);
389
390 dma_async_issue_pending(ppd->dma_chan_rx);
391
392 return HDF_SUCCESS;
393 }
394
DMADisableRx(struct PlatformData * platformData)395 int32_t DMADisableRx(struct PlatformData *platformData)
396 {
397 struct PrivPlatformData *ppd = NULL;
398 int32_t ret;
399 AUDIO_DRIVER_LOG_ERR("%s", __func__);
400 if (platformData == NULL) {
401 AUDIO_DRIVER_LOG_ERR("input para is NULL");
402 return HDF_FAILURE;
403 }
404 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
405
406 if (ppd->dma_chan_rx) {
407 dmaengine_terminate_all(ppd->dma_chan_rx);
408 } else {
409 AUDIO_DRIVER_LOG_ERR("dma chan not available");
410 }
411
412 ret = DMADeinitRxBuff(platformData);
413
414 return ret;
415 }
416
DMAPauseRx(struct PlatformData * platformData)417 int32_t DMAPauseRx(struct PlatformData *platformData)
418 {
419 struct PrivPlatformData *ppd = NULL;
420 AUDIO_DRIVER_LOG_ERR("%s", __func__);
421 if (platformData == NULL) {
422 AUDIO_DRIVER_LOG_ERR("input para is NULL");
423 return HDF_FAILURE;
424 }
425 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
426
427 if (ppd->dma_chan_rx) {
428 dmaengine_terminate_all(ppd->dma_chan_rx);
429 } else {
430 AUDIO_DRIVER_LOG_ERR("dma chan not available");
431 }
432
433 return HDF_SUCCESS;
434 }
435
DmaInit(struct PlatformData * platformData)436 int32_t DmaInit(struct PlatformData *platformData)
437 {
438 struct PrivPlatformData *ppd = NULL;
439 int32_t ret = 0;
440
441 if (platformData == NULL) {
442 AUDIO_DRIVER_LOG_ERR("input para is NULL");
443 return HDF_FAILURE;
444 }
445
446 ppd = (struct PrivPlatformData *)platformData->dmaPrv;
447 ret = dma_coerce_mask_and_coherent(&ppd->pdev->dev, DMA_BIT_MASK(32));
448
449 return ret;
450 }
451