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 "gpio_if.h"
20 #include "i2c_if.h"
21 #include "audio_device_log.h"
22 #include "imx8mm_common.h"
23 #include "wm8904_log.h"
24 #include "wm8904.h"
25 #include "audio_codec_base.h"
26 #include "audio_core.h"
27 #define WM8904_I2C_BUS_NUM (1)
28 #define WM8904_I2C_REG_DATA_LEN (2)
29
30 #define DATA_LEN_1 (1)
31 #define DATA_LEN_2 (2)
32 #define BYTE_NUM (8)
33
WM8904I2cOpen(void)34 DevHandle WM8904I2cOpen(void)
35 {
36 DevHandle i2cHandle;
37 i2cHandle = I2cOpen(WM8904_I2C_BUS_NUM);
38 if (i2cHandle == NULL) {
39 WM8904_CODEC_LOG_ERR("open i2cBus:%u fail! i2cHandle:%p", WM8904_I2C_BUS_NUM, i2cHandle);
40 return NULL;
41 }
42 return i2cHandle;
43 }
44
WM8904I2cClose(DevHandle handle)45 void WM8904I2cClose(DevHandle handle)
46 {
47 I2cClose(handle);
48 }
49
50 #define gwm8904i2cDevAddr (0x1a)
51 #define WM8904RegAddrLen (1) // unit byte
52 struct I2cTransferParam g_transferParam;
53
54
55 /************************************************************************************************
56 WM8904I2cRead: Read any Length byte from i2 device reg
57 struct DevHandle i2cHandle[in] : i2c bus Handle
58 unsigned int regaddr [in] : max supports 16 bits i2c device reg address
59 unsigned int regLen [in] : reg address length(8 or 16 bits)
60 uint8_t *regdata [out] : buffer
61 unsigned int dataLen [in] : buffer length
62 return : status
63 ************************************************************************************************/
WM8904I2cRead(DevHandle i2cHandle,uint16_t regaddr,unsigned int regLen,uint8_t * regdata,unsigned int dataLen)64 static int WM8904I2cRead(DevHandle i2cHandle, uint16_t regaddr,
65 unsigned int regLen, uint8_t *regdata, unsigned int dataLen)
66 {
67 int index = 0;
68 unsigned char regBuf[4] = {0};
69 struct I2cMsg msgs[2] = {0};
70
71 if (regLen == 1) {
72 regBuf[index++] = regaddr & 0xFF;
73 } else {
74 // i2c first write reg high 8 bits
75 regBuf[index++] = (regaddr >> 8) & 0xFF;
76 regBuf[index++] = regaddr & 0xFF;
77 }
78
79 // msgs[0] write regaddr to adapter
80 msgs[0].addr = gwm8904i2cDevAddr;
81 msgs[0].flags = 0;
82 msgs[0].len = regLen;
83 msgs[0].buf = regBuf;
84
85 // msgs[1] read dataLen byte regvalue to *regdata
86 msgs[1].addr = gwm8904i2cDevAddr;
87 msgs[1].flags = I2C_FLAG_READ;
88 msgs[1].len = dataLen;
89 msgs[1].buf = regdata;
90
91 if (I2cTransfer(i2cHandle, msgs, DATA_LEN_2) != DATA_LEN_2) {
92 WM8904_CODEC_LOG_ERR("i2c I2cTransfer read msg err");
93 return HDF_FAILURE;
94 }
95 return HDF_SUCCESS;
96 }
97
WM8904RegRead(DevHandle i2cHandle,unsigned int reg,unsigned int * val,unsigned int dataLen)98 int WM8904RegRead(DevHandle i2cHandle, unsigned int reg, unsigned int *val, unsigned int dataLen)
99 {
100 int32_t ret;
101 unsigned char regBuf[2] = {0};
102 WM8904_CODEC_LOG_DEBUG("entry");
103 if (val == NULL) {
104 WM8904_CODEC_LOG_ERR("input para is NULL.");
105 return HDF_ERR_INVALID_OBJECT;
106 }
107
108 if (dataLen == DATA_LEN_2) {
109 ret = WM8904I2cRead(i2cHandle, reg, WM8904RegAddrLen, regBuf, dataLen);
110 if (ret != HDF_SUCCESS) {
111 WM8904_CODEC_LOG_ERR("WM8904RegSeqRead fail.");
112 return HDF_FAILURE;
113 }
114 *val = 0;
115 *val = (regBuf[0] << BYTE_NUM) | regBuf[1];
116 } else if (dataLen == DATA_LEN_1) {
117 ret = WM8904I2cRead(i2cHandle, reg, WM8904RegAddrLen, regBuf, dataLen);
118 if (ret != HDF_SUCCESS) {
119 WM8904_CODEC_LOG_ERR("WM8904RegSeqRead fail.");
120 return HDF_FAILURE;
121 }
122 *val = regBuf[0];
123 } else {
124 WM8904_CODEC_LOG_ERR("input para is NULL. dataLen > 2");
125 }
126 return HDF_SUCCESS;
127 }
128
129 /*********************************************************************************************
130 WM8904I2cWrite: Write any Length byte from i2 device reg
131 struct DevHandle i2cHandle[in] : i2c bus Handle
132 unsigned int regaddr [in] : max supports 16 bits i2c device reg address
133 unsigned int regLen [in] : reg address length(8 or 16 bits)
134 uint8_t *regdata [in] : buffer
135 unsigned int dataLen [in] : buffer length
136 return : status
137 *********************************************************************************************/
WM8904I2cWrite(DevHandle i2cHandle,uint16_t regaddr,unsigned int regLen,uint8_t * regdata,unsigned int dataLen)138 static int WM8904I2cWrite(DevHandle i2cHandle, uint16_t regaddr,
139 unsigned int regLen, uint8_t *regdata, unsigned int dataLen)
140 {
141 int index = 0;
142 unsigned char regBuf[4] = {0};
143 struct I2cMsg msgs[1] = {0};
144
145 if (regLen == 1) {
146 regBuf[index++] = regaddr & 0xFF;
147 } else {
148 // i2c first write reg high 8 bits
149 regBuf[index++] = (regaddr >> 8) & 0xFF;
150 regBuf[index++] = regaddr & 0xFF;
151 }
152
153 for (int i = 0; i < dataLen; i++) {
154 regBuf[index++] = regdata[i];
155 }
156
157 // write regaddr to adapter
158 msgs[0].addr = gwm8904i2cDevAddr;
159 msgs[0].flags = 0;
160 msgs[0].len = regLen + dataLen;
161 msgs[0].buf = regBuf;
162
163 if (I2cTransfer(i2cHandle, msgs, 1) != 1) {
164 WM8904_CODEC_LOG_ERR("i2c I2cTransfer write msg err");
165 return HDF_FAILURE;
166 }
167 return HDF_SUCCESS;
168 }
169
WM8904RegWrite(DevHandle i2cHandle,unsigned int reg,unsigned int val,unsigned int dataLen)170 int WM8904RegWrite(DevHandle i2cHandle, unsigned int reg, unsigned int val, unsigned int dataLen)
171 {
172 int32_t ret;
173 unsigned char regBuf[2] = {0};
174
175 WM8904_CODEC_LOG_DEBUG("entry");
176
177 if (dataLen == DATA_LEN_2) {
178 regBuf[0] = (val >> BYTE_NUM) & 0xFF;
179 regBuf[1] = val & 0xFF;
180
181 ret = WM8904I2cWrite(i2cHandle, reg, WM8904RegAddrLen, regBuf, dataLen);
182 if (ret != HDF_SUCCESS) {
183 WM8904_CODEC_LOG_ERR("datalen=2 fail.");
184 return HDF_FAILURE;
185 }
186 } else if (dataLen == DATA_LEN_1) {
187 regBuf[0] = val;
188 ret = WM8904I2cWrite(i2cHandle, reg, WM8904RegAddrLen, regBuf, dataLen);
189 if (ret != HDF_SUCCESS) {
190 WM8904_CODEC_LOG_DEBUG("datalen=1 fail.");
191 return HDF_FAILURE;
192 }
193 } else {
194 WM8904_CODEC_LOG_DEBUG("input para is NULL. dataLen > 2");
195 }
196
197 return HDF_SUCCESS;
198 }
199
WM8904RegUpdateBits(DevHandle i2cHandle,unsigned int reg,unsigned int mask,unsigned int val,unsigned int dataLen)200 int WM8904RegUpdateBits(DevHandle i2cHandle, unsigned int reg, unsigned int mask,
201 unsigned int val, unsigned int dataLen)
202 {
203 unsigned int ret = 0, tmp = 0, orig = 0;
204
205 ret = WM8904RegRead(i2cHandle, reg, &orig, dataLen);
206 if (ret != HDF_SUCCESS)
207 return ret;
208
209 tmp = orig & ~mask;
210 tmp |= val & mask;
211
212 if (tmp != orig) {
213 ret = WM8904RegWrite(i2cHandle, reg, tmp, dataLen);
214 }
215 return ret;
216 }
217
218 #define CODEC_REG_ADDR_DUMMY (0x00)
219
220 static const struct AudioMixerControl g_audioRegParams = {
221 .reg = CODEC_REG_ADDR_DUMMY,
222 .rreg = CODEC_REG_ADDR_DUMMY,
223 .shift = 0,
224 .rshift = 0,
225 .min = 0x0,
226 .max = 0xFF,
227 .mask = 0x1,
228 .invert = 1,
229 };
230
231 static const struct AudioKcontrol g_audioControls[] = {
232 {
233 .iface = AUDIODRV_CTL_ELEM_IFACE_ACODEC,
234 .name = "External Codec Enable",
235 .Info = AudioInfoCtrlOps,
236 .Get = AudioCodecGetCtrlOps,
237 .Set = AudioCodecSetCtrlOps,
238 .privateValue = (unsigned long)&g_audioRegParams,
239 }, {
240 .iface = AUDIODRV_CTL_ELEM_IFACE_ACODEC,
241 .name = "Internally Codec Enable",
242 .Info = AudioInfoCtrlOps,
243 .Get = AudioCodecGetCtrlOps,
244 .Set = AudioCodecSetCtrlOps,
245 .privateValue = (unsigned long)&g_audioRegParams,
246 }, {
247 .iface = AUDIODRV_CTL_ELEM_IFACE_AIAO,
248 .name = "Render Channel Mode",
249 .Info = AudioInfoCtrlOps,
250 .Get = AudioCodecGetCtrlOps,
251 .Set = AudioCodecSetCtrlOps,
252 .privateValue = (unsigned long)&g_audioRegParams,
253 }, {
254 .iface = AUDIODRV_CTL_ELEM_IFACE_AIAO,
255 .name = "Captrue Channel Mode",
256 .Info = AudioInfoCtrlOps,
257 .Get = AudioCodecGetCtrlOps,
258 .Set = AudioCodecSetCtrlOps,
259 .privateValue = (unsigned long)&g_audioRegParams,
260 },
261 {
262 .iface = AUDIODRV_CTL_ELEM_IFACE_PGA,
263 .name = "LPGA MIC Switch",
264 .Info = AudioInfoCtrlOps,
265 .Get = AudioCodecGetCtrlOps,
266 .Set = AudioCodecSetCtrlOps,
267 .privateValue = (unsigned long)&g_audioRegParams,
268 },
269 {
270 .iface = AUDIODRV_CTL_ELEM_IFACE_PGA,
271 .name = "RPGA MIC Switch",
272 .Info = AudioInfoCtrlOps,
273 .Get = AudioCodecGetCtrlOps,
274 .Set = AudioCodecSetCtrlOps,
275 .privateValue = (unsigned long)&g_audioRegParams,
276 },
277 /* for sapm test */
278 {
279 .iface = AUDIODRV_CTL_ELEM_IFACE_DAC,
280 .name = "Dacl enable",
281 .Info = AudioInfoCtrlOps,
282 .Get = AudioCodecGetCtrlOps,
283 .Set = AudioCodecSetCtrlOps,
284 .privateValue = (unsigned long)&g_audioRegParams,
285 },
286 {
287 .iface = AUDIODRV_CTL_ELEM_IFACE_DAC,
288 .name = "Dacr enable",
289 .Info = AudioInfoCtrlOps,
290 .Get = AudioCodecGetCtrlOps,
291 .Set = AudioCodecSetCtrlOps,
292 .privateValue = (unsigned long)&g_audioRegParams,
293 },
294 {
295 .iface = 2,
296 .name = "Speaker1 Switch",
297 .Info = AudioInfoCtrlOps,
298 .Get = AudioCodecGetCtrlOps,
299 .Set = AudioCodecSetCtrlOps,
300 .privateValue = (unsigned long)&g_audioRegParams,
301 },
302 {
303 .iface = 2,
304 .name = "Headphone1 Switch",
305 .Info = AudioInfoCtrlOps,
306 .Get = AudioCodecGetCtrlOps,
307 .Set = AudioCodecSetCtrlOps,
308 .privateValue = (unsigned long)&g_audioRegParams,
309 },
310 {
311 .iface = 2,
312 .name = "Headphone2 Switch",
313 .Info = AudioInfoCtrlOps,
314 .Get = AudioCodecGetCtrlOps,
315 .Set = AudioCodecSetCtrlOps,
316 .privateValue = (unsigned long)&g_audioRegParams,
317 },
318 {
319 .iface = 2,
320 .name = "DACL Left Speaker Mixer",
321 .Info = AudioInfoCtrlOps,
322 .Get = AudioCodecGetCtrlOps,
323 .Set = AudioCodecSetCtrlOps,
324 .privateValue = (unsigned long)&g_audioRegParams,
325 },
326 {
327 .iface = 2,
328 .name = "DACR Left Speaker Mixer",
329 .Info = AudioInfoCtrlOps,
330 .Get = AudioCodecGetCtrlOps,
331 .Set = AudioCodecSetCtrlOps,
332 .privateValue = (unsigned long)&g_audioRegParams,
333 },
334
335 };
336
Wm8904DevInit(struct AudioCard * audioCard,const struct CodecDevice * device)337 int32_t Wm8904DevInit(struct AudioCard *audioCard, const struct CodecDevice *device)
338 {
339 int32_t ret;
340
341 if ((audioCard == NULL) || (device == NULL)) {
342 WM8904_CODEC_LOG_ERR("input para is NULL.");
343 return HDF_ERR_INVALID_OBJECT;
344 }
345 g_transferParam.i2cDevAddr = gwm8904i2cDevAddr;
346 g_transferParam.i2cBusNumber = WM8904_I2C_BUS_NUM;
347 g_transferParam.i2cRegDataLen = WM8904_I2C_REG_DATA_LEN;
348 device->devData->privateParam = &g_transferParam;
349 ret = AudioAddControls(audioCard, device->devData->controls, device->devData->numControls);
350 if (ret != HDF_SUCCESS) {
351 WM8904_CODEC_LOG_ERR("AudioAddControls failed.");
352 return HDF_FAILURE;
353 }
354
355 if (AudioAddControls(audioCard, g_audioControls, HDF_ARRAY_SIZE(g_audioControls)) != HDF_SUCCESS) {
356 WM8904_CODEC_LOG_DEBUG("add controls fail.");
357 }
358 WM8904_CODEC_LOG_DEBUG("success.");
359 return HDF_SUCCESS;
360 }
361
Wm8904DaiStart(const struct AudioCard * card,const struct DaiDevice * device)362 int32_t Wm8904DaiStart(const struct AudioCard *card, const struct DaiDevice *device)
363 {
364 (void)card;
365 (void)device;
366 return HDF_SUCCESS;
367 }
368
Wm8904DaiDevInit(struct AudioCard * card,const struct DaiDevice * device)369 int32_t Wm8904DaiDevInit(struct AudioCard *card, const struct DaiDevice *device)
370 {
371 if (device == NULL || device->devDaiName == NULL) {
372 WM8904_CODEC_LOG_ERR("input para is NULL.");
373 return HDF_FAILURE;
374 }
375 (void)card;
376 return HDF_SUCCESS;
377 }
378
379