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