1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <linux/interrupt.h>
20 #include "audio_platform_if.h"
21 #ifdef __LITEOS__
22 #include <los_vm_iomap.h>
23 #else
24 #include <linux/dma-mapping.h>
25 #endif
26 #include "audio_sapm.h"
27 #include "hi3516_aiao_impl.h"
28 #include "audio_stream_dispatch.h"
29 #include "audio_driver_log.h"
30 #include "osal_irq.h"
31 #include "osal_time.h"
32
33 #define HDF_LOG_TAG HDF_AUDIO_DRIVER
34 const int AUDIO_CACHE_ALIGN_SIZE = 64;
35 const int DMA_VIRTUAL_IRQ_NUM = 71;
36
37 #ifndef __LITEOS__
38 static struct device g_renderDev = {0};
39 static struct device g_captureDev = {0};
40 #endif
41
42 #ifdef AUDIO_ENABLE_CAP_THRESHOLD
DmacIsrCallBack(int irq,void * data)43 static uint32_t DmacIsrCallBack(int irq, void *data)
44 {
45 uint32_t chanlID = 0;
46 int ret;
47 struct HdfDeviceObject *device = NULL;
48 struct AudioEvent reportMsg;
49
50 AiaoRxIntClr(chanlID);
51
52 device = (struct HdfDeviceObject *)data;
53 if (device == NULL) {
54 AUDIO_DRIVER_LOG_ERR("device is null.");
55 return HDF_FAILURE;
56 }
57 reportMsg.eventType = HDF_AUDIO_CAPTURE_THRESHOLD;
58 reportMsg.deviceType = HDF_AUDIO_PRIMARY_DEVICE;
59 ret = AudioCapSilenceThresholdEvent(device, &reportMsg);
60 if (ret != HDF_SUCCESS) {
61 AUDIO_DRIVER_LOG_ERR("AudioCapSilenceThresholdEvent failed.");
62 return HDF_FAILURE;
63 }
64
65 return HDF_SUCCESS;
66 }
67 #endif
68
AudioDmaDeviceInit(const struct AudioCard * card,const struct PlatformDevice * platformDevice)69 int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platformDevice)
70 {
71 const unsigned int chnId = 0;
72 int ret;
73
74 if (card == NULL || card->device == NULL || platformDevice == NULL || platformDevice->devData == NULL) {
75 AUDIO_DRIVER_LOG_ERR("platformDevice is NULL.");
76 return HDF_FAILURE;
77 }
78
79 #ifdef AUDIO_ENABLE_CAP_THRESHOLD
80 if (!strcmp(card->configData.cardServiceName, "hdf_audio_codec_primary_dev0")) {
81 ret = OsalRegisterIrq(DMA_VIRTUAL_IRQ_NUM, IRQF_SHARED,
82 (OsalIRQHandle)DmacIsrCallBack, "AIO_interrupt", card->device);
83 if (ret < 0) {
84 AUDIO_DRIVER_LOG_ERR("OsalRegisterIrq: fail 0x%x", ret);
85 }
86 }
87 #endif
88
89 if (platformDevice->devData->platformInitFlag == true) {
90 AUDIO_DRIVER_LOG_DEBUG("platform init complete!");
91 return HDF_SUCCESS;
92 }
93
94 ret = AiaoHalSysInit();
95 if (ret != HDF_SUCCESS) {
96 AUDIO_DRIVER_LOG_ERR("AiaoHalSysInit: fail.");
97 return HDF_FAILURE;
98 }
99
100 /* PIN MUX */
101 ret = AiaoSysPinMux();
102 if (ret != HDF_SUCCESS) {
103 AUDIO_DRIVER_LOG_ERR("AiaoSysPinMux: fail.");
104 return HDF_FAILURE;
105 }
106
107 /* CLK reset */
108 ret = AiaoClockReset();
109 if (ret != HDF_SUCCESS) {
110 AUDIO_DRIVER_LOG_ERR("AiaoClockReset: fail");
111 return HDF_FAILURE;
112 }
113
114 /* aiao init */
115 ret = AiaoDeviceInit(chnId);
116 if (ret != HDF_SUCCESS) {
117 AUDIO_DRIVER_LOG_ERR("AiaoClockReset: fail");
118 return HDF_FAILURE;
119 }
120
121 platformDevice->devData->platformInitFlag = true;
122 return HDF_SUCCESS;
123 }
124
Hi3516DmaBufAlloc(struct PlatformData * data,const enum AudioStreamType streamType)125 int32_t Hi3516DmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType)
126 {
127 if (data == NULL) {
128 AUDIO_DRIVER_LOG_ERR("data is null");
129 return HDF_FAILURE;
130 }
131
132 if (streamType == AUDIO_CAPTURE_STREAM) {
133 #ifdef __LITEOS__
134 data->captureBufInfo.virtAddr = (uint32_t *)LOS_DmaMemAlloc(&data->captureBufInfo.phyAddr,
135 data->captureBufInfo.cirBufMax, AUDIO_CACHE_ALIGN_SIZE, DMA_NOCACHE);
136 #else
137 g_captureDev.coherent_dma_mask = 0xffffffffUL;
138 data->captureBufInfo.virtAddr = dma_alloc_wc(&g_captureDev, data->captureBufInfo.cirBufMax,
139 (dma_addr_t *)&data->captureBufInfo.phyAddr, GFP_DMA | GFP_KERNEL);
140 #endif
141 } else if (streamType == AUDIO_RENDER_STREAM) {
142 #ifdef __LITEOS__
143 data->renderBufInfo.virtAddr = (uint32_t *)LOS_DmaMemAlloc(&data->renderBufInfo.phyAddr,
144 data->renderBufInfo.cirBufMax,
145 AUDIO_CACHE_ALIGN_SIZE, DMA_NOCACHE);
146 #else
147 g_renderDev.coherent_dma_mask = 0xffffffffUL;
148 data->renderBufInfo.virtAddr = dma_alloc_wc(&g_renderDev, data->renderBufInfo.cirBufMax,
149 (dma_addr_t *)&data->renderBufInfo.phyAddr, GFP_DMA | GFP_KERNEL);
150 #endif
151 } else {
152 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
153 return HDF_FAILURE;
154 }
155 return HDF_SUCCESS;
156 }
157
Hi3516DmaBufFree(struct PlatformData * data,const enum AudioStreamType streamType)158 int32_t Hi3516DmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType)
159 {
160 if (data == NULL) {
161 AUDIO_DRIVER_LOG_ERR("data is null");
162 return HDF_FAILURE;
163 }
164
165 if (streamType == AUDIO_CAPTURE_STREAM) {
166 if (data->captureBufInfo.virtAddr != NULL) {
167 #ifdef __LITEOS__
168 LOS_DmaMemFree(data->captureBufInfo.virtAddr);
169 #else
170 dma_free_wc(&g_captureDev, data->captureBufInfo.cirBufMax, data->captureBufInfo.virtAddr,
171 data->captureBufInfo.phyAddr);
172 #endif
173 }
174 } else if (streamType == AUDIO_RENDER_STREAM) {
175 if (data->renderBufInfo.virtAddr != NULL) {
176 #ifdef __LITEOS__
177 LOS_DmaMemFree(data->renderBufInfo.virtAddr);
178 #else
179 dma_free_wc(&g_renderDev, data->renderBufInfo.cirBufMax, data->renderBufInfo.virtAddr,
180 data->renderBufInfo.phyAddr);
181 #endif
182 }
183 } else {
184 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
185 return HDF_FAILURE;
186 }
187 return HDF_SUCCESS;
188 }
189
Hi3516DmaRequestChannel(const struct PlatformData * data,const enum AudioStreamType streamType)190 int32_t Hi3516DmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
191 {
192 (void)data;
193 return HDF_SUCCESS;
194 }
195
Hi3516DmaConfigChannel(const struct PlatformData * data,const enum AudioStreamType streamType)196 int32_t Hi3516DmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
197 {
198 if (data == NULL) {
199 AUDIO_DRIVER_LOG_ERR("data is null");
200 return HDF_FAILURE;
201 }
202
203 if (streamType == AUDIO_CAPTURE_STREAM) {
204 if (AudioAiInit(data) != HDF_SUCCESS) {
205 AUDIO_DRIVER_LOG_ERR("AudioAiInit: fail.");
206 return HDF_FAILURE;
207 }
208 if (AipHalSetBuffWptr(0, 0) != HDF_SUCCESS) {
209 return HDF_FAILURE;
210 }
211 if (AipHalSetBuffRptr(0, 0) != HDF_SUCCESS) {
212 return HDF_FAILURE;
213 }
214 } else if (streamType == AUDIO_RENDER_STREAM) {
215 if (AudioAoInit(data) != HDF_SUCCESS) {
216 AUDIO_DRIVER_LOG_ERR("AudioAoInit: fail.");
217 return HDF_FAILURE;
218 }
219 if (AopHalSetBuffWptr(0, 0) != HDF_SUCCESS) {
220 return HDF_FAILURE;
221 }
222 if (AopHalSetBuffRptr(0, 0) != HDF_SUCCESS) {
223 return HDF_FAILURE;
224 }
225 } else {
226 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
227 return HDF_FAILURE;
228 }
229 return HDF_SUCCESS;
230 }
231
Hi3516DmaPrep(const struct PlatformData * data,const enum AudioStreamType streamType)232 int32_t Hi3516DmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType)
233 {
234 (void)data;
235 return HDF_SUCCESS;
236 }
237
Hi3516DmaSubmit(const struct PlatformData * data,const enum AudioStreamType streamType)238 int32_t Hi3516DmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType)
239 {
240 (void)data;
241 return HDF_SUCCESS;
242 }
243
Hi3516DmaPending(struct PlatformData * data,const enum AudioStreamType streamType)244 int32_t Hi3516DmaPending(struct PlatformData *data, const enum AudioStreamType streamType)
245 {
246 if (data == NULL) {
247 AUDIO_DRIVER_LOG_ERR("data is null");
248 return HDF_FAILURE;
249 }
250
251 if (streamType == AUDIO_CAPTURE_STREAM) {
252 OsalMutexLock(&data->captureBufInfo.buffMutex);
253 AipHalSetRxStart(data->captureBufInfo.chnId, HI_TRUE);
254 OsalMutexUnlock(&data->captureBufInfo.buffMutex);
255 } else if (streamType == AUDIO_RENDER_STREAM) {
256 AopHalDevEnable(data->renderBufInfo.chnId);
257 } else {
258 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
259 return HDF_FAILURE;
260 }
261 return HDF_SUCCESS;
262 }
263
Hi3516DmaPause(struct PlatformData * data,const enum AudioStreamType streamType)264 int32_t Hi3516DmaPause(struct PlatformData *data, const enum AudioStreamType streamType)
265 {
266 if (data == NULL) {
267 AUDIO_DRIVER_LOG_ERR("data is null");
268 return HDF_FAILURE;
269 }
270
271 if (streamType == AUDIO_CAPTURE_STREAM) {
272 OsalMutexLock(&data->captureBufInfo.buffMutex);
273 AipHalSetRxStart(data->captureBufInfo.chnId, HI_FALSE);
274 OsalMutexUnlock(&data->captureBufInfo.buffMutex);
275 } else if (streamType == AUDIO_RENDER_STREAM) {
276 OsalMutexLock(&data->renderBufInfo.buffMutex);
277 AopHalSetTxStart(data->renderBufInfo.chnId, HI_FALSE);
278 OsalMutexUnlock(&data->renderBufInfo.buffMutex);
279 } else {
280 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
281 return HDF_FAILURE;
282 }
283 return HDF_SUCCESS;
284 }
285
Hi3516DmaResume(const struct PlatformData * data,const enum AudioStreamType streamType)286 int32_t Hi3516DmaResume(const struct PlatformData *data, const enum AudioStreamType streamType)
287 {
288 if (data == NULL) {
289 AUDIO_DRIVER_LOG_ERR("data is null");
290 return HDF_FAILURE;
291 }
292
293 if (streamType == AUDIO_CAPTURE_STREAM) {
294 AipHalSetRxStart(data->captureBufInfo.chnId, HI_TRUE);
295 } else if (streamType == AUDIO_RENDER_STREAM) {
296 AopHalDevEnable(data->renderBufInfo.chnId);
297 } else {
298 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
299 return HDF_FAILURE;
300 }
301 return HDF_SUCCESS;
302 }
303
Hi3516DmaPointer(struct PlatformData * data,const enum AudioStreamType streamType,uint32_t * pointer)304 int32_t Hi3516DmaPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer)
305 {
306 int devId;
307 uint32_t bytesOfPointer;
308 uint32_t frameSize;
309 uint32_t wPtr;
310 uint32_t rPtr;
311
312 if (data == NULL || pointer == NULL) {
313 AUDIO_DRIVER_LOG_ERR("data is null");
314 return HDF_FAILURE;
315 }
316
317 if (streamType == AUDIO_RENDER_STREAM) {
318 OsalMutexLock(&data->renderBufInfo.buffMutex);
319 devId = data->renderBufInfo.chnId;
320 frameSize = data->renderPcmInfo.frameSize;
321 bytesOfPointer = AiaoHalReadReg(AiopRegCfg(AOP_BUFF_RPTR_REG, OFFSET_MULTL, devId));
322 *pointer = AudioBytesToFrames(bytesOfPointer, frameSize);
323 wPtr = data->renderBufInfo.wptrOffSet;
324 OsalMutexUnlock(&data->renderBufInfo.buffMutex);
325 if (AopHalSetBuffWptr(devId, wPtr) != HDF_SUCCESS) {
326 AUDIO_DRIVER_LOG_ERR("AopHalSetBuffWptr failed.");
327 return HDF_FAILURE;
328 }
329 } else if (streamType == AUDIO_CAPTURE_STREAM) {
330 OsalMutexLock(&data->captureBufInfo.buffMutex);
331 devId = data->captureBufInfo.chnId;
332 frameSize = data->capturePcmInfo.frameSize;
333 bytesOfPointer = AiaoHalReadReg(AiopRegCfg(AIP_BUFF_WPTR_REG, OFFSET_MULTL, devId));
334 *pointer = AudioBytesToFrames(bytesOfPointer, frameSize);
335 rPtr = data->captureBufInfo.rptrOffSet;
336 OsalMutexUnlock(&data->captureBufInfo.buffMutex);
337 if (AipHalSetBuffRptr(devId, rPtr) != HDF_SUCCESS) {
338 AUDIO_DRIVER_LOG_ERR("AipHalSetBuffRptr failed.");
339 return HDF_FAILURE;
340 }
341 } else {
342 AUDIO_DRIVER_LOG_ERR("stream Type is fail.");
343 return HDF_FAILURE;
344 }
345 return HDF_SUCCESS;
346 }
347