1 /*
2 * Copyright (C) 2021–2022 Beijing OSWare Technology Co., Ltd
3 * This file contains confidential and proprietary information of
4 * OSWare Technology Co., Ltd
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <linux/dma-mapping.h>
20
21 #include "imx8mm_platform.h"
22 #include "imx8mm_common.h"
23 #include "audio_platform_base.h"
24 #include "audio_sapm.h"
25 #include "audio_driver_log.h"
26 #include "osal_io.h"
27 #include "osal_uaccess.h"
28 #include "osal_time.h"
29 #include "dma_driver.h"
30
31 #define RATE_48000 (48000)
32 #define RATE_44100 (44100)
33 #define RATE_24576000 (24576000)
34 #define RATE_22579200 (22579200)
35 #define HDF_LOG_TAG imx8mm_platform_ops
36 int32_t g_dmaRequestChannel = 0;
37
Imx8mmDmaBufAlloc(struct PlatformData * data,const enum AudioStreamType streamType)38 int32_t Imx8mmDmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType)
39 {
40 int32_t ret = HDF_SUCCESS;
41
42 if (data == NULL) {
43 AUDIO_DRIVER_LOG_ERR("data is null");
44 return HDF_FAILURE;
45 }
46
47 if (AUDIO_RENDER_STREAM == streamType) {
48 ret = DMAInitTxBuff(data);
49 if (ret != HDF_SUCCESS) {
50 AUDIO_DRIVER_LOG_ERR("Imx8mmDmaBufAlloc: fail");
51 return HDF_FAILURE;
52 }
53 } else if (AUDIO_CAPTURE_STREAM == streamType) {
54 ret = DMAInitRxBuff(data);
55 if (ret != HDF_SUCCESS) {
56 AUDIO_DRIVER_LOG_ERR("Imx8mmDmaBufAlloc: fail");
57 return HDF_FAILURE;
58 }
59 } else {
60 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
61 return HDF_FAILURE;
62 }
63
64 return HDF_SUCCESS;
65 }
66
Imx8mmDmaBufFree(struct PlatformData * data,const enum AudioStreamType streamType)67 int32_t Imx8mmDmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType)
68 {
69 if (data == NULL) {
70 AUDIO_DRIVER_LOG_ERR("data is null");
71 return HDF_FAILURE;
72 }
73
74 if (streamType == AUDIO_CAPTURE_STREAM) {
75 if (data->captureBufInfo.virtAddr != NULL) {
76 (void)DMADeinitRxBuff(data);
77 }
78 } else if (streamType == AUDIO_RENDER_STREAM) {
79 if (data->renderBufInfo.virtAddr != NULL) {
80 (void)DMADeinitTxBuff(data);
81 }
82 } else {
83 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
84 return HDF_FAILURE;
85 }
86
87 return HDF_SUCCESS;
88 }
89
90 #define BYTE_NUM (2)
Imx8mmDmaRequestChannel(const struct PlatformData * data,const enum AudioStreamType streamType)91 int32_t Imx8mmDmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
92 {
93 int32_t ret;
94 uint32_t fmt = 0, freq = 0, clkId = 0, rate = 0, bitWidth = 0;
95 int channel = 0;
96 g_dmaRequestChannel = false;
97
98 if (data == NULL) {
99 return HDF_FAILURE;
100 }
101
102 if (streamType == AUDIO_RENDER_STREAM) {
103 channel = data->renderPcmInfo.channels;
104 rate = data->renderPcmInfo.rate;
105 bitWidth = data->renderPcmInfo.bitWidth;
106 } else if (streamType == AUDIO_CAPTURE_STREAM) {
107 channel = data->capturePcmInfo.channels;
108 rate = data->capturePcmInfo.rate;
109 bitWidth = data->capturePcmInfo.bitWidth;
110 } else {
111 return HDF_FAILURE;
112 }
113
114 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF;
115 if (rate == RATE_48000) {
116 freq = RATE_24576000;
117 } else if (rate == RATE_44100) {
118 freq = RATE_22579200;
119 }
120
121 clkId = FSL_SAI_CLK_MAST1;
122
123 ret = SaiRuntimeResume(data);
124 if (ret != HDF_SUCCESS) {
125 return ret;
126 }
127
128 ret = SaiSetDaiFmt(data, fmt);
129 if (ret != HDF_SUCCESS) {
130 return ret;
131 }
132
133 ret = SaiSetDaiTdmSlot(data, 0, 0, BYTE_NUM, bitWidth);
134 if (ret != HDF_SUCCESS) {
135 return ret;
136 }
137
138 ret = SaiSetSysclk(data, clkId, freq, SOC_CLOCK_OUT);
139 if (ret != HDF_SUCCESS) {
140 return ret;
141 }
142
143 ret = SaiSetHwParams(data, streamType);
144 if (ret != HDF_SUCCESS) {
145 return ret;
146 }
147
148 g_dmaRequestChannel = true;
149 return HDF_SUCCESS;
150 }
151
Imx8mmDmaConfigChannel(const struct PlatformData * data,const enum AudioStreamType streamType)152 int32_t Imx8mmDmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType)
153 {
154 int32_t ret;
155 struct PlatformData *platformData;
156
157 platformData = (struct PlatformData *)data;
158
159 if (streamType == AUDIO_CAPTURE_STREAM) {
160 if (platformData->captureBufInfo.virtAddr != NULL) {
161 ret = DMAConfigRxBuff(platformData);
162 if (ret != HDF_SUCCESS) {
163 AUDIO_DRIVER_LOG_ERR("DMAAiInit: fail");
164 return HDF_FAILURE;
165 }
166 }
167 } else if (streamType == AUDIO_RENDER_STREAM) {
168 if (data->renderBufInfo.virtAddr != NULL) {
169 ret = DMAConfigTxBuff((struct PlatformData *)data);
170 if (ret != HDF_SUCCESS) {
171 AUDIO_DRIVER_LOG_ERR("DMAAoInit: fail");
172 return HDF_FAILURE;
173 }
174 }
175 ret = DMAEnableTx(data);
176 if (ret != HDF_SUCCESS) {
177 AUDIO_DRIVER_LOG_ERR("DMAEnableTx failed");
178 return HDF_FAILURE;
179 }
180 } else {
181 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
182 return HDF_FAILURE;
183 }
184
185 return HDF_SUCCESS;
186 }
187
Imx8mmDmaPrep(const struct PlatformData * data,const enum AudioStreamType streamType)188 int32_t Imx8mmDmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType)
189 {
190 (void)data;
191 (void)streamType;
192 return HDF_SUCCESS;
193 }
194
Imx8mmDmaSubmit(const struct PlatformData * data,const enum AudioStreamType streamType)195 int32_t Imx8mmDmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType)
196 {
197 int ret = 0;
198 struct PlatformData *platformData;
199
200 platformData = (struct PlatformData *)data;
201
202 if (data == NULL) {
203 AUDIO_DRIVER_LOG_ERR("data is null");
204 return HDF_FAILURE;
205 }
206
207 if (streamType == AUDIO_CAPTURE_STREAM) {
208 ret = DMAEnableRx(data);
209 if (ret != HDF_SUCCESS) {
210 AUDIO_DRIVER_LOG_ERR("DMAEnableRx failed");
211 return HDF_FAILURE;
212 }
213 } else if (streamType == AUDIO_RENDER_STREAM) {
214 // delete dmaEnable because 1.after pause remalloc DMA buffer 2.DMA process must before sai trigger
215 } else {
216 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
217 return HDF_FAILURE;
218 }
219
220 return HDF_SUCCESS;
221 }
222
Imx8mmDmaPending(struct PlatformData * data,const enum AudioStreamType streamType)223 int32_t Imx8mmDmaPending(struct PlatformData *data, const enum AudioStreamType streamType)
224 {
225 (void)data;
226 (void)streamType;
227 return HDF_SUCCESS;
228 }
229
Imx8mmDmaPause(struct PlatformData * data,const enum AudioStreamType streamType)230 int32_t Imx8mmDmaPause(struct PlatformData *data, const enum AudioStreamType streamType)
231 {
232 struct PrivPlatformData *ppd = NULL;
233
234 if (data == NULL) {
235 AUDIO_DRIVER_LOG_ERR("data is null");
236 return HDF_FAILURE;
237 }
238
239 ppd = (struct PrivPlatformData *)data->dmaPrv;
240
241 if (streamType == AUDIO_CAPTURE_STREAM) {
242 DMAPauseRx(data);
243 } else if (streamType == AUDIO_RENDER_STREAM) {
244 data->renderBufInfo.runStatus = 0;
245 // change Disable DMA becasue 1.after pause remalloc DMA buffer
246 DMADisableTx(data);
247 ppd->tx_dma_pos = 0;
248 } else {
249 AUDIO_DRIVER_LOG_ERR("stream Type is invalude.");
250 return HDF_FAILURE;
251 }
252 return HDF_SUCCESS;
253 }
254
Imx8mmDmaResume(const struct PlatformData * data,const enum AudioStreamType streamType)255 int32_t Imx8mmDmaResume(const struct PlatformData *data, const enum AudioStreamType streamType)
256 {
257 int ret = 0;
258
259 if (data == NULL) {
260 AUDIO_DRIVER_LOG_ERR("data is null");
261 return HDF_FAILURE;
262 }
263
264 if (streamType == AUDIO_CAPTURE_STREAM) {
265 ret = DMAEnableRx(data);
266 if (ret != HDF_SUCCESS) {
267 AUDIO_DRIVER_LOG_ERR("DMAEnableRx failed");
268 return HDF_FAILURE;
269 }
270 } else if (streamType == AUDIO_RENDER_STREAM) {
271 ret = DMAEnableTx(data);
272 if (ret != HDF_SUCCESS) {
273 AUDIO_DRIVER_LOG_ERR("DMAEnableTx failed");
274 return HDF_FAILURE;
275 }
276 }
277
278 return HDF_SUCCESS;
279 }
280
Imx8mmDmaPointer(struct PlatformData * data,const enum AudioStreamType streamType,uint32_t * pointer)281 int32_t Imx8mmDmaPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer)
282 {
283 struct PrivPlatformData *ppd = NULL;
284
285 if (data == NULL || pointer == NULL) {
286 AUDIO_DRIVER_LOG_ERR("data is null");
287 return HDF_FAILURE;
288 }
289
290 ppd = (struct PrivPlatformData *)data->dmaPrv;
291
292 if (streamType == AUDIO_RENDER_STREAM) {
293 OsalMutexLock(&data->renderBufInfo.buffMutex);
294 *pointer = (ppd->tx_dma_pos) / (data->renderPcmInfo.frameSize);
295 OsalMutexUnlock(&data->renderBufInfo.buffMutex);
296 } else if (streamType == AUDIO_CAPTURE_STREAM) {
297 OsalMutexLock(&data->captureBufInfo.buffMutex);
298 *pointer = (ppd->rx_dma_pos) / (data->capturePcmInfo.frameSize);
299 OsalMutexUnlock(&data->captureBufInfo.buffMutex);
300 } else {
301 AUDIO_DRIVER_LOG_ERR("stream Type is fail.");
302 return HDF_FAILURE;
303 }
304
305 return HDF_SUCCESS;
306 }
307