1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-12-05 zylx The first version for STM32F4xx
9 * 2019-4-25 misonyo port to IMXRT
10 */
11 #include <rtthread.h>
12 #include <rtdevice.h>
13
14 #include "bsp_wm8960.h"
15 #include <stdlib.h>
16 #include <drv_log.h>
17 #include <rthw.h>
18 static rt_uint16_t wm8960_regval_tbl[56] = {
19 0x0097, 0x0097, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x000a, 0x01c0, 0x0000, 0x00ff, 0x00ff, 0x0000, 0x0000,
20 0x0000, 0x0000, 0x0000, 0x007b, 0x0100, 0x0032, 0x0000, 0x00c3, 0x00c3, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000,
21 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0050, 0x0050, 0x0050, 0x0050, 0x0000, 0x0000, 0x0000, 0x0000,
22 0x0040, 0x0000, 0x0000, 0x0050, 0x0050, 0x0000, 0x0002, 0x0037, 0x004d, 0x0080, 0x0008, 0x0031, 0x0026, 0x00e9,
23 };
24 static rt_uint16_t reg_cache[WM8960_CACHEREGNUM];
wm8960_write_reg(struct rt_i2c_bus_device * dev,rt_uint8_t reg,rt_uint16_t val)25 static void wm8960_write_reg(struct rt_i2c_bus_device *dev, rt_uint8_t reg, rt_uint16_t val)
26 {
27 struct rt_i2c_msg msg;
28 rt_uint8_t send_buffer[2];
29 RT_ASSERT(dev != RT_NULL);
30 /* store temp */
31 rt_uint16_t buff = val;
32 reg_cache[reg] = buff;
33 send_buffer[0] = (reg << 1) | ((val >> 8U) & 0x0001U);
34 send_buffer[1] = (rt_uint8_t)(val & 0xFF);
35 msg.addr = 0x1A;////WM8960_I2C_ADDR 0x1A
36 msg.flags = RT_I2C_WR;
37 msg.len = 2;
38 msg.buf = send_buffer;
39 rt_i2c_transfer(dev, &msg, 1);
40 }
wm8960_read_reg(struct rt_i2c_bus_device * dev,rt_uint8_t reg,rt_uint16_t * val)41 static void wm8960_read_reg(struct rt_i2c_bus_device *dev, rt_uint8_t reg, rt_uint16_t *val)
42 {
43 *val = reg_cache[reg];
44 }
45
wm8960_modify_reg(struct rt_i2c_bus_device * dev,rt_uint8_t reg,rt_uint16_t mask,rt_uint16_t val)46 static void wm8960_modify_reg(struct rt_i2c_bus_device *dev, rt_uint8_t reg, rt_uint16_t mask, rt_uint16_t val)
47 {
48 uint16_t reg_val = 0;
49 wm8960_read_reg(dev, reg, ®_val);
50 reg_val &= (rt_uint16_t)~mask;
51 reg_val |= val;
52
53 wm8960_write_reg(dev, reg, reg_val);
54 }
WM8960_SetMasterSlave(struct rt_i2c_bus_device * dev,rt_bool_t master)55 void WM8960_SetMasterSlave(struct rt_i2c_bus_device *dev, rt_bool_t master)
56 {
57 if (master == 1)
58 {
59 wm8960_modify_reg(dev, WM8960_IFACE1, WM8960_IFACE1_MS_MASK, WM8960_IFACE1_MS(WM8960_IFACE1_MASTER));
60 }
61 else
62 {
63 wm8960_modify_reg(dev, WM8960_IFACE1, WM8960_IFACE1_MS_MASK, WM8960_IFACE1_MS(WM8960_IFACE1_SLAVE));
64 }
65 }
66
WM8960_SetModule(struct rt_i2c_bus_device * dev,wm8960_module_t module,rt_bool_t isEnabled)67 void WM8960_SetModule(struct rt_i2c_bus_device *dev, wm8960_module_t module, rt_bool_t isEnabled)
68 {
69 switch (module)
70 {
71 case kWM8960_ModuleADC:
72 wm8960_modify_reg(dev, WM8960_POWER1, WM8960_POWER1_ADCL_MASK,
73 ((uint16_t)isEnabled << WM8960_POWER1_ADCL_SHIFT));
74 wm8960_modify_reg(dev, WM8960_POWER1, WM8960_POWER1_ADCR_MASK,
75 ((uint16_t)isEnabled << WM8960_POWER1_ADCR_SHIFT));
76 break;
77 case kWM8960_ModuleDAC:
78 wm8960_modify_reg(dev, WM8960_POWER2, WM8960_POWER2_DACL_MASK,
79 ((uint16_t)isEnabled << WM8960_POWER2_DACL_SHIFT));
80 wm8960_modify_reg(dev, WM8960_POWER2, WM8960_POWER2_DACR_MASK,
81 ((uint16_t)isEnabled << WM8960_POWER2_DACR_SHIFT));
82 break;
83 case kWM8960_ModuleVREF:
84 wm8960_modify_reg(dev, WM8960_POWER1, WM8960_POWER1_VREF_MASK,
85 ((uint16_t)isEnabled << WM8960_POWER1_VREF_SHIFT));
86 break;
87 case kWM8960_ModuleLineIn:
88 wm8960_modify_reg(dev, WM8960_POWER1, WM8960_POWER1_AINL_MASK,
89 ((uint16_t)isEnabled << WM8960_POWER1_AINL_SHIFT));
90 wm8960_modify_reg(dev, WM8960_POWER1, WM8960_POWER1_AINR_MASK,
91 ((uint16_t)isEnabled << WM8960_POWER1_AINR_SHIFT));
92 break;
93 case kWM8960_ModuleLineOut:
94 wm8960_modify_reg(dev, WM8960_POWER2, WM8960_POWER2_LOUT1_MASK,
95 ((uint16_t)isEnabled << WM8960_POWER2_LOUT1_SHIFT));
96 wm8960_modify_reg(dev, WM8960_POWER2, WM8960_POWER2_ROUT1_MASK,
97 ((uint16_t)isEnabled << WM8960_POWER2_ROUT1_SHIFT));
98 break;
99 case kWM8960_ModuleMICB:
100 wm8960_modify_reg(dev, WM8960_POWER1, WM8960_POWER1_MICB_MASK,
101 ((uint16_t)isEnabled << WM8960_POWER1_MICB_SHIFT));
102 break;
103 case kWM8960_ModuleSpeaker:
104 wm8960_modify_reg(dev, WM8960_POWER2, WM8960_POWER2_SPKL_MASK,
105 ((uint16_t)isEnabled << WM8960_POWER2_SPKL_SHIFT));
106 wm8960_modify_reg(dev, WM8960_POWER2, WM8960_POWER2_SPKR_MASK,
107 ((uint16_t)isEnabled << WM8960_POWER2_SPKR_SHIFT));
108 wm8960_write_reg(dev, WM8960_CLASSD1, 0xF7);
109 break;
110 case kWM8960_ModuleMIC:
111 wm8960_modify_reg(dev, WM8960_POWER3, WM8960_POWER3_LMIC_MASK,
112 ((uint16_t)isEnabled << WM8960_POWER3_LMIC_SHIFT));
113 wm8960_modify_reg(dev, WM8960_POWER3, WM8960_POWER3_RMIC_MASK,
114 ((uint16_t)isEnabled << WM8960_POWER3_RMIC_SHIFT));
115 break;
116 case kWM8960_ModuleOMIX:
117 wm8960_modify_reg(dev, WM8960_POWER3, WM8960_POWER3_LOMIX_MASK,
118 ((uint16_t)isEnabled << WM8960_POWER3_LOMIX_SHIFT));
119 wm8960_modify_reg(dev, WM8960_POWER3, WM8960_POWER3_ROMIX_MASK,
120 ((uint16_t)isEnabled << WM8960_POWER3_ROMIX_SHIFT));
121 break;
122 default:
123 break;
124 }
125 }
126
WM8960_SetDataRoute(struct rt_i2c_bus_device * dev,wm8960_route_t route)127 void WM8960_SetDataRoute(struct rt_i2c_bus_device *dev, wm8960_route_t route)
128 {
129 switch (route)
130 {
131 case kWM8960_RouteBypass:
132 /* Bypass means from line-in to HP*/
133 /*
134 * Left LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
135 */
136 wm8960_write_reg(dev, WM8960_LOUTMIX, 0x80);
137
138 /*
139 * Right RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
140 */
141 wm8960_write_reg(dev, WM8960_ROUTMIX, 0x80);
142 break;
143 case kWM8960_RoutePlayback:
144 /* Data route I2S_IN-> DAC-> HP */
145 /*
146 * Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
147 */
148 wm8960_write_reg(dev, WM8960_LOUTMIX, 0x100);
149
150 /*
151 * Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
152 */
153 wm8960_write_reg(dev, WM8960_ROUTMIX, 0x100);
154 wm8960_write_reg(dev, WM8960_POWER3, 0x0C);
155 /* Set power for DAC */
156 WM8960_SetModule(dev, kWM8960_ModuleDAC, RT_TRUE);
157 WM8960_SetModule(dev, kWM8960_ModuleOMIX, RT_TRUE);
158 WM8960_SetModule(dev, kWM8960_ModuleLineOut, RT_TRUE);
159 break;
160 case kWM8960_RoutePlaybackandRecord:
161 /*
162 * Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
163 */
164 wm8960_write_reg(dev, WM8960_LOUTMIX, 0x100);
165
166 /*
167 * Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
168 */
169 wm8960_write_reg(dev, WM8960_ROUTMIX, 0x100);
170 wm8960_write_reg(dev, WM8960_POWER3, 0x3C);
171 WM8960_SetModule(dev, kWM8960_ModuleDAC, RT_TRUE);
172 WM8960_SetModule(dev, kWM8960_ModuleADC, RT_TRUE);
173 WM8960_SetModule(dev, kWM8960_ModuleLineIn, RT_TRUE);
174 WM8960_SetModule(dev, kWM8960_ModuleOMIX, RT_TRUE);
175 WM8960_SetModule(dev, kWM8960_ModuleLineOut, RT_TRUE);
176 break;
177 case kWM8960_RouteRecord:
178 /* LINE_IN->ADC->I2S_OUT */
179 /*
180 * Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
181 */
182 wm8960_write_reg(dev, WM8960_POWER3, 0x30);
183 /* Power up ADC and AIN */
184 WM8960_SetModule(dev, kWM8960_ModuleLineIn, RT_TRUE);
185 WM8960_SetModule(dev, kWM8960_ModuleADC, RT_TRUE);
186 break;
187 default:
188 break;
189 }
190 }
191
WM8960_SetLeftInput(struct rt_i2c_bus_device * dev,wm8960_input_t input)192 void WM8960_SetLeftInput(struct rt_i2c_bus_device *dev, wm8960_input_t input)
193 {
194 uint16_t val = 0;
195
196 switch (input)
197 {
198 case kWM8960_InputSingleEndedMic:
199 /* Only LMN1 enabled, LMICBOOST to 13db, LMIC2B enabled */
200 wm8960_read_reg(dev,WM8960_POWER1, &val);
201 val |= (WM8960_POWER1_AINL_MASK | WM8960_POWER1_ADCL_MASK | WM8960_POWER1_MICB_MASK);
202 wm8960_write_reg(dev, WM8960_POWER1, val);
203 wm8960_write_reg(dev, WM8960_LINPATH, 0x138);
204 wm8960_write_reg(dev, WM8960_LINVOL, 0x117);
205 break;
206 case kWM8960_InputDifferentialMicInput2:
207 wm8960_read_reg(dev,WM8960_POWER1, &val);
208 val |= (WM8960_POWER1_AINL_MASK | WM8960_POWER1_ADCL_MASK | WM8960_POWER1_MICB_MASK);
209 wm8960_write_reg(dev, WM8960_POWER1, val);
210 wm8960_write_reg(dev, WM8960_LINPATH, 0x178);
211 wm8960_write_reg(dev, WM8960_LINVOL, 0x117);
212 break;
213 case kWM8960_InputDifferentialMicInput3:
214 wm8960_read_reg(dev,WM8960_POWER1, &val);
215 val |= (WM8960_POWER1_AINL_MASK | WM8960_POWER1_ADCL_MASK | WM8960_POWER1_MICB_MASK);
216 wm8960_write_reg(dev, WM8960_POWER1, val);
217 wm8960_write_reg(dev, WM8960_LINPATH, 0x1B8);
218 wm8960_write_reg(dev, WM8960_LINVOL, 0x117);
219 break;
220 case kWM8960_InputLineINPUT2:
221 wm8960_read_reg(dev,WM8960_POWER1, &val);
222 val |= (WM8960_POWER1_AINL_MASK | WM8960_POWER1_ADCL_MASK);
223 wm8960_write_reg(dev, WM8960_POWER1, val);
224 wm8960_read_reg(dev,WM8960_INBMIX1, &val);
225 val |= 0xE;
226 wm8960_write_reg(dev, WM8960_INBMIX1, val);
227 break;
228 case kWM8960_InputLineINPUT3:
229 wm8960_read_reg(dev,WM8960_POWER1, &val);
230 val |= (WM8960_POWER1_AINL_MASK | WM8960_POWER1_ADCL_MASK);
231 wm8960_write_reg(dev, WM8960_POWER1, val);
232 wm8960_read_reg(dev,WM8960_INBMIX1, &val);
233 val |= 0x70;
234 wm8960_write_reg(dev, WM8960_INBMIX1, val);
235 break;
236 default:
237 break;
238 }
239 }
240
WM8960_SetRightInput(struct rt_i2c_bus_device * dev,wm8960_input_t input)241 void WM8960_SetRightInput(struct rt_i2c_bus_device *dev, wm8960_input_t input)
242 {
243 uint16_t val = 0;
244
245 switch (input)
246 {
247 case kWM8960_InputSingleEndedMic:
248 /* Only LMN1 enabled, LMICBOOST to 13db, LMIC2B enabled */
249 wm8960_read_reg(dev,WM8960_POWER1, &val);
250 val |= (WM8960_POWER1_AINR_MASK | WM8960_POWER1_ADCR_MASK | WM8960_POWER1_MICB_MASK);
251 wm8960_write_reg(dev, WM8960_POWER1, val);
252 wm8960_write_reg(dev, WM8960_RINPATH, 0x138);
253 wm8960_write_reg(dev, WM8960_RINVOL, 0x117);
254 break;
255 case kWM8960_InputDifferentialMicInput2:
256 wm8960_read_reg(dev,WM8960_POWER1, &val);
257 val |= (WM8960_POWER1_AINR_MASK | WM8960_POWER1_ADCR_MASK | WM8960_POWER1_MICB_MASK);
258 wm8960_write_reg(dev, WM8960_POWER1, val);
259 wm8960_write_reg(dev, WM8960_RINPATH, 0x178);
260 wm8960_write_reg(dev, WM8960_RINVOL, 0x117);
261 break;
262 case kWM8960_InputDifferentialMicInput3:
263 wm8960_read_reg(dev,WM8960_POWER1, &val);
264 val |= (WM8960_POWER1_AINR_MASK | WM8960_POWER1_ADCR_MASK | WM8960_POWER1_MICB_MASK);
265 wm8960_write_reg(dev, WM8960_POWER1, val);
266 wm8960_write_reg(dev, WM8960_RINPATH, 0x1B8);
267 wm8960_write_reg(dev, WM8960_RINVOL, 0x117);
268 break;
269 case kWM8960_InputLineINPUT2:
270 wm8960_read_reg(dev,WM8960_POWER1, &val);
271 val |= (WM8960_POWER1_AINR_MASK | WM8960_POWER1_ADCR_MASK);
272 wm8960_write_reg(dev, WM8960_POWER1, val);
273 wm8960_read_reg(dev,WM8960_INBMIX2, &val);
274 val |= 0xE;
275 wm8960_write_reg(dev, WM8960_INBMIX2, val);
276 break;
277 case kWM8960_InputLineINPUT3:
278 wm8960_read_reg(dev,WM8960_POWER1, &val);
279 val |= (WM8960_POWER1_AINR_MASK | WM8960_POWER1_ADCR_MASK);
280 wm8960_write_reg(dev, WM8960_POWER1, val);
281 wm8960_read_reg(dev,WM8960_INBMIX2, &val);
282 val |= 0x70;
283 wm8960_write_reg(dev, WM8960_INBMIX2, val);
284 break;
285 default:
286 break;
287 }
288 }
289
WM8960_SetProtocol(struct rt_i2c_bus_device * dev,wm8960_protocol_t protocol)290 void WM8960_SetProtocol(struct rt_i2c_bus_device *dev, wm8960_protocol_t protocol)
291 {
292 wm8960_modify_reg(dev, WM8960_IFACE1, WM8960_IFACE1_FORMAT_MASK | WM8960_IFACE1_LRP_MASK, protocol);
293 }
294
WM8960_SetVolume(struct rt_i2c_bus_device * dev,wm8960_module_t module,rt_uint32_t volume)295 void WM8960_SetVolume(struct rt_i2c_bus_device *dev, wm8960_module_t module, rt_uint32_t volume)
296 {
297 uint16_t vol = 0;
298 switch (module)
299 {
300 case kWM8960_ModuleADC:
301 vol = volume;
302 wm8960_write_reg(dev, WM8960_LADC, vol);
303 wm8960_write_reg(dev, WM8960_RADC, vol);
304 /* Update volume */
305 vol = 0x100 | volume;
306 wm8960_write_reg(dev, WM8960_LADC, vol);
307 wm8960_write_reg(dev, WM8960_RADC, vol);
308 break;
309 case kWM8960_ModuleDAC:
310 vol = volume;
311 wm8960_write_reg(dev, WM8960_LDAC, vol);
312 wm8960_write_reg(dev, WM8960_RDAC, vol);
313 vol = 0x100 | volume;
314 wm8960_write_reg(dev, WM8960_LDAC, vol);
315 wm8960_write_reg(dev, WM8960_RDAC, vol);
316 break;
317 case kWM8960_ModuleHP:
318 vol = volume;
319 wm8960_write_reg(dev, WM8960_LOUT1, vol);
320 wm8960_write_reg(dev, WM8960_ROUT1, vol);
321 vol = 0x100 | volume;
322 wm8960_write_reg(dev, WM8960_LOUT1, vol);
323 wm8960_write_reg(dev, WM8960_ROUT1, vol);
324 break;
325 case kWM8960_ModuleLineIn:
326 vol = volume;
327 wm8960_write_reg(dev, WM8960_LINVOL, vol);
328 wm8960_write_reg(dev, WM8960_RINVOL, vol);
329 vol = 0x100 | volume;
330 wm8960_write_reg(dev, WM8960_LINVOL, vol);
331 wm8960_write_reg(dev, WM8960_RINVOL, vol);
332 break;
333 case kWM8960_ModuleSpeaker:
334 vol = volume;
335 wm8960_write_reg(dev, WM8960_LOUT2, vol);
336 wm8960_write_reg(dev, WM8960_ROUT2, vol);
337 vol = 0x100 | volume;
338 wm8960_write_reg(dev, WM8960_LOUT2, vol);
339 wm8960_write_reg(dev, WM8960_ROUT2, vol);
340 break;
341 default:
342 break;
343 }
344 }
345
WM8960_GetVolume(struct rt_i2c_bus_device * dev,wm8960_module_t module)346 rt_uint32_t WM8960_GetVolume(struct rt_i2c_bus_device *dev, wm8960_module_t module)
347 {
348 uint16_t vol = 0;
349 switch (module)
350 {
351 case kWM8960_ModuleADC:
352 wm8960_read_reg(dev,WM8960_LADC, &vol);
353 vol &= 0xFF;
354 break;
355 case kWM8960_ModuleDAC:
356 wm8960_read_reg(dev,WM8960_LDAC, &vol);
357 vol &= 0xFF;
358 break;
359 case kWM8960_ModuleHP:
360 wm8960_read_reg(dev,WM8960_LOUT1, &vol);
361 vol &= 0x7F;
362 break;
363 case kWM8960_ModuleLineOut:
364 wm8960_read_reg(dev,WM8960_LINVOL, &vol);
365 vol &= 0x3F;
366 break;
367 default:
368 vol = 0;
369 break;
370 }
371 return vol;
372 }
373
WM8960_SetMute(struct rt_i2c_bus_device * dev,wm8960_module_t module,rt_bool_t isEnabled)374 void WM8960_SetMute(struct rt_i2c_bus_device *dev, wm8960_module_t module, rt_bool_t isEnabled)
375 {
376 switch (module)
377 {
378 case kWM8960_ModuleADC:
379 /*
380 * Digital Mute
381 */
382 if (isEnabled)
383 {
384 wm8960_write_reg(dev, WM8960_LADC, 0x100);
385 wm8960_write_reg(dev, WM8960_RADC, 0x100);
386 }
387 else
388 {
389 wm8960_write_reg(dev, WM8960_LADC, 0x1C3);
390 wm8960_write_reg(dev, WM8960_RADC, 0x1C3);
391 }
392 break;
393 case kWM8960_ModuleDAC:
394 /*
395 * Digital mute
396 */
397 if (isEnabled)
398 {
399 wm8960_write_reg(dev, WM8960_LDAC, 0x100);
400 wm8960_write_reg(dev, WM8960_RDAC, 0x100);
401 }
402 else
403 {
404 wm8960_write_reg(dev, WM8960_LDAC, 0x1FF);
405 wm8960_write_reg(dev, WM8960_RDAC, 0x1FF);
406 }
407 break;
408 case kWM8960_ModuleHP:
409 /*
410 * Analog mute
411 */
412 if (isEnabled)
413 {
414 wm8960_write_reg(dev, WM8960_LOUT1, 0x100);
415 wm8960_write_reg(dev, WM8960_ROUT1, 0x100);
416 }
417 else
418 {
419 wm8960_write_reg(dev, WM8960_LOUT1, 0x16F);
420 wm8960_write_reg(dev, WM8960_ROUT1, 0x16F);
421 }
422 break;
423
424 case kWM8960_ModuleSpeaker:
425 if (isEnabled)
426 {
427 wm8960_write_reg(dev, WM8960_LOUT2, 0x100);
428 wm8960_write_reg(dev, WM8960_ROUT2, 0x100);
429 }
430 else
431 {
432 wm8960_write_reg(dev, WM8960_LOUT2, 0x16F);
433 wm8960_write_reg(dev, WM8960_ROUT2, 0x16f);
434 }
435 break;
436
437 case kWM8960_ModuleLineOut:
438 break;
439 default:
440 break;
441 }
442 }
443
WM8960_ConfigDataFormat(struct rt_i2c_bus_device * dev,rt_uint32_t sysclk,rt_uint32_t sample_rate,rt_uint32_t bits)444 void WM8960_ConfigDataFormat(struct rt_i2c_bus_device *dev, rt_uint32_t sysclk, rt_uint32_t sample_rate, rt_uint32_t bits)
445 {
446 uint32_t divider = 0;
447 uint16_t val = 0;
448
449 /* Compute sample rate divider, dac and adc are the same sample rate */
450 divider = sysclk / sample_rate;
451 if (divider == 256)
452 {
453 val = 0;
454 }
455 if (divider > 256)
456 {
457 val = (((divider / 256U) << 6U) | ((divider / 256U) << 3U));
458 }
459
460 wm8960_write_reg(dev, WM8960_CLOCK1, val);
461
462 /* Compute bclk divider */
463 divider /= bits * 2;
464 switch (divider)
465 {
466 case 4:
467 case 5:
468 case 6:
469 val = (0x1C0 | divider);
470 break;
471 case 8:
472 val = 0x1C7;
473 break;
474 case 11:
475 val = 0x1C8;
476 break;
477 case 12:
478 val = 0x1C9;
479 break;
480 case 16:
481 val = 0x1CA;
482 break;
483 case 22:
484 val = 0x1CB;
485 break;
486 case 24:
487 val = 0x1CC;
488 break;
489 case 32:
490 val = 0x1CF;
491 break;
492 default:
493 break;
494
495 }
496
497 wm8960_write_reg(dev, WM8960_CLOCK2, val);
498 /*
499 * Slave mode (MS = 0), LRP = 0, 32bit WL, left justified (FORMAT[1:0]=0b01)
500 */
501 switch (bits)
502 {
503 case 16:
504 wm8960_modify_reg(dev, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
505 WM8960_IFACE1_WL(WM8960_IFACE1_WL_16BITS));
506 break;
507 case 20:
508 wm8960_modify_reg(dev, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
509 WM8960_IFACE1_WL(WM8960_IFACE1_WL_20BITS));
510 break;
511 case 24:
512 wm8960_modify_reg(dev, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
513 WM8960_IFACE1_WL(WM8960_IFACE1_WL_24BITS));
514 break;
515 case 32:
516 wm8960_modify_reg(dev, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
517 WM8960_IFACE1_WL(WM8960_IFACE1_WL_32BITS));
518 break;
519 default:
520 break;
521 }
522 }
523
WM8960_Deinit(struct rt_i2c_bus_device * dev)524 void WM8960_Deinit(struct rt_i2c_bus_device *dev)
525 {
526 WM8960_SetModule(dev, kWM8960_ModuleADC, RT_FALSE);
527 WM8960_SetModule(dev, kWM8960_ModuleDAC, RT_FALSE);
528 WM8960_SetModule(dev, kWM8960_ModuleVREF, RT_FALSE);
529 WM8960_SetModule(dev, kWM8960_ModuleLineIn, RT_FALSE);
530 WM8960_SetModule(dev, kWM8960_ModuleLineOut, RT_FALSE);
531 WM8960_SetModule(dev, kWM8960_ModuleSpeaker, RT_FALSE);
532 }
533
WM8960_init(struct rt_i2c_bus_device * dev,wm8960_config_t * wm8960Config)534 void WM8960_init(struct rt_i2c_bus_device *dev, wm8960_config_t *wm8960Config)
535 {
536 wm8960_config_t *config = wm8960Config;
537 rt_memcpy(reg_cache, wm8960_regval_tbl, sizeof(wm8960_regval_tbl));
538 /* Reset the codec */
539 wm8960_write_reg(dev, WM8960_RESET, 0x00);
540 /*
541 * VMID=50K, Enable VREF, AINL, AINR, ADCL and ADCR
542 * I2S_IN (bit 0), I2S_OUT (bit 1), DAP (bit 4), DAC (bit 5), ADC (bit 6) are powered on
543 */
544 wm8960_write_reg(dev, WM8960_POWER1, 0xFE);
545 /*
546 * Enable DACL, DACR, LOUT1, ROUT1, PLL down
547 */
548 wm8960_write_reg(dev, WM8960_POWER2, 0x1E0);
549 /*
550 * Enable left and right channel input PGA, left and right output mixer
551 */
552 wm8960_write_reg(dev, WM8960_POWER3, 0x3C);
553 /* ADC and DAC uses same clock */
554 wm8960_write_reg(dev, WM8960_IFACE2, 0x40);
555 /* set data route */
556 WM8960_SetDataRoute(dev, config->route);
557 /* set data protocol */
558 WM8960_SetProtocol(dev, config->bus);
559 /* set master or slave */
560 WM8960_SetMasterSlave(dev, config->master_slave);
561 /* select left input */
562 WM8960_SetLeftInput(dev, config->leftInputSource);
563 /* select right input */
564 WM8960_SetRightInput(dev, config->rightInputSource);
565 /* speaker power */
566 if (config->enableSpeaker)
567 {
568 WM8960_SetModule(dev, kWM8960_ModuleSpeaker, RT_TRUE);
569 }
570 wm8960_write_reg(dev, WM8960_ADDCTL1, 0x0C0);
571 wm8960_write_reg(dev, WM8960_ADDCTL4, 0x40);
572
573 wm8960_write_reg(dev, WM8960_BYPASS1, 0x0);
574 wm8960_write_reg(dev, WM8960_BYPASS2, 0x0);
575 /*
576 * ADC volume, 0dB
577 */
578 wm8960_write_reg(dev, WM8960_LADC, 0x1C3);
579 wm8960_write_reg(dev, WM8960_RADC, 0x1C3);
580
581 /*
582 * Digital DAC volume, 0dB
583 */
584 wm8960_write_reg(dev, WM8960_LDAC, 0x1E0);
585 wm8960_write_reg(dev, WM8960_RDAC, 0x1E0);
586
587 /*
588 * Headphone volume, LOUT1 and ROUT1, 0dB
589 */
590 wm8960_write_reg(dev, WM8960_LOUT1, 0x16F);
591 wm8960_write_reg(dev, WM8960_ROUT1, 0x16F);
592
593 /* Unmute DAC. */
594 wm8960_write_reg(dev, WM8960_DACCTL1, 0x0000);
595 wm8960_write_reg(dev, WM8960_LINVOL, 0x117);
596 wm8960_write_reg(dev, WM8960_RINVOL, 0x117);
597
598 WM8960_ConfigDataFormat(dev, config->format.mclk_HZ, config->format.sampleRate, config->format.bitWidth);
599 }
WM8960_SetPlay(struct rt_i2c_bus_device * dev,uint32_t playSource)600 void WM8960_SetPlay(struct rt_i2c_bus_device *dev, uint32_t playSource)
601 {
602 if (kWM8960_PlaySourcePGA & playSource)
603 {
604 wm8960_modify_reg(dev, WM8960_BYPASS1, 0x80U, 0x80U);
605 wm8960_modify_reg(dev, WM8960_BYPASS2, 0x80U, 0x80U);
606 wm8960_modify_reg(dev, WM8960_LOUTMIX, 0x180U, 0U);
607 wm8960_modify_reg(dev, WM8960_ROUTMIX, 0x180U, 0U);
608 }
609
610 if (playSource & kWM8960_PlaySourceDAC)
611 {
612 wm8960_modify_reg(dev, WM8960_BYPASS1, 0x80U, 0x00U);
613 wm8960_modify_reg(dev, WM8960_BYPASS2, 0x80U, 0x00U);
614 wm8960_modify_reg(dev, WM8960_LOUTMIX, 0x180U, 0x100U);
615 wm8960_modify_reg(dev, WM8960_ROUTMIX, 0x180U, 0x100U);
616 }
617
618 if (playSource & kWM8960_PlaySourceInput)
619 {
620 wm8960_modify_reg(dev, WM8960_BYPASS1, 0x80U, 0x0U);
621 wm8960_modify_reg(dev, WM8960_BYPASS2, 0x80U, 0x0U);
622 wm8960_modify_reg(dev, WM8960_LOUTMIX, 0x180U, 0x80U);
623 wm8960_modify_reg(dev, WM8960_ROUTMIX, 0x180U, 0x80U);
624 }
625 }
626