• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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