aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/components/codec/cs42888/fsl_cs42888.c
diff options
context:
space:
mode:
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.c494
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 */
27static 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 */
34static void CS42888_DelayMs(uint32_t ms);
35/*******************************************************************************
36 * Variables
37 ******************************************************************************/
38
39/*******************************************************************************
40 * Code
41 ******************************************************************************/
42static 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}
54status_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
144status_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
156void 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
164static 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
176status_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
187status_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
277status_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
346status_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
370status_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
386status_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
402uint8_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
417uint8_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
432status_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
440status_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
467status_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
474status_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
481status_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, &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}