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