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 "hi3516_codec_impl.h"
11 #include "audio_control.h"
12 #include "audio_core.h"
13 #include "audio_driver_log.h"
14 #include "audio_platform_base.h"
15 #include "osal_io.h"
16 #include <asm/io.h>
17
18 #define HDF_LOG_TAG hi3516_codec_impl
19
20 static void *g_regAcodecBase = NULL; // CODEC Reg Base Addr
21 const int HALF_MINUTE = 30;
22 const int VOLUME_DB_MAX = 6;
23 const int VOLUME_DB_MIN = -121;
24
CodecHalSysInit(struct CodecData * codeData)25 int32_t CodecHalSysInit(struct CodecData *codeData)
26 {
27 if (codeData == NULL) {
28 AUDIO_DEVICE_LOG_ERR("input invalid parameter.");
29 return HDF_ERR_INVALID_PARAM;
30 }
31 // ACODEC REMAP
32 if (g_regAcodecBase == NULL) {
33 g_regAcodecBase = (void *)(uintptr_t)(codeData->virtualAddress);
34 if (g_regAcodecBase == NULL) {
35 AUDIO_DEVICE_LOG_ERR("regAcodecBase is null.");
36 return HDF_FAILURE;
37 }
38 }
39 return HDF_SUCCESS;
40 }
41
42 // Read contrl reg bits value
CodecRegBitsRead(struct AudioMixerControl * regAttr,uint32_t * regValue)43 int32_t CodecRegBitsRead(struct AudioMixerControl *regAttr, uint32_t *regValue)
44 {
45 if (g_regAcodecBase == NULL || regAttr == NULL ||
46 regAttr->reg < 0 || regValue == NULL) {
47 AUDIO_DEVICE_LOG_ERR("input invalid parameter.");
48 return HDF_ERR_INVALID_PARAM;
49 }
50 regAttr->value = SysReadl((uintptr_t)g_regAcodecBase + regAttr->reg);
51 *regValue = regAttr->value;
52 regAttr->value = (*regValue >> regAttr->shift) & regAttr->mask;
53 if (regAttr->value > regAttr->max || regAttr->value < regAttr->min) {
54 AUDIO_DEVICE_LOG_DEBUG("invalid bitsValue=0x%x", regAttr->value);
55 return HDF_FAILURE;
56 }
57 if (regAttr->invert) {
58 regAttr->value = regAttr->max - regAttr->value;
59 }
60 return HDF_SUCCESS;
61 }
62
63 // Update contrl reg bits value
CodecRegBitsUpdate(struct AudioMixerControl regAttr)64 int32_t CodecRegBitsUpdate(struct AudioMixerControl regAttr)
65 {
66 int32_t ret;
67 uint32_t newValue, newMask, oldValue;
68 if (g_regAcodecBase == NULL || regAttr.reg < 0) {
69 AUDIO_DEVICE_LOG_ERR("input invalid parameter.");
70 return HDF_ERR_INVALID_PARAM;
71 }
72 if (regAttr.invert) {
73 regAttr.value = regAttr.max - regAttr.value;
74 }
75 newValue = regAttr.value << regAttr.shift;
76 newMask = regAttr.mask << regAttr.shift;
77 ret = CodecRegBitsRead(®Attr, &oldValue);
78 if (ret != HDF_SUCCESS) {
79 ADM_LOG_ERR("CodecRegBitsRead failed, ret=%d.", ret);
80 return HDF_FAILURE;
81 }
82 regAttr.value = (oldValue & ~newMask) | (newValue & newMask);
83 SysWritel((uintptr_t)g_regAcodecBase + regAttr.reg, regAttr.value);
84 return HDF_SUCCESS;
85 }
86
CodecRegDefaultInit(struct AudioRegCfgGroupNode ** regCfgGroup)87 int32_t CodecRegDefaultInit(struct AudioRegCfgGroupNode **regCfgGroup)
88 {
89 int32_t i;
90 struct AudioAddrConfig *regAttr = NULL;
91 if (g_regAcodecBase == NULL || regCfgGroup == NULL || regCfgGroup[AUDIO_INIT_GROUP] == NULL ||
92 regCfgGroup[AUDIO_INIT_GROUP]->addrCfgItem == NULL || regCfgGroup[AUDIO_INIT_GROUP]->itemNum <= 0) {
93 AUDIO_DEVICE_LOG_ERR("input invalid parameter.");
94 return HDF_FAILURE;
95 }
96 regAttr = regCfgGroup[AUDIO_INIT_GROUP]->addrCfgItem;
97
98 for (i = 0; i < regCfgGroup[AUDIO_INIT_GROUP]->itemNum; i++) {
99 SysWritel((uintptr_t)g_regAcodecBase + regAttr[i].addr, regAttr[i].value);
100 }
101 AUDIO_DEVICE_LOG_DEBUG("success.");
102 return HDF_SUCCESS;
103 }
104
CodecGetI2sFs(const unsigned int rate)105 static unsigned int CodecGetI2sFs(const unsigned int rate)
106 {
107 switch (rate) {
108 case AUDIO_SAMPLE_RATE_8000:
109 case AUDIO_SAMPLE_RATE_11025:
110 case AUDIO_SAMPLE_RATE_12000:
111 return ACODEC_I2S_FS_8000;
112 case AUDIO_SAMPLE_RATE_16000:
113 case AUDIO_SAMPLE_RATE_22050:
114 case AUDIO_SAMPLE_RATE_24000:
115 return ACODEC_I2S_FS_16000;
116 case AUDIO_SAMPLE_RATE_32000:
117 case AUDIO_SAMPLE_RATE_44100:
118 case AUDIO_SAMPLE_RATE_48000:
119 return ACODEC_I2S_FS_32000;
120 case AUDIO_SAMPLE_RATE_64000:
121 case AUDIO_SAMPLE_RATE_96000:
122 return ACODEC_I2S_FS_64000;
123 default:
124 AUDIO_DEVICE_LOG_DEBUG("unsupport samplerate %d\n", rate);
125 return ACODEC_I2S_FS_BUTT;
126 }
127 }
128
CodecGetAdcModeSel(const unsigned int rate)129 static unsigned int CodecGetAdcModeSel(const unsigned int rate)
130 {
131 switch (rate) {
132 case AUDIO_SAMPLE_RATE_8000:
133 case AUDIO_SAMPLE_RATE_16000:
134 case AUDIO_SAMPLE_RATE_32000:
135 case AUDIO_SAMPLE_RATE_64000:
136 return ACODEC_ADC_MODESEL_4096;
137 case AUDIO_SAMPLE_RATE_11025:
138 case AUDIO_SAMPLE_RATE_12000:
139 case AUDIO_SAMPLE_RATE_22050:
140 case AUDIO_SAMPLE_RATE_24000:
141 case AUDIO_SAMPLE_RATE_44100:
142 case AUDIO_SAMPLE_RATE_48000:
143 case AUDIO_SAMPLE_RATE_96000:
144 return ACODEC_ADC_MODESEL_6144;
145 default:
146 AUDIO_DEVICE_LOG_DEBUG("unsupport samplerate %d.\n", rate);
147 return ACODEC_I2S_FS_BUTT;
148 }
149 }
150
CodecGetI2s1DataWidth(unsigned int bitWidth,uint16_t * i2s1DataWidth)151 static int32_t CodecGetI2s1DataWidth(unsigned int bitWidth, uint16_t *i2s1DataWidth)
152 {
153 if (i2s1DataWidth == NULL) {
154 AUDIO_DEVICE_LOG_ERR("input param is NULL");
155 return HDF_FAILURE;
156 }
157 *i2s1DataWidth = AUDIO_CODEC_BIT_WIDTH_16;
158 switch (bitWidth) {
159 case BIT_WIDTH16:
160 *i2s1DataWidth = AUDIO_CODEC_BIT_WIDTH_16;
161 break;
162 case BIT_WIDTH18:
163 *i2s1DataWidth = AUDIO_CODEC_BIT_WIDTH_18;
164 break;
165 case BIT_WIDTH20:
166 *i2s1DataWidth = AUDIO_CODEC_BIT_WIDTH_20;
167 break;
168 case BIT_WIDTH24:
169 *i2s1DataWidth = AUDIO_CODEC_BIT_WIDTH_24;
170 break;
171 default:
172 AUDIO_DEVICE_LOG_ERR("unsupport sample bit width %d.\n", bitWidth);
173 return AUDIO_CODEC_BIT_WIDTH_BUTT;
174 }
175 return HDF_SUCCESS;
176 }
177
CodecDaiParamsUpdate(struct AudioRegCfgGroupNode ** regCfgGroup,struct CodecDaiParamsVal codecDaiParamsVal)178 int32_t CodecDaiParamsUpdate(struct AudioRegCfgGroupNode **regCfgGroup,
179 struct CodecDaiParamsVal codecDaiParamsVal)
180 {
181 int32_t ret;
182 const int itemNum = 3; // current only 3 items
183 struct AudioMixerControl *regAttr = NULL;
184 uint16_t codecBitWidth;
185
186 ret = (regCfgGroup == NULL
187 || regCfgGroup[AUDIO_DAI_PATAM_GROUP] == NULL
188 || regCfgGroup[AUDIO_DAI_PATAM_GROUP]->regCfgItem == NULL
189 || regCfgGroup[AUDIO_DAI_PATAM_GROUP]->itemNum < itemNum);
190 if (ret) {
191 AUDIO_DEVICE_LOG_ERR("input invalid parameter.");
192 return HDF_FAILURE;
193 }
194 regAttr = regCfgGroup[AUDIO_DAI_PATAM_GROUP]->regCfgItem;
195
196 regAttr[0].value = CodecGetI2sFs(codecDaiParamsVal.frequencyVal);
197 ret = CodecRegBitsUpdate(regAttr[0]); // i2s_frequency
198 if (ret != HDF_SUCCESS) {
199 AUDIO_DEVICE_LOG_ERR("set i2s_frequency failed.");
200 return HDF_FAILURE;
201 }
202 regAttr[1].value = CodecGetAdcModeSel(codecDaiParamsVal.frequencyVal);
203 ret = CodecRegBitsUpdate(regAttr[1]); // adc_mode_sel
204 if (ret != HDF_SUCCESS) {
205 AUDIO_DEVICE_LOG_ERR("set adc_mode_sel failed.");
206 return HDF_FAILURE;
207 }
208
209 ret = CodecGetI2s1DataWidth(codecDaiParamsVal.formatVal, &codecBitWidth);
210 if (ret != HDF_SUCCESS) {
211 AUDIO_DEVICE_LOG_ERR("I2s1DataWidthSel failed.");
212 return HDF_FAILURE;
213 }
214 regAttr[itemNum - 1].value = codecBitWidth; // i2s_datawith
215 ret = CodecRegBitsUpdate(regAttr[itemNum - 1]);
216 if (ret != HDF_SUCCESS) {
217 AUDIO_DEVICE_LOG_ERR("set i2s_datawith failed.");
218 return HDF_FAILURE;
219 }
220 AUDIO_DEVICE_LOG_DEBUG("success.");
221 return HDF_SUCCESS;
222 }
223
CodecSetAdcTuneEnable(struct AudioRegCfgGroupNode ** regCfgGroup)224 int32_t CodecSetAdcTuneEnable(struct AudioRegCfgGroupNode **regCfgGroup)
225 {
226 int32_t ret;
227 struct AudioMixerControl *regAttr = NULL;
228 const int itemNum = 1;
229 ret = (regCfgGroup == NULL || regCfgGroup[AUDIO_DAI_STARTUP_PATAM_GROUP] == NULL
230 || regCfgGroup[AUDIO_DAI_STARTUP_PATAM_GROUP]->regCfgItem == NULL
231 || regCfgGroup[AUDIO_DAI_STARTUP_PATAM_GROUP]->itemNum < itemNum);
232 if (ret) {
233 AUDIO_DEVICE_LOG_ERR("input invalid parameter.");
234 return HDF_FAILURE;
235 }
236 regAttr = regCfgGroup[AUDIO_DAI_STARTUP_PATAM_GROUP]->regCfgItem;
237 ret = CodecRegBitsUpdate(regAttr[0]);
238 if (ret != HDF_SUCCESS) {
239 AUDIO_DEVICE_LOG_ERR("set adc_tune_En09 failed.");
240 return HDF_FAILURE;
241 }
242 AUDIO_DEVICE_LOG_DEBUG("success.");
243 return HDF_SUCCESS;
244 }
245
AudioCodecAiaoGetCtrlOps(const struct AudioKcontrol * kcontrol,struct AudioCtrlElemValue * elemValue)246 int32_t AudioCodecAiaoGetCtrlOps(const struct AudioKcontrol *kcontrol, struct AudioCtrlElemValue *elemValue)
247 {
248 uint32_t curValue;
249 uint32_t rcurValue;
250 void *codecVir = NULL;
251 struct AudioMixerControl *mixerCtrl = NULL;
252 if (kcontrol == NULL || kcontrol->privateValue <= 0 || elemValue == NULL) {
253 AUDIO_DEVICE_LOG_ERR("Audio input param is NULL.");
254 return HDF_ERR_INVALID_OBJECT;
255 }
256 mixerCtrl = (struct AudioMixerControl *)((volatile uintptr_t)kcontrol->privateValue);
257 if (mixerCtrl == NULL) {
258 AUDIO_DEVICE_LOG_ERR("mixerCtrl is NULL.");
259 return HDF_FAILURE;
260 }
261 codecVir = OsalIoRemap(AIAO_REG_BASE, AIAO_MAX_REG_SIZE);
262 if (codecVir == NULL) {
263 AUDIO_DEVICE_LOG_ERR("codecVir is NULL.");
264 return HDF_FAILURE;
265 }
266 curValue = OSAL_READL((void *)((uintptr_t)codecVir + mixerCtrl->reg));
267 rcurValue = OSAL_READL((void *)((uintptr_t)codecVir + mixerCtrl->rreg));
268 OsalIoUnmap(codecVir);
269
270 if (AudioGetCtrlOpsReg(elemValue, mixerCtrl, curValue) != HDF_SUCCESS ||
271 AudioGetCtrlOpsRReg(elemValue, mixerCtrl, rcurValue) != HDF_SUCCESS) {
272 AUDIO_DEVICE_LOG_ERR("Audio codec get kcontrol reg and rreg failed.");
273 return HDF_FAILURE;
274 }
275
276 return HDF_SUCCESS;
277 }
278
AudioUpdateCodecAiaoRegBits(const struct AudioMixerControl * mixerControl,uint32_t value)279 static void AudioUpdateCodecAiaoRegBits(const struct AudioMixerControl *mixerControl, uint32_t value)
280 {
281 if (mixerControl == NULL) {
282 AUDIO_DEVICE_LOG_ERR("param mixerControl is null.");
283 return;
284 }
285
286 uint32_t curValue;
287 void *codecVir = NULL;
288 uint32_t mixerControlMask;
289
290 value = value << mixerControl->shift;
291 mixerControlMask = mixerControl->mask << mixerControl->shift;
292 codecVir = OsalIoRemap(AIAO_REG_BASE, AIAO_MAX_REG_SIZE);
293 if (codecVir == NULL) {
294 AUDIO_DEVICE_LOG_ERR("codecVir is NULL.");
295 return;
296 }
297
298 curValue = OSAL_READL((void *)((uintptr_t)codecVir + mixerControl->reg));
299 curValue = (curValue & ~mixerControlMask) | (value & mixerControlMask);
300 OSAL_WRITEL(curValue, (void *)((uintptr_t)codecVir + mixerControl->reg));
301 OsalIoUnmap(codecVir);
302 }
303
AudioCodecAiaoSetCtrlOps(const struct AudioKcontrol * kcontrol,const struct AudioCtrlElemValue * elemValue)304 int32_t AudioCodecAiaoSetCtrlOps(const struct AudioKcontrol *kcontrol, const struct AudioCtrlElemValue *elemValue)
305 {
306 uint32_t value;
307 uint32_t rvalue;
308 bool updateRReg = false;
309 struct AudioMixerControl *mixerCtrl = NULL;
310 if (kcontrol == NULL || (kcontrol->privateValue <= 0) || elemValue == NULL) {
311 AUDIO_DEVICE_LOG_ERR("Audio input param is NULL.");
312 return HDF_ERR_INVALID_OBJECT;
313 }
314
315 mixerCtrl = (struct AudioMixerControl *)((volatile uintptr_t)kcontrol->privateValue);
316 if (AudioSetCtrlOpsReg(kcontrol, elemValue, mixerCtrl, &value) != HDF_SUCCESS) {
317 AUDIO_DEVICE_LOG_ERR("AudioSetCtrlOpsReg is failed.");
318 return HDF_ERR_INVALID_OBJECT;
319 }
320 AudioUpdateCodecAiaoRegBits(mixerCtrl, value);
321 if (AudioSetCtrlOpsRReg(elemValue, mixerCtrl, &rvalue, &updateRReg) != HDF_SUCCESS) {
322 AUDIO_DEVICE_LOG_ERR("AudioSetCtrlOpsRReg is failed.");
323 return HDF_ERR_INVALID_OBJECT;
324 }
325 if (updateRReg) {
326 AudioUpdateCodecAiaoRegBits(mixerCtrl, rvalue);
327 }
328
329 return HDF_SUCCESS;
330 }
331