• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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