• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
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,
75                            const struct PlatformDevice *platform)
76 {
77     struct PlatformData *data = NULL;
78     static const char *const dmaChannelNames[] = {
79         [DMA_RX_CHANNEL] = "rx",
80         [DMA_TX_CHANNEL] = "tx",
81     };
82     uint32_t i = 0;
83     struct device *dmaDevice = getDmaDevice();
84 
85     if (card == NULL) {
86         AUDIO_DEVICE_LOG_ERR("card is null.");
87         return HDF_FAILURE;
88     }
89     g_device = card->device;
90 
91     data = PlatformDataFromCard(card);
92     if (data == NULL) {
93         AUDIO_DEVICE_LOG_ERR("PlatformDataFromCard failed.");
94         return HDF_FAILURE;
95     }
96     if (data->platformInitFlag == true) {
97         AUDIO_DRIVER_LOG_DEBUG("platform init complete!");
98         return HDF_SUCCESS;
99     }
100     data->platformInitFlag = true;
101     for (i = 0; i <= 1; i++) {
102         g_dmaChn[i] = dma_request_slave_channel(dmaDevice, dmaChannelNames[i]);
103         if (g_dmaChn[i] == NULL) {
104             AUDIO_DEVICE_LOG_ERR(
105                 "dma_request_slave_channel streamType=%d failed", i);
106             return HDF_FAILURE;
107         }
108     }
109     AUDIO_DEVICE_LOG_DEBUG("success.");
110     return HDF_SUCCESS;
111 }
112 
DmaRtdMemAlloc(struct PlatformData * data,enum AudioStreamType streamType)113 static int32_t DmaRtdMemAlloc(struct PlatformData *data,
114                               enum AudioStreamType streamType)
115 {
116     struct DmaRuntimeData *dmaRtd = NULL;
117 
118     if (data == NULL) {
119         AUDIO_DEVICE_LOG_ERR("data is null.");
120         return HDF_FAILURE;
121     }
122 
123     dmaRtd = kzalloc(sizeof(*dmaRtd), GFP_KERNEL);
124     if (!dmaRtd) {
125         AUDIO_DEVICE_LOG_ERR("AudioRenderBuffInit: fail.");
126         return HDF_FAILURE;
127     }
128     data->dmaPrv = dmaRtd;
129     dmaRtd->streamType = streamType;
130     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
131     dmaRtd->dmaChn[streamType] = g_dmaChn[streamType];
132     AUDIO_DEVICE_LOG_DEBUG("success.");
133     return HDF_SUCCESS;
134 }
135 
Rk3568DmaBufAlloc(struct PlatformData * data,const enum AudioStreamType streamType)136 int32_t Rk3568DmaBufAlloc(struct PlatformData *data,
137                           const enum AudioStreamType streamType)
138 {
139     uint32_t preallocBufSize;
140     struct device *dmaDevice = getDmaDevice();
141 
142     if (data == NULL) {
143         AUDIO_DEVICE_LOG_ERR("data is null");
144         return HDF_FAILURE;
145     }
146 
147     if (dmaDevice == NULL) {
148         AUDIO_DEVICE_LOG_ERR("dmaDevice is null");
149         return HDF_FAILURE;
150     }
151 
152     if (streamType == AUDIO_CAPTURE_STREAM) {
153         if (data->captureBufInfo.virtAddr == NULL) {
154             preallocBufSize = data->captureBufInfo.cirBufMax;
155             dmaDevice->coherent_dma_mask = 0xffffffffUL;
156             data->captureBufInfo.virtAddr =
157                 dma_alloc_wc(dmaDevice, preallocBufSize,
158                              (dma_addr_t *)&data->captureBufInfo.phyAddr,
159                              GFP_DMA | GFP_KERNEL);
160         }
161     } else if (streamType == AUDIO_RENDER_STREAM) {
162         if (data->renderBufInfo.virtAddr == NULL) {
163             preallocBufSize = data->renderBufInfo.cirBufMax;
164             dmaDevice->coherent_dma_mask = 0xffffffffUL;
165             data->renderBufInfo.virtAddr =
166                 dma_alloc_wc(dmaDevice, preallocBufSize,
167                              (dma_addr_t *)&data->renderBufInfo.phyAddr,
168                              GFP_DMA | GFP_KERNEL);
169         }
170     } else {
171         AUDIO_DEVICE_LOG_ERR("stream Type is invalude.");
172         return HDF_FAILURE;
173     }
174 
175     AUDIO_DEVICE_LOG_DEBUG("success.");
176     return HDF_SUCCESS;
177 }
178 
Rk3568DmaBufFree(struct PlatformData * data,const enum AudioStreamType streamType)179 int32_t Rk3568DmaBufFree(struct PlatformData *data,
180                          const enum AudioStreamType streamType)
181 {
182     struct device *dmaDevice = getDmaDevice();
183 
184     if (data == NULL) {
185         AUDIO_DEVICE_LOG_ERR("data is null");
186         return HDF_FAILURE;
187     }
188 
189     if (streamType == AUDIO_CAPTURE_STREAM) {
190         dma_free_wc(dmaDevice, data->captureBufInfo.cirBufMax,
191                     data->captureBufInfo.virtAddr,
192                     data->captureBufInfo.phyAddr);
193     } else if (streamType == AUDIO_RENDER_STREAM) {
194         dma_free_wc(dmaDevice, data->renderBufInfo.cirBufMax,
195                     data->renderBufInfo.virtAddr, data->renderBufInfo.phyAddr);
196     } else {
197         AUDIO_DEVICE_LOG_ERR("stream Type is invalude.");
198         return HDF_FAILURE;
199     }
200 
201     AUDIO_DEVICE_LOG_DEBUG("success");
202     return HDF_SUCCESS;
203 }
204 
Rk3568DmaRequestChannel(const struct PlatformData * data,const enum AudioStreamType streamType)205 int32_t Rk3568DmaRequestChannel(const struct PlatformData *data,
206                                 const enum AudioStreamType streamType)
207 {
208     (void)data;
209     AUDIO_DEVICE_LOG_DEBUG("sucess");
210     return HDF_SUCCESS;
211 }
212 
Rk3568DmaConfigChannel(const struct PlatformData * data,const enum AudioStreamType streamType)213 int32_t Rk3568DmaConfigChannel(const struct PlatformData *data,
214                                const enum AudioStreamType streamType)
215 {
216     struct dma_chan *dmaChan;
217     struct dma_slave_config slaveConfig;
218     int32_t ret = 0;
219 
220     (void)memset_s(&slaveConfig, sizeof(slaveConfig), 0, sizeof(slaveConfig));
221     if (streamType == AUDIO_RENDER_STREAM) {
222         dmaChan = (struct dma_chan *)g_dmaChn[DMA_TX_CHANNEL]; // tx
223         slaveConfig.direction = DMA_MEM_TO_DEV;
224         slaveConfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
225         slaveConfig.dst_addr = I2S1_ADDR + I2S_TXDR;
226         slaveConfig.dst_maxburst = 8; // Max Transimit 8 Byte
227     } else {
228         dmaChan = (struct dma_chan *)g_dmaChn[DMA_RX_CHANNEL];
229         slaveConfig.direction = DMA_DEV_TO_MEM;
230         slaveConfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
231         slaveConfig.src_addr = I2S1_ADDR + I2S_RXDR;
232         slaveConfig.src_maxburst = 8; // Max Transimit 8 Byte
233     }
234     slaveConfig.device_fc = 0;
235     slaveConfig.slave_id = 0;
236 
237     if (dmaChan == NULL) {
238         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
239         return HDF_FAILURE;
240     }
241     ret = dmaengine_slave_config(dmaChan, &slaveConfig);
242     if (ret != 0) {
243         AUDIO_DEVICE_LOG_ERR("dmaengine_slave_config failed");
244         return HDF_FAILURE;
245     }
246     AUDIO_DEVICE_LOG_DEBUG("success");
247     return HDF_SUCCESS;
248 }
249 
BytesToFrames(uint32_t frameBits,uint32_t size,uint32_t * pointer)250 static int32_t BytesToFrames(uint32_t frameBits, uint32_t size,
251                              uint32_t *pointer)
252 {
253     if (pointer == NULL || frameBits == 0) {
254         AUDIO_DEVICE_LOG_ERR("input para is error.");
255         return HDF_FAILURE;
256     }
257     *pointer = size / frameBits;
258     return HDF_SUCCESS;
259 }
260 
Rk3568PcmPointer(struct PlatformData * data,const enum AudioStreamType streamType,uint32_t * pointer)261 int32_t Rk3568PcmPointer(struct PlatformData *data,
262                          const enum AudioStreamType streamType,
263                          uint32_t *pointer)
264 {
265     uint32_t bufSize;
266     struct dma_chan *dmaChn;
267     struct dma_tx_state dmaState;
268     uint32_t currentPointer;
269     int ret;
270 
271     if (data == NULL) {
272         AUDIO_DEVICE_LOG_ERR("input para is null.");
273         return HDF_FAILURE;
274     }
275 
276     if (streamType == AUDIO_RENDER_STREAM) {
277         dmaChn = g_dmaChn[DMA_TX_CHANNEL];
278         bufSize = data->renderBufInfo.cirBufSize;
279         if (dmaChn == NULL) {
280             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
281             return HDF_FAILURE;
282         }
283         dmaengine_tx_status(dmaChn, g_cookie[DMA_TX_CHANNEL], &dmaState);
284 
285         if (dmaState.residue) {
286             currentPointer = bufSize - dmaState.residue;
287             ret = BytesToFrames(data->renderPcmInfo.frameSize, currentPointer,
288                                 pointer);
289             if (ret != HDF_SUCCESS) {
290                 AUDIO_DEVICE_LOG_ERR("BytesToFrames is failed.");
291                 return HDF_FAILURE;
292             }
293         } else {
294             *pointer = 0;
295         }
296     } else {
297         dmaChn = g_dmaChn[DMA_RX_CHANNEL];
298         bufSize = data->captureBufInfo.cirBufSize;
299         if (dmaChn == NULL) {
300             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
301             return HDF_FAILURE;
302         }
303         dmaengine_tx_status(dmaChn, g_cookie[DMA_RX_CHANNEL], &dmaState);
304 
305         if (dmaState.residue) {
306             currentPointer = bufSize - dmaState.residue;
307             ret = BytesToFrames(data->capturePcmInfo.frameSize, currentPointer,
308                                 pointer);
309             if (ret != HDF_SUCCESS) {
310                 AUDIO_DEVICE_LOG_ERR("BytesToFrames is failed.");
311                 return HDF_FAILURE;
312             }
313         } else {
314             *pointer = 0;
315         }
316     }
317 
318     return HDF_SUCCESS;
319 }
320 
Rk3568DmaPrep(const struct PlatformData * data,const enum AudioStreamType streamType)321 int32_t Rk3568DmaPrep(const struct PlatformData *data,
322                       const enum AudioStreamType streamType)
323 {
324     (void)data;
325     return HDF_SUCCESS;
326 }
327 
DmaenginePcmDmaComplete(void * arg)328 static void DmaenginePcmDmaComplete(void *arg)
329 {
330     int ret;
331     struct AudioEvent reportMsg;
332     (void)arg;
333 
334     reportMsg.eventType = HDF_AUDIO_CAPTURE_THRESHOLD;
335     reportMsg.deviceType = HDF_AUDIO_PRIMARY_DEVICE;
336     ret = AudioCapSilenceThresholdEvent(g_device, &reportMsg);
337     if (ret != HDF_SUCCESS) {
338         AUDIO_DRIVER_LOG_ERR("AudioCapSilenceThresholdEvent failed.");
339     }
340     return;
341 }
342 
Rk3568DmaSubmit(const struct PlatformData * data,const enum AudioStreamType streamType)343 int32_t Rk3568DmaSubmit(const struct PlatformData *data,
344                         const enum AudioStreamType streamType)
345 {
346     struct dma_async_tx_descriptor *desc;
347     enum dma_transfer_direction direction;
348     unsigned long flags = 3;
349     struct dma_chan *dmaChan = NULL;
350 
351     if (data == NULL) {
352         AUDIO_DEVICE_LOG_ERR("input para is null.");
353         return HDF_FAILURE;
354     }
355 
356     if (streamType == AUDIO_RENDER_STREAM) {
357         direction = DMA_MEM_TO_DEV;
358         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
359         if (dmaChan == NULL) {
360             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
361             return HDF_FAILURE;
362         }
363         desc = dmaengine_prep_dma_cyclic(dmaChan, data->renderBufInfo.phyAddr,
364                                          data->renderBufInfo.cirBufSize,
365                                          data->renderBufInfo.periodSize,
366                                          direction, flags);
367         if (!desc) {
368             AUDIO_DEVICE_LOG_ERR("DMA_TX_CHANNEL desc create failed");
369             return -ENOMEM;
370         }
371         g_cookie[DMA_TX_CHANNEL] = dmaengine_submit(desc);
372     } else {
373         direction = DMA_DEV_TO_MEM;
374         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
375         if (dmaChan == NULL) {
376             AUDIO_DEVICE_LOG_ERR("dmaChan is null");
377             return HDF_FAILURE;
378         }
379 
380         desc = dmaengine_prep_dma_cyclic(dmaChan, data->captureBufInfo.phyAddr,
381                                          data->captureBufInfo.cirBufSize,
382                                          data->captureBufInfo.periodSize,
383                                          direction, flags);
384         if (!desc) {
385             AUDIO_DEVICE_LOG_ERR("DMA_RX_CHANNEL desc create failed");
386             return -ENOMEM;
387         }
388 #ifdef AUDIO_ENABLE_CAP_THRESHOLD
389         desc->callback = DmaenginePcmDmaComplete;
390         desc->callback_param = (void *)data;
391 #endif
392         g_cookie[DMA_RX_CHANNEL] = dmaengine_submit(desc);
393     }
394 
395     AUDIO_DEVICE_LOG_DEBUG("success");
396     return 0;
397 }
398 
Rk3568DmaPending(struct PlatformData * data,const enum AudioStreamType streamType)399 int32_t Rk3568DmaPending(struct PlatformData *data,
400                          const enum AudioStreamType streamType)
401 {
402     struct dma_chan *dmaChan = NULL;
403 
404     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
405     if (streamType == AUDIO_RENDER_STREAM) {
406         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
407     } else {
408         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
409     }
410     if (dmaChan == NULL) {
411         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
412         return HDF_FAILURE;
413     }
414 
415     dma_async_issue_pending(dmaChan);
416     AUDIO_DEVICE_LOG_DEBUG("dmaChan chan_id = %d.", dmaChan->chan_id);
417 
418     AUDIO_DEVICE_LOG_DEBUG("success");
419     return HDF_SUCCESS;
420 }
421 
Rk3568DmaPause(struct PlatformData * data,const enum AudioStreamType streamType)422 int32_t Rk3568DmaPause(struct PlatformData *data,
423                        const enum AudioStreamType streamType)
424 {
425     struct dma_chan *dmaChan;
426 
427     if (streamType == AUDIO_RENDER_STREAM) {
428         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
429     } else {
430         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
431     }
432     // can not use dmaengine_pause function
433     if (dmaChan == NULL) {
434         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
435         return HDF_FAILURE;
436     }
437     dmaengine_terminate_async(dmaChan);
438 
439     AUDIO_DEVICE_LOG_DEBUG("success");
440     return HDF_SUCCESS;
441 }
Rk3568DmaResume(const struct PlatformData * data,const enum AudioStreamType streamType)442 int32_t Rk3568DmaResume(const struct PlatformData *data,
443                         const enum AudioStreamType streamType)
444 {
445     int ret;
446     struct dma_chan *dmaChan;
447     if (data == NULL) {
448         AUDIO_DEVICE_LOG_ERR("data is null");
449         return HDF_FAILURE;
450     }
451 
452     if (streamType == AUDIO_RENDER_STREAM) {
453         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
454     } else {
455         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
456     }
457     if (dmaChan == NULL) {
458         AUDIO_DEVICE_LOG_ERR("dmaChan is null");
459         return HDF_FAILURE;
460     }
461 
462     // use start Operation function
463     ret = Rk3568DmaSubmit(data, streamType);
464     if (ret != HDF_SUCCESS) {
465         AUDIO_DEVICE_LOG_ERR("call Rk3568DmaSubmit failed");
466         return HDF_FAILURE;
467     }
468     dma_async_issue_pending(dmaChan);
469 
470     AUDIO_DEVICE_LOG_DEBUG("success");
471     return HDF_SUCCESS;
472 }
473