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