• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 HiHope Open Source Organization .
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 #include <sound/memalloc.h>
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/dma-mapping.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/notifier.h>
17 #include <linux/of.h>
18 #include <linux/of_dma.h>
19 #include <linux/of_device.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 #include <linux/stat.h>
23 #include <linux/string.h>
24 #include <linux/sysfs.h>
25 #include <linux/suspend.h>
26 
27 #include "audio_platform_base.h"
28 #include "osal_io.h"
29 #include "osal_uaccess.h"
30 #include "audio_driver_log.h"
31 #include "rk3568_dma_ops.h"
32 
33 #define HDF_LOG_TAG rk3568_platform_ops
34 
35 #define I2S1_ADDR 0xfe410000
36 #define I2S_TXDR 0x24
37 #define I2S_RXDR 0x28
38 
39 #define DMA_RX_CHANNEL 0
40 #define DMA_TX_CHANNEL 1
41 #define DMA_CHANNEL_MAX 2
42 
43 struct HdfDeviceObject *g_device;
44 
45 struct DmaRuntimeData {
46     struct dma_chan *dmaChn[DMA_CHANNEL_MAX];
47     dma_cookie_t cookie[DMA_CHANNEL_MAX];
48     uint32_t streamType;
49 };
50 static const char *g_i2s1DtsTreePath = "/i2s@fe410000";
51 static struct dma_chan *g_dmaChn[DMA_CHANNEL_MAX];
52 static dma_cookie_t g_cookie[DMA_CHANNEL_MAX];
53 static struct device *g_dmaDev;
54 
getDmaDevice(void)55 struct device *getDmaDevice(void)
56 {
57     struct device_node    *dmaOfNode = NULL;
58     struct platform_device *platformdev = NULL;
59 
60     dmaOfNode = of_find_node_by_path(g_i2s1DtsTreePath);
61     if (dmaOfNode == NULL) {
62         AUDIO_DEVICE_LOG_ERR("get device node failed.");
63         return NULL;
64     }
65     platformdev = of_find_device_by_node(dmaOfNode);
66     if (platformdev == NULL) {
67         AUDIO_DEVICE_LOG_ERR("get platformdev failed.");
68         return NULL;
69     }
70     g_dmaDev = &platformdev->dev;
71     return g_dmaDev;
72 }
73 
AudioDmaDeviceInit(const struct AudioCard * card,const struct PlatformDevice * platform)74 int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform)
75 {
76     struct PlatformData *data = NULL;
77     static const char * const dmaChannelNames[] = {
78         [DMA_RX_CHANNEL] = "rx",
79         [DMA_TX_CHANNEL] = "tx",
80     };
81     uint32_t i = 0;
82     struct device *dmaDevice = getDmaDevice();
83 
84     if (card == NULL) {
85         AUDIO_DEVICE_LOG_ERR("card is null.");
86         return HDF_FAILURE;
87     }
88     g_device = card->device;
89 
90     data = PlatformDataFromCard(card);
91     if (data == NULL) {
92         AUDIO_DEVICE_LOG_ERR("PlatformDataFromCard failed.");
93         return HDF_FAILURE;
94     }
95     if (data->platformInitFlag == true) {
96         AUDIO_DRIVER_LOG_DEBUG("platform init complete!");
97         return HDF_SUCCESS;
98     }
99     data->platformInitFlag = true;
100     for (i = 0; i <= 1; i++) {
101         g_dmaChn[i] = dma_request_slave_channel(dmaDevice,
102             dmaChannelNames[i]);
103         if (g_dmaChn[i] == NULL) {
104             AUDIO_DEVICE_LOG_ERR("dma_request_slave_channel streamType=%d failed", i);
105             return HDF_FAILURE;
106         }
107     }
108     AUDIO_DEVICE_LOG_DEBUG("success.");
109     return HDF_SUCCESS;
110 }
111 
112 
DmaRtdMemAlloc(struct PlatformData * data,enum AudioStreamType streamType)113 static int32_t DmaRtdMemAlloc(struct PlatformData *data, enum AudioStreamType streamType)
114 {
115     struct DmaRuntimeData *dmaRtd = NULL;
116 
117     if (data == NULL) {
118         AUDIO_DEVICE_LOG_ERR("data is null.");
119         return HDF_FAILURE;
120     }
121 
122     dmaRtd = kzalloc(sizeof(*dmaRtd), GFP_KERNEL);
123     if (!dmaRtd) {
124         AUDIO_DEVICE_LOG_ERR("AudioRenderBuffInit: fail.");
125         return HDF_FAILURE;
126     }
127     data->dmaPrv = dmaRtd;
128     dmaRtd->streamType = streamType;
129     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
130     dmaRtd->dmaChn[streamType] = g_dmaChn[streamType];
131     AUDIO_DEVICE_LOG_DEBUG("success.");
132     return HDF_SUCCESS;
133 }
134 
Rk3568DmaBufAlloc(struct PlatformData * data,const enum AudioStreamType streamType)135 int32_t Rk3568DmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType)
136 {
137     uint32_t preallocBufSize;
138     struct device *dmaDevice = getDmaDevice();
139 
140     if (data == NULL) {
141         AUDIO_DEVICE_LOG_ERR("data is null");
142         return HDF_FAILURE;
143     }
144 
145     if (dmaDevice == NULL) {
146         AUDIO_DEVICE_LOG_ERR("dmaDevice is null");
147         return HDF_FAILURE;
148     }
149 
150     if (streamType == AUDIO_CAPTURE_STREAM) {
151         if (data->captureBufInfo.virtAddr == NULL) {
152             preallocBufSize = data->captureBufInfo.cirBufMax;
153             dmaDevice->coherent_dma_mask = 0xffffffffUL;
154             data->captureBufInfo.virtAddr = dma_alloc_wc(dmaDevice, preallocBufSize,
155                 (dma_addr_t *)&data->captureBufInfo.phyAddr, GFP_DMA | GFP_KERNEL);
156         }
157     } else if (streamType == AUDIO_RENDER_STREAM) {
158         if (data->renderBufInfo.virtAddr == NULL) {
159             preallocBufSize = data->renderBufInfo.cirBufMax;
160             dmaDevice->coherent_dma_mask = 0xffffffffUL;
161             data->renderBufInfo.virtAddr = dma_alloc_wc(dmaDevice, preallocBufSize,
162                 (dma_addr_t *)&data->renderBufInfo.phyAddr, GFP_DMA | GFP_KERNEL);
163         }
164     } else {
165         AUDIO_DEVICE_LOG_ERR("stream Type is invalude.");
166         return HDF_FAILURE;
167     }
168 
169     AUDIO_DEVICE_LOG_DEBUG("success.");
170     return HDF_SUCCESS;
171 }
172 
Rk3568DmaBufFree(struct PlatformData * data,const enum AudioStreamType streamType)173 int32_t Rk3568DmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType)
174 {
175     struct device *dmaDevice = getDmaDevice();
176 
177     if (data == NULL) {
178         AUDIO_DEVICE_LOG_ERR("data is null");
179         return HDF_FAILURE;
180     }
181 
182     if (streamType == AUDIO_CAPTURE_STREAM) {
183         dma_free_wc(dmaDevice, data->captureBufInfo.cirBufMax, data->captureBufInfo.virtAddr,
184                     data->captureBufInfo.phyAddr);
185     } else if (streamType == AUDIO_RENDER_STREAM) {
186         dma_free_wc(dmaDevice, data->renderBufInfo.cirBufMax, data->renderBufInfo.virtAddr,
187                     data->renderBufInfo.phyAddr);
188     } else {
189         AUDIO_DEVICE_LOG_ERR("stream Type is invalude.");
190         return HDF_FAILURE;
191     }
192 
193     AUDIO_DEVICE_LOG_DEBUG("success");
194     return HDF_SUCCESS;
195 }
196 
Rk3568DmaRequestChannel(const struct PlatformData * data,const enum AudioStreamType streamType)197 int32_t  Rk3568DmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
198 {
199     (void)data;
200     AUDIO_DEVICE_LOG_DEBUG("sucess");
201     return HDF_SUCCESS;
202 }
203 
Rk3568DmaConfigChannel(const struct PlatformData * data,const enum AudioStreamType streamType)204 int32_t Rk3568DmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
205 {
206     struct dma_chan *dmaChan;
207     struct dma_slave_config slaveConfig;
208     int32_t ret = 0;
209 
210     (void)memset_s(&slaveConfig, sizeof(slaveConfig), 0, sizeof(slaveConfig));
211     if (streamType == AUDIO_RENDER_STREAM) {
212         dmaChan = (struct dma_chan *)g_dmaChn[DMA_TX_CHANNEL];   // tx
213         slaveConfig.direction = DMA_MEM_TO_DEV;
214         slaveConfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
215         slaveConfig.dst_addr = I2S1_ADDR + I2S_TXDR;
216         slaveConfig.dst_maxburst = 8; // Max Transimit 8 Byte
217     } else {
218         dmaChan = (struct dma_chan *)g_dmaChn[DMA_RX_CHANNEL];
219         slaveConfig.direction = DMA_DEV_TO_MEM;
220         slaveConfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
221         slaveConfig.src_addr = I2S1_ADDR + I2S_RXDR;
222         slaveConfig.src_maxburst = 8; // Max Transimit 8 Byte
223     }
224     slaveConfig.device_fc = 0;
225     slaveConfig.slave_id = 0;
226 
227     if (dmaChan == NULL) {
228         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
229         return HDF_FAILURE;
230     }
231     ret = dmaengine_slave_config(dmaChan, &slaveConfig);
232     if (ret != 0) {
233         AUDIO_DEVICE_LOG_ERR("dmaengine_slave_config failed");
234         return HDF_FAILURE;
235     }
236     AUDIO_DEVICE_LOG_DEBUG("success");
237     return HDF_SUCCESS;
238 }
239 
BytesToFrames(uint32_t frameBits,uint32_t size,uint32_t * pointer)240 static int32_t BytesToFrames(uint32_t frameBits, uint32_t size, uint32_t *pointer)
241 {
242     if (pointer == NULL || frameBits == 0) {
243         AUDIO_DEVICE_LOG_ERR("input para is error.");
244         return HDF_FAILURE;
245     }
246     *pointer = size / frameBits;
247     return HDF_SUCCESS;
248 }
249 
Rk3568PcmPointer(struct PlatformData * data,const enum AudioStreamType streamType,uint32_t * pointer)250 int32_t Rk3568PcmPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer)
251 {
252     uint32_t bufSize;
253     struct dma_chan *dmaChn;
254     struct dma_tx_state dmaState;
255     uint32_t currentPointer;
256     int ret;
257 
258     if (data == NULL) {
259         AUDIO_DEVICE_LOG_ERR("input para is null.");
260         return HDF_FAILURE;
261     }
262 
263     if (streamType == AUDIO_RENDER_STREAM) {
264         dmaChn = g_dmaChn[DMA_TX_CHANNEL];
265         bufSize = data->renderBufInfo.cirBufSize;
266         if (dmaChn == NULL) {
267             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
268             return HDF_FAILURE;
269         }
270         dmaengine_tx_status(dmaChn, g_cookie[DMA_TX_CHANNEL], &dmaState);
271 
272         if (dmaState.residue) {
273             currentPointer = bufSize - dmaState.residue;
274             ret = BytesToFrames(data->renderPcmInfo.frameSize, currentPointer, pointer);
275             if (ret != HDF_SUCCESS) {
276                 AUDIO_DEVICE_LOG_ERR("BytesToFrames is failed.");
277                 return HDF_FAILURE;
278             }
279         } else {
280             *pointer = 0;
281         }
282     } else {
283         dmaChn = g_dmaChn[DMA_RX_CHANNEL];
284         bufSize = data->captureBufInfo.cirBufSize;
285         if (dmaChn == NULL) {
286             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
287             return HDF_FAILURE;
288         }
289         dmaengine_tx_status(dmaChn, g_cookie[DMA_RX_CHANNEL], &dmaState);
290 
291         if (dmaState.residue) {
292             currentPointer = bufSize - dmaState.residue;
293             ret = BytesToFrames(data->capturePcmInfo.frameSize, currentPointer, pointer);
294             if (ret != HDF_SUCCESS) {
295                 AUDIO_DEVICE_LOG_ERR("BytesToFrames is failed.");
296                 return HDF_FAILURE;
297             }
298         } else {
299             *pointer = 0;
300         }
301     }
302 
303     return HDF_SUCCESS;
304 }
305 
Rk3568DmaPrep(const struct PlatformData * data,const enum AudioStreamType streamType)306 int32_t Rk3568DmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType)
307 {
308     (void)data;
309     return HDF_SUCCESS;
310 }
311 
DmaenginePcmDmaComplete(void * arg)312 static void DmaenginePcmDmaComplete(void *arg)
313 {
314     int ret;
315     struct AudioEvent reportMsg;
316     (void)arg;
317 
318     reportMsg.eventType = HDF_AUDIO_CAPTURE_THRESHOLD;
319     reportMsg.deviceType = HDF_AUDIO_PRIMARY_DEVICE;
320     ret = AudioCapSilenceThresholdEvent(g_device, &reportMsg);
321     if (ret != HDF_SUCCESS) {
322         AUDIO_DRIVER_LOG_ERR("AudioCapSilenceThresholdEvent failed.");
323     }
324     return ;
325 }
326 
Rk3568DmaSubmit(const struct PlatformData * data,const enum AudioStreamType streamType)327 int32_t Rk3568DmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType)
328 {
329     struct dma_async_tx_descriptor *desc;
330     enum dma_transfer_direction direction;
331     unsigned long flags = 3;
332     struct dma_chan *dmaChan = NULL;
333 
334     if (data == NULL) {
335         AUDIO_DEVICE_LOG_ERR("input para is null.");
336         return HDF_FAILURE;
337     }
338 
339     if (streamType == AUDIO_RENDER_STREAM) {
340         direction = DMA_MEM_TO_DEV;
341         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
342         if (dmaChan == NULL) {
343             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
344             return HDF_FAILURE;
345         }
346         desc = dmaengine_prep_dma_cyclic(dmaChan,
347             data->renderBufInfo.phyAddr,
348             data->renderBufInfo.cirBufSize,
349             data->renderBufInfo.periodSize, direction, flags);
350         if (!desc) {
351             AUDIO_DEVICE_LOG_ERR("DMA_TX_CHANNEL desc create failed");
352             return -ENOMEM;
353         }
354         g_cookie[DMA_TX_CHANNEL] = dmaengine_submit(desc);
355     } else {
356         direction = DMA_DEV_TO_MEM;
357         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
358         if (dmaChan == NULL) {
359             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
360             return HDF_FAILURE;
361         }
362 
363         desc = dmaengine_prep_dma_cyclic(dmaChan,
364             data->captureBufInfo.phyAddr,
365             data->captureBufInfo.cirBufSize,
366             data->captureBufInfo.periodSize, direction, flags);
367         if (!desc) {
368             AUDIO_DEVICE_LOG_ERR("DMA_RX_CHANNEL desc create failed");
369             return -ENOMEM;
370         }
371 #ifdef AUDIO_ENABLE_CAP_THRESHOLD
372         desc->callback = DmaenginePcmDmaComplete;
373         desc->callback_param = (void *)data;
374 #endif
375         g_cookie[DMA_RX_CHANNEL] = dmaengine_submit(desc);
376     }
377 
378     AUDIO_DEVICE_LOG_DEBUG("success");
379     return 0;
380 }
381 
Rk3568DmaPending(struct PlatformData * data,const enum AudioStreamType streamType)382 int32_t Rk3568DmaPending(struct PlatformData *data, const enum AudioStreamType streamType)
383 {
384     struct dma_chan *dmaChan = NULL;
385 
386     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
387     if (streamType == AUDIO_RENDER_STREAM) {
388         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
389     } else {
390         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
391     }
392     if (dmaChan == NULL) {
393         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
394         return HDF_FAILURE;
395     }
396 
397     dma_async_issue_pending(dmaChan);
398     AUDIO_DEVICE_LOG_DEBUG("dmaChan chan_id = %d.", dmaChan->chan_id);
399 
400     AUDIO_DEVICE_LOG_DEBUG("success");
401     return HDF_SUCCESS;
402 }
403 
Rk3568DmaPause(struct PlatformData * data,const enum AudioStreamType streamType)404 int32_t Rk3568DmaPause(struct PlatformData *data, const enum AudioStreamType streamType)
405 {
406     struct dma_chan *dmaChan;
407 
408     if (streamType == AUDIO_RENDER_STREAM) {
409         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
410     } else {
411         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
412     }
413     // can not use dmaengine_pause function
414     if (dmaChan == NULL) {
415         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
416         return HDF_FAILURE;
417     }
418     dmaengine_terminate_async(dmaChan);
419 
420     AUDIO_DEVICE_LOG_DEBUG("success");
421     return HDF_SUCCESS;
422 }
Rk3568DmaResume(const struct PlatformData * data,const enum AudioStreamType streamType)423 int32_t Rk3568DmaResume(const struct PlatformData *data, const enum AudioStreamType streamType)
424 {
425     int ret;
426     struct dma_chan *dmaChan;
427     if (data == NULL) {
428         AUDIO_DEVICE_LOG_ERR("data is null");
429         return HDF_FAILURE;
430     }
431 
432     if (streamType == AUDIO_RENDER_STREAM) {
433         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
434     } else {
435         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
436     }
437     if (dmaChan == NULL) {
438         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
439         return HDF_FAILURE;
440     }
441 
442     // use start Operation function
443     ret = Rk3568DmaSubmit(data, streamType);
444     if (ret != HDF_SUCCESS) {
445         AUDIO_DEVICE_LOG_ERR("call Rk3568DmaSubmit failed");
446         return HDF_FAILURE;
447     }
448     dma_async_issue_pending(dmaChan);
449 
450     AUDIO_DEVICE_LOG_DEBUG("success");
451     return HDF_SUCCESS;
452 }
453