• 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 DmaRuntimeData {
44     struct dma_chan *dmaChn[DMA_CHANNEL_MAX];
45     dma_cookie_t cookie[DMA_CHANNEL_MAX];
46     uint32_t streamType;
47 };
48 static const char *g_i2s1DtsTreePath = "/i2s@fe410000";
49 static struct dma_chan *g_dmaChn[DMA_CHANNEL_MAX];
50 static dma_cookie_t g_cookie[DMA_CHANNEL_MAX];
51 static struct device *g_dmaDev;
getDmaDevice(void)52 struct device *getDmaDevice(void)
53 {
54     struct device_node    *dmaOfNode;
55     struct platform_device *platformdev;
56     dmaOfNode = of_find_node_by_path(g_i2s1DtsTreePath);
57     if (dmaOfNode == NULL) {
58         AUDIO_DEVICE_LOG_ERR("get device node failed.");
59     }
60     platformdev = of_find_device_by_node(dmaOfNode);
61     g_dmaDev = &platformdev->dev;
62     return g_dmaDev;
63 }
64 
AudioDmaDeviceInit(const struct AudioCard * card,const struct PlatformDevice * platform)65 int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform)
66 {
67     struct PlatformData *data = NULL;
68     static const char * const dmaChannelNames[] = {
69         [DMA_RX_CHANNEL] = "rx",
70         [DMA_TX_CHANNEL] = "tx",
71     };
72     uint32_t i = 0;
73     struct device *dmaDevice = getDmaDevice();
74 
75     data = PlatformDataFromCard(card);
76     if (data == NULL) {
77         AUDIO_DEVICE_LOG_ERR("PlatformDataFromCard failed.");
78         return HDF_FAILURE;
79     }
80     if (data->platformInitFlag == true) {
81         AUDIO_DRIVER_LOG_DEBUG("platform init complete!");
82         return HDF_SUCCESS;
83     }
84     data->platformInitFlag = true;
85     for (i = 0; i <= 1; i++) {
86         g_dmaChn[i] = dma_request_slave_channel(dmaDevice,
87             dmaChannelNames[i]);
88         if (g_dmaChn[i] == NULL) {
89             AUDIO_DEVICE_LOG_ERR("dma_request_slave_channel streamType=%d failed", i);
90             return HDF_FAILURE;
91         }
92     }
93     AUDIO_DEVICE_LOG_DEBUG("success.");
94     return HDF_SUCCESS;
95 }
96 
97 
DmaRtdMemAlloc(struct PlatformData * data,enum AudioStreamType streamType)98 static int32_t DmaRtdMemAlloc(struct PlatformData *data, enum AudioStreamType streamType)
99 {
100     struct DmaRuntimeData *dmaRtd = NULL;
101 
102     if (data == NULL) {
103         AUDIO_DEVICE_LOG_ERR("data is null.");
104         return HDF_FAILURE;
105     }
106 
107     dmaRtd = kzalloc(sizeof(*dmaRtd), GFP_KERNEL);
108     if (!dmaRtd) {
109         AUDIO_DEVICE_LOG_ERR("AudioRenderBuffInit: fail.");
110         return HDF_FAILURE;
111     }
112     data->dmaPrv = dmaRtd;
113     dmaRtd->streamType = streamType;
114     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
115     dmaRtd->dmaChn[streamType] = g_dmaChn[streamType];
116     AUDIO_DEVICE_LOG_DEBUG("success.");
117     return HDF_SUCCESS;
118 }
119 
Rk3568DmaBufAlloc(struct PlatformData * data,const enum AudioStreamType streamType)120 int32_t Rk3568DmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType)
121 {
122     int ret;
123     uint32_t preallocBufSize;
124     struct device *dmaDevice = getDmaDevice();
125     AUDIO_DEVICE_LOG_DEBUG("entry");
126 
127     if (data == NULL) {
128         AUDIO_DEVICE_LOG_ERR("data is null");
129         return HDF_FAILURE;
130     }
131     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
132 
133     if (streamType == AUDIO_CAPTURE_STREAM) {
134         if (data->captureBufInfo.virtAddr == NULL) {
135             preallocBufSize = data->captureBufInfo.cirBufMax;
136             dmaDevice->coherent_dma_mask = 0xffffffffUL;
137             AUDIO_DEVICE_LOG_DEBUG("AUDIO_CAPTURE_STREAM");
138             data->captureBufInfo.virtAddr = dma_alloc_wc(dmaDevice, preallocBufSize,
139                 (dma_addr_t *)&data->captureBufInfo.phyAddr, GFP_DMA | GFP_KERNEL);
140         }
141     } else if (streamType == AUDIO_RENDER_STREAM) {
142         if (data->renderBufInfo.virtAddr == NULL) {
143             preallocBufSize = data->renderBufInfo.cirBufMax;
144             dmaDevice->coherent_dma_mask = 0xffffffffUL;
145             AUDIO_DEVICE_LOG_DEBUG("AUDIO_RENDER_STREAM");
146             data->renderBufInfo.virtAddr = dma_alloc_wc(dmaDevice, preallocBufSize,
147                 (dma_addr_t *)&data->renderBufInfo.phyAddr, GFP_DMA | GFP_KERNEL);
148         }
149     } else {
150         AUDIO_DEVICE_LOG_ERR("stream Type is invalude.");
151         return HDF_FAILURE;
152     }
153     ret = DmaRtdMemAlloc(data, streamType);
154     if (ret != HDF_SUCCESS) {
155         AUDIO_DEVICE_LOG_ERR("DmaRtdMemAlloc fail.");
156         return HDF_FAILURE;
157     }
158     AUDIO_DEVICE_LOG_DEBUG("success.");
159 
160     return HDF_SUCCESS;
161 }
162 
Rk3568DmaBufFree(struct PlatformData * data,const enum AudioStreamType streamType)163 int32_t Rk3568DmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType)
164 {
165     struct DmaRuntimeData *dmaRtd = (struct DmaRuntimeData *)data->dmaPrv;
166     struct device *dmaDevice = getDmaDevice();
167 
168     if (data == NULL) {
169         AUDIO_DEVICE_LOG_ERR("data is null");
170         return HDF_FAILURE;
171     }
172     if (dmaRtd == NULL) {
173         AUDIO_DRIVER_LOG_INFO("dmaPrv is null.");
174         return HDF_SUCCESS;
175     }
176     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
177     kfree(dmaRtd);
178     if (streamType == AUDIO_CAPTURE_STREAM) {
179         AUDIO_DEVICE_LOG_DEBUG("AUDIO_CAPTURE_STREAM");
180         dma_free_wc(dmaDevice, data->captureBufInfo.cirBufMax, data->captureBufInfo.virtAddr,
181                     data->captureBufInfo.phyAddr);
182     } else if (streamType == AUDIO_RENDER_STREAM) {
183         AUDIO_DEVICE_LOG_DEBUG("AUDIO_RENDER_STREAM");
184         dma_free_wc(dmaDevice, data->renderBufInfo.cirBufMax, data->renderBufInfo.virtAddr,
185                     data->renderBufInfo.phyAddr);
186     } else {
187         AUDIO_DEVICE_LOG_ERR("stream Type is invalude.");
188         return HDF_FAILURE;
189     }
190 
191     AUDIO_DEVICE_LOG_DEBUG("success");
192     return HDF_SUCCESS;
193 }
194 
Rk3568DmaRequestChannel(const struct PlatformData * data,const enum AudioStreamType streamType)195 int32_t  Rk3568DmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
196 {
197     (void)data;
198     AUDIO_DEVICE_LOG_DEBUG("sucess");
199     return HDF_SUCCESS;
200 }
201 
Rk3568DmaConfigChannel(const struct PlatformData * data,const enum AudioStreamType streamType)202 int32_t Rk3568DmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
203 {
204     struct dma_chan *dmaChan;
205     struct dma_slave_config slaveConfig;
206     int32_t ret = 0;
207 
208     (void)memset_s(&slaveConfig, sizeof(slaveConfig), 0, sizeof(slaveConfig));
209     if (streamType == AUDIO_RENDER_STREAM) {
210         dmaChan = (struct dma_chan *)g_dmaChn[DMA_TX_CHANNEL];   // tx
211         slaveConfig.direction = DMA_MEM_TO_DEV;
212         slaveConfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
213         slaveConfig.dst_addr = I2S1_ADDR + I2S_TXDR;
214         slaveConfig.dst_maxburst = 8; // Max Transimit 8 Byte
215     } else {
216         dmaChan = (struct dma_chan *)g_dmaChn[DMA_RX_CHANNEL];
217         slaveConfig.direction = DMA_DEV_TO_MEM;
218         slaveConfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
219         slaveConfig.src_addr = I2S1_ADDR + I2S_RXDR;
220         slaveConfig.src_maxburst = 8; // Max Transimit 8 Byte
221     }
222     slaveConfig.device_fc = 0;
223     slaveConfig.slave_id = 0;
224 
225     ret = dmaengine_slave_config(dmaChan, &slaveConfig);
226     if (ret != 0) {
227         AUDIO_DEVICE_LOG_ERR("dmaengine_slave_config failed");
228         return HDF_FAILURE;
229     }
230     AUDIO_DEVICE_LOG_DEBUG("success");
231     return HDF_SUCCESS;
232 }
233 
BytesToFrames(uint32_t frameBits,uint32_t size)234 static inline signed long BytesToFrames(uint32_t frameBits, uint32_t size)
235 {
236     if (frameBits == 0 || size == 0) {
237         AUDIO_DEVICE_LOG_ERR("input error.");
238     }
239     return size / frameBits;
240 }
241 
Rk3568PcmPointer(struct PlatformData * data,const enum AudioStreamType streamType,uint32_t * pointer)242 int32_t Rk3568PcmPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer)
243 {
244     uint32_t bufSize;
245     struct dma_chan *dmaChn;
246     struct dma_tx_state dmaState;
247     uint32_t currentPointer;
248     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
249     if (streamType == AUDIO_RENDER_STREAM) {
250         dmaChn = g_dmaChn[DMA_TX_CHANNEL];
251         bufSize = data->renderBufInfo.cirBufSize;
252         dmaengine_tx_status(dmaChn, g_cookie[DMA_TX_CHANNEL], &dmaState);
253         if (dmaState.residue) {
254             currentPointer = bufSize - dmaState.residue;
255             *pointer = BytesToFrames(data->renderPcmInfo.frameSize, currentPointer);
256         } else {
257             *pointer = 0;
258         }
259     } else {
260         dmaChn = g_dmaChn[DMA_RX_CHANNEL];
261         bufSize = data->captureBufInfo.cirBufSize;
262         dmaengine_tx_status(dmaChn, g_cookie[DMA_RX_CHANNEL], &dmaState);
263         if (dmaState.residue) {
264             currentPointer = bufSize - dmaState.residue;
265             *pointer = BytesToFrames(data->capturePcmInfo.frameSize, currentPointer);
266         } else {
267             *pointer = 0;
268         }
269     }
270 
271     AUDIO_DEVICE_LOG_DEBUG("success");
272     return HDF_SUCCESS;
273 }
274 
Rk3568DmaPrep(const struct PlatformData * data,const enum AudioStreamType streamType)275 int32_t Rk3568DmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType)
276 {
277     (void)data;
278     return HDF_SUCCESS;
279 }
280 
Rk3568DmaSubmit(const struct PlatformData * data,const enum AudioStreamType streamType)281 int32_t Rk3568DmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType)
282 {
283     struct dma_async_tx_descriptor *desc;
284     enum dma_transfer_direction direction;
285     unsigned long flags = 3;
286     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
287     if (streamType == AUDIO_RENDER_STREAM) {
288         direction = DMA_MEM_TO_DEV;
289         desc = dmaengine_prep_dma_cyclic(g_dmaChn[DMA_TX_CHANNEL],
290             data->renderBufInfo.phyAddr,
291             data->renderBufInfo.cirBufSize,
292             data->renderBufInfo.periodSize, direction, flags);
293         if (!desc) {
294             AUDIO_DEVICE_LOG_ERR("DMA_TX_CHANNEL desc create failed");
295             return -ENOMEM;
296         }
297         g_cookie[DMA_TX_CHANNEL] = dmaengine_submit(desc);
298     } else {
299         direction = DMA_DEV_TO_MEM;
300         desc = dmaengine_prep_dma_cyclic(g_dmaChn[DMA_RX_CHANNEL],
301             data->captureBufInfo.phyAddr,
302             data->captureBufInfo.cirBufSize,
303             data->captureBufInfo.periodSize, direction, flags);
304         if (!desc) {
305             AUDIO_DEVICE_LOG_ERR("DMA_RX_CHANNEL desc create failed");
306             return -ENOMEM;
307         }
308         g_cookie[DMA_RX_CHANNEL] = dmaengine_submit(desc);
309     }
310 
311     AUDIO_DEVICE_LOG_ERR("success");
312     return 0;
313 }
314 
Rk3568DmaPending(struct PlatformData * data,const enum AudioStreamType streamType)315 int32_t Rk3568DmaPending(struct PlatformData *data, const enum AudioStreamType streamType)
316 {
317     struct dma_chan *dmaChan;
318     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
319     if (streamType == AUDIO_RENDER_STREAM) {
320         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
321     } else {
322         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
323     }
324     dma_async_issue_pending(dmaChan);
325     AUDIO_DRIVER_LOG_INFO("dmaChan chan_id = %d.", dmaChan->chan_id);
326 
327     AUDIO_DEVICE_LOG_DEBUG("success");
328     return HDF_SUCCESS;
329 }
330 
Rk3568DmaPause(struct PlatformData * data,const enum AudioStreamType streamType)331 int32_t Rk3568DmaPause(struct PlatformData *data, const enum AudioStreamType streamType)
332 {
333     struct dma_chan *dmaChan;
334     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
335     if (streamType == AUDIO_RENDER_STREAM) {
336         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
337     } else {
338         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
339     }
340     // can not use dmaengine_pause function
341     dmaengine_terminate_async(dmaChan);
342 
343     AUDIO_DEVICE_LOG_ERR("success");
344     return HDF_SUCCESS;
345 }
Rk3568DmaResume(const struct PlatformData * data,const enum AudioStreamType streamType)346 int32_t Rk3568DmaResume(const struct PlatformData *data, const enum AudioStreamType streamType)
347 {
348     int ret;
349     struct dma_chan *dmaChan;
350     if (data == NULL) {
351         AUDIO_DEVICE_LOG_ERR("data is null");
352         return HDF_FAILURE;
353     }
354 
355     AUDIO_DEVICE_LOG_DEBUG("streamType = %d", streamType);
356     if (streamType == AUDIO_RENDER_STREAM) {
357         dmaChan = g_dmaChn[DMA_TX_CHANNEL];
358     } else {
359         dmaChan = g_dmaChn[DMA_RX_CHANNEL];
360     }
361 
362     // use start Operation function
363     ret = Rk3568DmaSubmit(data, streamType);
364     if (ret != HDF_SUCCESS) {
365         AUDIO_DEVICE_LOG_ERR("call Rk3568DmaSubmit failed");
366         return HDF_FAILURE;
367     }
368     dma_async_issue_pending(dmaChan);
369 
370     AUDIO_DEVICE_LOG_DEBUG("success");
371     return HDF_SUCCESS;
372 }
373