1 /*
2 * Copyright (c) 2021 Huawei Device 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
9 #include "hi3516_aiao_impl.h"
10 #include "audio_host.h"
11 #include "audio_control.h"
12 #include "audio_dai_if.h"
13 #include "audio_dai_base.h"
14 #include "audio_driver_log.h"
15 #include "osal_io.h"
16
17 #define HDF_LOG_TAG hi3516_dai_ops
18
19 /* Hi35xx IO register address */
20 #define HI35XX_I2C_REG_BASE_ADDR (0x114F0000)
21 #define HI35XX_I2S_REG_BASE_ADDR (0x112F0000)
22 #define CODEC_REG_BASE (0x113C0000)
23 #define CODEC_MAX_REG_SIZE (0x1000)
24
25 #define I2S_IOCFG2_BASE1 0x0020
26 #define I2S_IOCFG2_BASE2 0x0024
27 #define I2S_IOCFG2_BASE3 0x0028
28 #define I2S_IOCFG2_BASE4 0x002C
29 #define I2S_IOCFG2_BASE5 0x0030
30
31 #define I2S_IOCFG2_BASE1_VAL 0x663
32 #define I2S_IOCFG2_BASE2_VAL 0x673
33 #define I2S_IOCFG2_BASE3_VAL 0x573
34 #define I2S_IOCFG2_BASE4_VAL 0x473
35 #define I2S_IOCFG2_BASE5_VAL 0x433
36
37 void *g_regCodecBase = NULL;
38 void *g_regDaiBase = NULL;
39
40 /* i2c6 init */
I2c6PinInit(void)41 static int I2c6PinInit(void)
42 {
43 char *regI2cBase = (void *)OsalIoRemap(HI35XX_I2C_REG_BASE_ADDR, 0x1000);
44 if (regI2cBase == NULL) {
45 AUDIO_DRIVER_LOG_ERR("regI2cBase is null.");
46 return HDF_FAILURE;
47 }
48 SysWritel((uintptr_t)regI2cBase + 0x0048, 0x0473); // I2C6_SCL
49 SysWritel((uintptr_t)regI2cBase + 0x004C, 0x0473); // I2C6_SDA
50 if (regI2cBase != NULL) {
51 OsalIoUnmap(regI2cBase);
52 }
53 AUDIO_DRIVER_LOG_DEBUG("success!");
54 return HDF_SUCCESS;
55 }
56
57 /* i2s0 pin init */
I2s0PinMux(const char * regI2sBase)58 static void I2s0PinMux(const char *regI2sBase)
59 {
60 SysWritel((uintptr_t)regI2sBase + I2S_IOCFG2_BASE1, I2S_IOCFG2_BASE1_VAL);
61 SysWritel((uintptr_t)regI2sBase + I2S_IOCFG2_BASE2, I2S_IOCFG2_BASE2_VAL);
62 SysWritel((uintptr_t)regI2sBase + I2S_IOCFG2_BASE3, I2S_IOCFG2_BASE3_VAL);
63 SysWritel((uintptr_t)regI2sBase + I2S_IOCFG2_BASE4, I2S_IOCFG2_BASE4_VAL);
64 SysWritel((uintptr_t)regI2sBase + I2S_IOCFG2_BASE5, I2S_IOCFG2_BASE5_VAL);
65 }
66
67 /* i2s init */
I2sPinInit(void)68 static int I2sPinInit(void)
69 {
70 char *regI2sBase = (void *)OsalIoRemap(HI35XX_I2S_REG_BASE_ADDR, 0x1000);
71 if (regI2sBase == NULL) {
72 AUDIO_DRIVER_LOG_ERR("regI2sBase is null.");
73 return HDF_FAILURE;
74 }
75 I2s0PinMux(regI2sBase);
76 if (regI2sBase != NULL) {
77 OsalIoUnmap(regI2sBase);
78 }
79 AUDIO_DRIVER_LOG_DEBUG("success!");
80 return HDF_SUCCESS;
81 }
82
DaiDeviceInit(struct AudioCard * audioCard,const struct DaiDevice * dai)83 int32_t DaiDeviceInit(struct AudioCard *audioCard, const struct DaiDevice *dai)
84 {
85 if (dai == NULL || dai->devData == NULL) {
86 AUDIO_DRIVER_LOG_ERR("dai is nullptr.");
87 return HDF_FAILURE;
88 }
89 struct DaiData *data = dai->devData;
90 struct AudioRegCfgData *regConfig = dai->devData->regConfig;
91 if (regConfig == NULL) {
92 AUDIO_DRIVER_LOG_ERR("regConfig is nullptr.");
93 return HDF_FAILURE;
94 }
95
96 if (g_regCodecBase == NULL) {
97 g_regCodecBase = OsalIoRemap(CODEC_REG_BASE, CODEC_MAX_REG_SIZE);
98 if (g_regCodecBase == NULL) {
99 AUDIO_DRIVER_LOG_ERR("OsalIoRemap fail.");
100 return HDF_FAILURE;
101 }
102 }
103
104 if (g_regDaiBase == NULL) {
105 g_regDaiBase = OsalIoRemap(regConfig->audioIdInfo.chipIdRegister,
106 regConfig->audioIdInfo.chipIdSize);
107 if (g_regDaiBase == NULL) {
108 AUDIO_DRIVER_LOG_ERR("OsalIoRemap fail.");
109 return HDF_FAILURE;
110 }
111 }
112
113 data->regVirtualAddr = (uintptr_t)g_regCodecBase;
114
115 if (DaiSetConfigInfo(data) != HDF_SUCCESS) {
116 AUDIO_DRIVER_LOG_ERR("set config info fail.");
117 return HDF_FAILURE;
118 }
119
120 int ret = AudioAddControls(audioCard, data->controls, data->numControls);
121 if (ret != HDF_SUCCESS) {
122 AUDIO_DRIVER_LOG_ERR("add controls failed.");
123 return HDF_FAILURE;
124 }
125
126 if (data->daiInitFlag == true) {
127 AUDIO_DRIVER_LOG_DEBUG("dai init complete!");
128 return HDF_SUCCESS;
129 }
130
131 if (I2c6PinInit() != HDF_SUCCESS) {
132 AUDIO_DRIVER_LOG_ERR("I2c6PinInit fail.");
133 return HDF_FAILURE;
134 }
135
136 data->daiInitFlag = true;
137
138 return HDF_SUCCESS;
139 }
140
DaiTrigger(const struct AudioCard * card,int cmd,const struct DaiDevice * device)141 int32_t DaiTrigger(const struct AudioCard *card, int cmd, const struct DaiDevice *device)
142 {
143 (void)card;
144 (void)device;
145 (void)cmd;
146
147 return HDF_SUCCESS;
148 }
149
DaiStartup(const struct AudioCard * card,const struct DaiDevice * device)150 int32_t DaiStartup(const struct AudioCard *card, const struct DaiDevice *device)
151 {
152 struct AudioMixerControl *regCfgItem = NULL;
153 (void)card;
154
155 if (device == NULL || device->devData == NULL || device->devData->regConfig == NULL ||
156 device->devData->regConfig->audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP] == NULL ||
157 device->devData->regConfig->audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP]->regCfgItem == NULL) {
158 AUDIO_DRIVER_LOG_ERR("input para is nullptr.");
159 return HDF_FAILURE;
160 }
161 regCfgItem = device->devData->regConfig->audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP]->regCfgItem;
162 int itemNum = device->devData->regConfig->audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP]->itemNum;
163
164 device->devData->regVirtualAddr = (uintptr_t)g_regDaiBase;
165 for (int i = 0; i < itemNum; i++) {
166 int ret = AudioUpdateDaiRegBits(device, regCfgItem[i].reg, regCfgItem[i].mask,
167 regCfgItem[i].shift, regCfgItem[i].value);
168 if (ret != HDF_SUCCESS) {
169 AUDIO_DRIVER_LOG_ERR("set frequency fail.");
170 return HDF_FAILURE;
171 }
172 }
173 device->devData->regVirtualAddr = (uintptr_t)g_regCodecBase;
174
175 if (I2sPinInit() != HDF_SUCCESS) {
176 AUDIO_DRIVER_LOG_ERR("I2sPinInit fail.");
177 }
178
179 return HDF_SUCCESS;
180 }
181
SetIISRate(const struct DaiDevice * device,const struct AudioMixerControl * regCfgItem)182 static int32_t SetIISRate(const struct DaiDevice *device, const struct AudioMixerControl *regCfgItem)
183 {
184 const uint32_t shiftMax = 4;
185 uint32_t mclkSel;
186 uint32_t shift = 0;
187 uint32_t bclkRegVal;
188
189 if (device == NULL || device->devData == NULL || regCfgItem == NULL) {
190 AUDIO_DRIVER_LOG_ERR("input para is nullptr.");
191 return HDF_FAILURE;
192 }
193 uint32_t rate = device->devData->pcmInfo.rate;
194 uint32_t bitWidth = device->devData->pcmInfo.bitWidth;
195
196 if (device->devData->pcmInfo.streamType == AUDIO_CAPTURE_STREAM) {
197 shift = shiftMax;
198 }
199
200 (void)memset_s(&mclkSel, sizeof(uint32_t), 0, sizeof(uint32_t));
201 if (AiaoGetMclk(rate, &mclkSel) != HDF_SUCCESS) {
202 return HDF_FAILURE;
203 }
204
205 if (AudioUpdateDaiRegBits(device, regCfgItem[0 + shift].reg, regCfgItem[0 + shift].mask,
206 regCfgItem[0 + shift].shift, mclkSel) != HDF_SUCCESS) {
207 AUDIO_DRIVER_LOG_ERR("set frequency fail.");
208 return HDF_FAILURE;
209 }
210
211 (void)memset_s(&bclkRegVal, sizeof(uint32_t), 0, sizeof(uint32_t));
212 if (AiaoSetSysCtlRegValue(mclkSel, bitWidth, rate, &bclkRegVal) != HDF_SUCCESS) {
213 return HDF_FAILURE;
214 }
215
216 if (AudioUpdateDaiRegBits(device, regCfgItem[1 + shift].reg, regCfgItem[1 + shift].mask,
217 regCfgItem[1 + shift].shift, bclkRegVal) != HDF_SUCCESS) {
218 AUDIO_DRIVER_LOG_ERR("set frequency fail.");
219 return HDF_FAILURE;
220 }
221 return HDF_SUCCESS;
222 }
223
DaiParamsUpdate(const struct DaiDevice * device)224 int32_t DaiParamsUpdate(const struct DaiDevice *device)
225 {
226 uint32_t value;
227 struct AudioMixerControl *regCfgItem = NULL;
228 const uint32_t shiftMax = 4;
229 uint32_t shift = 0;
230 const uint32_t index2 = 2;
231 const uint32_t index3 = 3;
232
233 if (device == NULL || device->devData == NULL || device->devData->regConfig == NULL ||
234 device->devData->regConfig->audioRegParams[AUDIO_DAI_PATAM_GROUP] == NULL ||
235 device->devData->regConfig->audioRegParams[AUDIO_DAI_PATAM_GROUP]->regCfgItem == NULL) {
236 AUDIO_DRIVER_LOG_ERR("input para is nullptr.");
237 return HDF_FAILURE;
238 }
239 regCfgItem = device->devData->regConfig->audioRegParams[AUDIO_DAI_PATAM_GROUP]->regCfgItem;
240
241 if (device->devData->pcmInfo.streamType == AUDIO_CAPTURE_STREAM) {
242 shift = shiftMax;
243 }
244
245 if (SetIISRate(device, regCfgItem) != HDF_SUCCESS) {
246 AUDIO_DRIVER_LOG_ERR("set Rate fail.");
247 return HDF_FAILURE;
248 }
249
250 uint32_t bitWidth = device->devData->pcmInfo.bitWidth;
251
252 if (bitWidth == BIT_WIDTH16) {
253 value = 0x1;
254 } else if (bitWidth == BIT_WIDTH24) {
255 value = 0x2; /* 2: 24bit */
256 } else {
257 AUDIO_DEVICE_LOG_ERR(" invalued bitWidth: %d.", bitWidth);
258 return HDF_FAILURE;
259 }
260
261 if (AudioUpdateDaiRegBits(device, regCfgItem[index2 + shift].reg, regCfgItem[index2 + shift].mask,
262 regCfgItem[index2 + shift].shift, value) != HDF_SUCCESS) {
263 AUDIO_DRIVER_LOG_ERR("set bitWidth fail.");
264 return HDF_FAILURE;
265 }
266
267 value = device->devData->pcmInfo.channels - 1;
268 if (AudioUpdateDaiRegBits(device, regCfgItem[index3 + shift].reg, regCfgItem[index3 + shift].mask,
269 regCfgItem[index3 + shift].shift, value) != HDF_SUCCESS) {
270 AUDIO_DRIVER_LOG_ERR("set channels fail.");
271 return HDF_FAILURE;
272 }
273 return HDF_SUCCESS;
274 }
275
DaiHwParams(const struct AudioCard * card,const struct AudioPcmHwParams * param)276 int32_t DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param)
277 {
278 uint32_t bitWidth;
279
280 if (card == NULL || card->rtd == NULL || card->rtd->cpuDai == NULL ||
281 param == NULL || param->cardServiceName == NULL) {
282 AUDIO_DRIVER_LOG_ERR("input para is nullptr.");
283 return HDF_FAILURE;
284 }
285 struct DaiDevice *device = card->rtd->cpuDai;
286
287 if (DaiCheckSampleRate(param->rate) != HDF_SUCCESS) {
288 return HDF_ERR_NOT_SUPPORT;
289 }
290
291 struct DaiData *data = DaiDataFromCard(card);
292 if (data == NULL) {
293 AUDIO_DRIVER_LOG_ERR("platformHost is nullptr.");
294 return HDF_FAILURE;
295 }
296
297 data->pcmInfo.channels = param->channels;
298
299 if (AudioFramatToBitWidth(param->format, &bitWidth) != HDF_SUCCESS) {
300 return HDF_FAILURE;
301 }
302
303 data->pcmInfo.bitWidth = bitWidth;
304 data->pcmInfo.rate = param->rate;
305 data->pcmInfo.streamType = param->streamType;
306 data->regVirtualAddr = (uintptr_t)g_regDaiBase;
307
308 if (DaiParamsUpdate(device) != HDF_SUCCESS) {
309 AUDIO_DRIVER_LOG_ERR("DaiParamsUpdate: fail.");
310 return HDF_FAILURE;
311 }
312 data->regVirtualAddr = (uintptr_t)g_regCodecBase;
313 return HDF_SUCCESS;
314 }
315