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