diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/components/codec/cs42888/fsl_cs42888.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/components/codec/cs42888/fsl_cs42888.c | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/components/codec/cs42888/fsl_cs42888.c b/lib/chibios-contrib/ext/mcux-sdk/components/codec/cs42888/fsl_cs42888.c new file mode 100644 index 000000000..59753998d --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/components/codec/cs42888/fsl_cs42888.c | |||
@@ -0,0 +1,494 @@ | |||
1 | /* | ||
2 | * Copyright 2017-2019 NXP | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | */ | ||
8 | #include "fsl_cs42888.h" | ||
9 | /******************************************************************************* | ||
10 | * Definitations | ||
11 | ******************************************************************************/ | ||
12 | #define CLOCK_RATE_IN_RANGE(x, min, max) (((x) > (min)) && ((x) < (max))) | ||
13 | /*! @brief CS42888 ms counter*/ | ||
14 | #ifndef CS42888_MS_COUNTER | ||
15 | #define CS42888_MS_COUNTER 200000U /* 1ms under 200MHZ core clock */ | ||
16 | #endif | ||
17 | |||
18 | /******************************************************************************* | ||
19 | * Prototypes | ||
20 | ******************************************************************************/ | ||
21 | /*! | ||
22 | * @brief Set CS42888 reset function. | ||
23 | * | ||
24 | * @param handle CS42888 handle structure. | ||
25 | * @param codecReset reset pin control function pointer. | ||
26 | */ | ||
27 | static void CS42888_Reset(cs42888_handle_t *handle, cs42888_reset codecReset); | ||
28 | |||
29 | /*! | ||
30 | *@brief cs42888 ms delay function. | ||
31 | * | ||
32 | * @param ms ms to delay. | ||
33 | */ | ||
34 | static void CS42888_DelayMs(uint32_t ms); | ||
35 | /******************************************************************************* | ||
36 | * Variables | ||
37 | ******************************************************************************/ | ||
38 | |||
39 | /******************************************************************************* | ||
40 | * Code | ||
41 | ******************************************************************************/ | ||
42 | static void CS42888_DelayMs(uint32_t ms) | ||
43 | { | ||
44 | uint32_t i = 0U, j = 0U; | ||
45 | |||
46 | for (i = 0U; i < ms; i++) | ||
47 | { | ||
48 | for (j = 0U; j < CS42888_MS_COUNTER; j++) | ||
49 | { | ||
50 | __NOP(); | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | status_t CS42888_Init(cs42888_handle_t *handle, cs42888_config_t *config) | ||
55 | { | ||
56 | assert(handle != NULL); | ||
57 | assert(config != NULL); | ||
58 | |||
59 | uint8_t i = 0; | ||
60 | status_t errorStatus = kStatus_Success; | ||
61 | |||
62 | handle->config = config; | ||
63 | |||
64 | /* i2c bus initialization */ | ||
65 | errorStatus = CODEC_I2C_Init(handle->i2cHandle, config->i2cConfig.codecI2CInstance, CS42888_I2C_BITRATE, | ||
66 | config->i2cConfig.codecI2CSourceClock); | ||
67 | if (errorStatus != (status_t)kStatus_HAL_I2cSuccess) | ||
68 | { | ||
69 | return errorStatus; | ||
70 | } | ||
71 | |||
72 | /* reset codec firstly */ | ||
73 | CS42888_Reset(handle, ((cs42888_config_t *)config)->reset); | ||
74 | |||
75 | errorStatus = CS42888_WriteReg(handle, CS42888_POWER_CONTROL, 0x7F); | ||
76 | if (errorStatus != kStatus_Success) | ||
77 | { | ||
78 | return errorStatus; | ||
79 | } | ||
80 | |||
81 | if (!config->master) | ||
82 | { | ||
83 | /* set as slave */ | ||
84 | errorStatus = CS42888_SelectFunctionalMode(handle, kCS42888_ModeSlave, kCS42888_ModeSlave); | ||
85 | if (errorStatus != kStatus_Success) | ||
86 | { | ||
87 | return errorStatus; | ||
88 | } | ||
89 | } | ||
90 | else | ||
91 | { | ||
92 | /* set as master */ | ||
93 | errorStatus = CS42888_SelectFunctionalMode(handle, config->ADCMode, config->DACMode); | ||
94 | if (errorStatus != kStatus_Success) | ||
95 | { | ||
96 | return errorStatus; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* set protocol */ | ||
101 | errorStatus = CS42888_SetProtocol(handle, config->bus, config->format.bitWidth); | ||
102 | if (errorStatus != kStatus_Success) | ||
103 | { | ||
104 | return errorStatus; | ||
105 | } | ||
106 | /* set data format */ | ||
107 | errorStatus = | ||
108 | CS42888_ConfigDataFormat(handle, config->format.mclk_HZ, config->format.sampleRate, config->format.bitWidth); | ||
109 | if (errorStatus != kStatus_Success) | ||
110 | { | ||
111 | return errorStatus; | ||
112 | } | ||
113 | /*Mute all DACs*/ | ||
114 | errorStatus = CS42888_WriteReg(handle, CS42888_CHANNEL_MUTE, 0xFF); | ||
115 | if (errorStatus != kStatus_Success) | ||
116 | { | ||
117 | return errorStatus; | ||
118 | } | ||
119 | /*Set PDN as 0*/ | ||
120 | errorStatus = CS42888_WriteReg(handle, CS42888_POWER_CONTROL, 0x0); | ||
121 | if (errorStatus != kStatus_Success) | ||
122 | { | ||
123 | return errorStatus; | ||
124 | } | ||
125 | errorStatus = CS42888_WriteReg(handle, CS42888_TRANSITION_CONTROL, 0x10); | ||
126 | if (errorStatus != kStatus_Success) | ||
127 | { | ||
128 | return errorStatus; | ||
129 | } | ||
130 | /* Configure the codec AIN volume to 8db */ | ||
131 | for (i = 1; i <= 4U; i++) | ||
132 | { | ||
133 | errorStatus = CS42888_SetAINVolume(handle, i, 16); | ||
134 | if (errorStatus != kStatus_Success) | ||
135 | { | ||
136 | return errorStatus; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | /*Delay and unmute*/ | ||
141 | return CS42888_WriteReg(handle, CS42888_CHANNEL_MUTE, 0x0); | ||
142 | } | ||
143 | |||
144 | status_t CS42888_SelectFunctionalMode(cs42888_handle_t *handle, cs42888_func_mode adcMode, cs42888_func_mode dacMode) | ||
145 | { | ||
146 | if (CS42888_ModifyReg(handle, CS42888_FUNCTIONAL_MODE, CS42888_FUNCTIONAL_MODE_DAC_FM_MASK, | ||
147 | CS42888_FUNCTIONAL_MODE_DAC_FM(dacMode)) == kStatus_Success) | ||
148 | { | ||
149 | return CS42888_ModifyReg(handle, CS42888_FUNCTIONAL_MODE, CS42888_FUNCTIONAL_MODE_ADC_FM_MASK, | ||
150 | CS42888_FUNCTIONAL_MODE_ADC_FM(adcMode)); | ||
151 | } | ||
152 | |||
153 | return kStatus_Fail; | ||
154 | } | ||
155 | |||
156 | void CS42888_SetFuncMode(cs42888_handle_t *handle, cs42888_func_mode mode) | ||
157 | { | ||
158 | (void)CS42888_ModifyReg(handle, CS42888_FUNCTIONAL_MODE, CS42888_FUNCTIONAL_MODE_DAC_FM_MASK, | ||
159 | CS42888_FUNCTIONAL_MODE_DAC_FM(mode)); | ||
160 | (void)CS42888_ModifyReg(handle, CS42888_FUNCTIONAL_MODE, CS42888_FUNCTIONAL_MODE_ADC_FM_MASK, | ||
161 | CS42888_FUNCTIONAL_MODE_ADC_FM(mode)); | ||
162 | } | ||
163 | |||
164 | static void CS42888_Reset(cs42888_handle_t *handle, cs42888_reset codecReset) | ||
165 | { | ||
166 | assert(codecReset != NULL); | ||
167 | |||
168 | /* hold reset 0 */ | ||
169 | codecReset(false); | ||
170 | /* delay 400ms */ | ||
171 | CS42888_DelayMs(400U); | ||
172 | /* hold reset 0 */ | ||
173 | codecReset(true); | ||
174 | } | ||
175 | |||
176 | status_t CS42888_Deinit(cs42888_handle_t *handle) | ||
177 | { | ||
178 | /* Disable all modules making CS42888 enter a low power mode */ | ||
179 | if (CS42888_WriteReg(handle, CS42888_FUNCTIONAL_MODE, 0U) != kStatus_Success) | ||
180 | { | ||
181 | return kStatus_Fail; | ||
182 | } | ||
183 | |||
184 | return CODEC_I2C_Deinit(handle->i2cHandle); | ||
185 | } | ||
186 | |||
187 | status_t CS42888_SetProtocol(cs42888_handle_t *handle, cs42888_bus_t protocol, uint32_t bitWidth) | ||
188 | { | ||
189 | uint8_t format = 0U; | ||
190 | status_t errorStatus = kStatus_Success; | ||
191 | |||
192 | switch (protocol) | ||
193 | { | ||
194 | case kCS42888_BusLeftJustified: | ||
195 | if (bitWidth <= 24U) | ||
196 | { | ||
197 | format = 0U; | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | errorStatus = kStatus_InvalidArgument; | ||
202 | } | ||
203 | break; | ||
204 | |||
205 | case kCS42888_BusI2S: | ||
206 | if (bitWidth <= 24U) | ||
207 | { | ||
208 | format = 0x09U; | ||
209 | } | ||
210 | else | ||
211 | { | ||
212 | errorStatus = kStatus_InvalidArgument; | ||
213 | } | ||
214 | break; | ||
215 | |||
216 | case kCS42888_BusRightJustified: | ||
217 | if (bitWidth == 24U) | ||
218 | { | ||
219 | format = 0x12U; | ||
220 | } | ||
221 | else if (bitWidth == 16U) | ||
222 | { | ||
223 | format = 0x1BU; | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | errorStatus = kStatus_InvalidArgument; | ||
228 | } | ||
229 | break; | ||
230 | |||
231 | case kCS42888_BusOL1: | ||
232 | if (bitWidth == 20U) | ||
233 | { | ||
234 | format = 0x24U; | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | errorStatus = kStatus_InvalidArgument; | ||
239 | } | ||
240 | break; | ||
241 | |||
242 | case kCS42888_BusOL2: | ||
243 | if (bitWidth == 24U) | ||
244 | { | ||
245 | format = 0x2DU; | ||
246 | } | ||
247 | else | ||
248 | { | ||
249 | errorStatus = kStatus_InvalidArgument; | ||
250 | } | ||
251 | break; | ||
252 | |||
253 | case kCS42888_BusTDM: | ||
254 | if (bitWidth == 24U) | ||
255 | { | ||
256 | format = 0x36U; | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | errorStatus = kStatus_InvalidArgument; | ||
261 | } | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | errorStatus = kStatus_InvalidArgument; | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | if (errorStatus == kStatus_Success) | ||
270 | { | ||
271 | errorStatus = CS42888_ModifyReg(handle, CS42888_INTERFACE_FORMATS, 0x3FU, format); | ||
272 | } | ||
273 | |||
274 | return errorStatus; | ||
275 | } | ||
276 | |||
277 | status_t CS42888_ConfigDataFormat(cs42888_handle_t *handle, uint32_t mclk, uint32_t sample_rate, uint32_t bits) | ||
278 | { | ||
279 | status_t retval = kStatus_Success; | ||
280 | |||
281 | uint8_t val = 0; | ||
282 | uint32_t ratio = mclk / sample_rate; | ||
283 | |||
284 | if (CS42888_ReadReg(handle, CS42888_FUNCTIONAL_MODE, &val) != kStatus_Success) | ||
285 | { | ||
286 | return kStatus_Fail; | ||
287 | } | ||
288 | |||
289 | /* clear mfreq field */ | ||
290 | val &= (uint8_t)~0xEU; | ||
291 | |||
292 | switch (ratio) | ||
293 | { | ||
294 | case 64: | ||
295 | assert(CLOCK_RATE_IN_RANGE(sample_rate, 100000U, 200000U)); | ||
296 | assert(CLOCK_RATE_IN_RANGE(mclk, 1029000U, 12800000U)); | ||
297 | break; | ||
298 | |||
299 | case 128: | ||
300 | if (CLOCK_RATE_IN_RANGE(sample_rate, 100000U, 200000U) && CLOCK_RATE_IN_RANGE(mclk, 2048000U, 25600000U)) | ||
301 | { | ||
302 | val |= 4U; | ||
303 | } | ||
304 | break; | ||
305 | |||
306 | case 256: | ||
307 | if (CLOCK_RATE_IN_RANGE(sample_rate, 50000U, 100000U) && CLOCK_RATE_IN_RANGE(mclk, 2048000U, 25600000U)) | ||
308 | { | ||
309 | val |= 4U; | ||
310 | } | ||
311 | |||
312 | if (CLOCK_RATE_IN_RANGE(sample_rate, 100000U, 200000U) && CLOCK_RATE_IN_RANGE(mclk, 4096000U, 51200000U)) | ||
313 | { | ||
314 | val |= 8U; | ||
315 | } | ||
316 | break; | ||
317 | |||
318 | case 512: | ||
319 | if (CLOCK_RATE_IN_RANGE(sample_rate, 4000U, 50000U) && CLOCK_RATE_IN_RANGE(mclk, 2048000U, 25600000U)) | ||
320 | { | ||
321 | val |= 4U; | ||
322 | } | ||
323 | |||
324 | if (CLOCK_RATE_IN_RANGE(sample_rate, 50000U, 100000U) && CLOCK_RATE_IN_RANGE(mclk, 4096000U, 51200000U)) | ||
325 | { | ||
326 | val |= 8U; | ||
327 | } | ||
328 | break; | ||
329 | |||
330 | case 1024: | ||
331 | assert(CLOCK_RATE_IN_RANGE(mclk, 4096000U, 51200000U)); | ||
332 | assert(CLOCK_RATE_IN_RANGE(sample_rate, 4000U, 50000U)); | ||
333 | val |= 8U; | ||
334 | break; | ||
335 | |||
336 | default: | ||
337 | assert(false); | ||
338 | break; | ||
339 | } | ||
340 | |||
341 | retval = CS42888_WriteReg(handle, CS42888_FUNCTIONAL_MODE, val); | ||
342 | |||
343 | return retval; | ||
344 | } | ||
345 | |||
346 | status_t CS42888_SetModule(cs42888_handle_t *handle, cs42888_module_t module, bool isEnabled) | ||
347 | { | ||
348 | status_t ret = kStatus_Success; | ||
349 | uint8_t val = 0; | ||
350 | |||
351 | /* Read Power control register value */ | ||
352 | if (CS42888_ReadReg(handle, CS42888_POWER_CONTROL, &val) != kStatus_Success) | ||
353 | { | ||
354 | return kStatus_Fail; | ||
355 | } | ||
356 | |||
357 | if (isEnabled) | ||
358 | { | ||
359 | val |= (uint8_t)module; | ||
360 | } | ||
361 | else | ||
362 | { | ||
363 | val &= ~(uint8_t)module; | ||
364 | } | ||
365 | |||
366 | ret = CS42888_WriteReg(handle, CS42888_POWER_CONTROL, val); | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | status_t CS42888_SetAOUTVolume(cs42888_handle_t *handle, uint8_t channel, uint8_t volume) | ||
371 | { | ||
372 | status_t ret = kStatus_Success; | ||
373 | uint8_t reg = CS42888_VOL_CONTROL_AOUT1 + (channel - 1U); | ||
374 | |||
375 | if ((channel < 1U) || (channel > 8U)) | ||
376 | { | ||
377 | ret = kStatus_Fail; | ||
378 | } | ||
379 | else | ||
380 | { | ||
381 | ret = CS42888_WriteReg(handle, reg, volume); | ||
382 | } | ||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | status_t CS42888_SetAINVolume(cs42888_handle_t *handle, uint8_t channel, uint8_t volume) | ||
387 | { | ||
388 | status_t ret = kStatus_Success; | ||
389 | uint8_t reg = CS42888_VOL_CONTROL_AIN1 + (channel - 1U); | ||
390 | |||
391 | if ((channel < 1U) || (channel > 4U)) | ||
392 | { | ||
393 | ret = kStatus_Fail; | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | ret = CS42888_WriteReg(handle, reg, volume); | ||
398 | } | ||
399 | return ret; | ||
400 | } | ||
401 | |||
402 | uint8_t CS42888_GetAOUTVolume(cs42888_handle_t *handle, uint8_t channel) | ||
403 | { | ||
404 | uint8_t val = 0; | ||
405 | uint8_t reg = CS42888_VOL_CONTROL_AOUT1 + (channel - 1U); | ||
406 | if ((channel < 1U) || (channel > 8U)) | ||
407 | { | ||
408 | val = 0; | ||
409 | } | ||
410 | else | ||
411 | { | ||
412 | (void)CS42888_ReadReg(handle, reg, &val); | ||
413 | } | ||
414 | return val; | ||
415 | } | ||
416 | |||
417 | uint8_t CS42888_GetAINVolume(cs42888_handle_t *handle, uint8_t channel) | ||
418 | { | ||
419 | uint8_t val = 0; | ||
420 | uint8_t reg = CS42888_VOL_CONTROL_AIN1 + (channel - 1U); | ||
421 | if ((channel < 1U) || (channel > 4U)) | ||
422 | { | ||
423 | val = 0; | ||
424 | } | ||
425 | else | ||
426 | { | ||
427 | (void)CS42888_ReadReg(handle, reg, &val); | ||
428 | } | ||
429 | return val; | ||
430 | } | ||
431 | |||
432 | status_t CS42888_SetMute(cs42888_handle_t *handle, uint8_t channelMask) | ||
433 | { | ||
434 | status_t ret = kStatus_Success; | ||
435 | |||
436 | ret = CS42888_WriteReg(handle, CS42888_CHANNEL_MUTE, channelMask); | ||
437 | return ret; | ||
438 | } | ||
439 | |||
440 | status_t CS42888_SetChannelMute(cs42888_handle_t *handle, uint8_t channel, bool isMute) | ||
441 | { | ||
442 | assert(channel >= (uint8_t)kCS42888_AOUT1); | ||
443 | |||
444 | status_t ret = kStatus_Success; | ||
445 | |||
446 | uint8_t val = 0U; | ||
447 | |||
448 | ret = CS42888_ReadReg(handle, CS42888_CHANNEL_MUTE, &val); | ||
449 | if (ret != kStatus_Success) | ||
450 | { | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | if (isMute) | ||
455 | { | ||
456 | val |= 1U << (channel - 1U); | ||
457 | } | ||
458 | else | ||
459 | { | ||
460 | val &= ~(1U << (channel - 1u)); | ||
461 | } | ||
462 | |||
463 | return CS42888_WriteReg(handle, CS42888_CHANNEL_MUTE, val); | ||
464 | ; | ||
465 | } | ||
466 | |||
467 | status_t CS42888_WriteReg(cs42888_handle_t *handle, uint8_t reg, uint8_t val) | ||
468 | { | ||
469 | assert(handle->config != NULL); | ||
470 | |||
471 | return CODEC_I2C_Send(handle->i2cHandle, handle->config->slaveAddress, reg, 1U, &val, 1U); | ||
472 | } | ||
473 | |||
474 | status_t CS42888_ReadReg(cs42888_handle_t *handle, uint8_t reg, uint8_t *val) | ||
475 | { | ||
476 | assert(handle->config != NULL); | ||
477 | |||
478 | return CODEC_I2C_Receive(handle->i2cHandle, handle->config->slaveAddress, reg, 1U, val, 1U); | ||
479 | } | ||
480 | |||
481 | status_t CS42888_ModifyReg(cs42888_handle_t *handle, uint8_t reg, uint8_t mask, uint8_t val) | ||
482 | { | ||
483 | uint8_t reg_val = 0; | ||
484 | |||
485 | if (CS42888_ReadReg(handle, reg, ®_val) != kStatus_Success) | ||
486 | { | ||
487 | return kStatus_Fail; | ||
488 | } | ||
489 | |||
490 | reg_val &= (uint8_t)~mask; | ||
491 | reg_val |= val; | ||
492 | |||
493 | return CS42888_WriteReg(handle, reg, reg_val); | ||
494 | } | ||