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 ******************************************************************************/
CS42888_DelayMs(uint32_t ms)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 }
CS42888_Init(cs42888_handle_t * handle,cs42888_config_t * config)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
CS42888_SelectFunctionalMode(cs42888_handle_t * handle,cs42888_func_mode adcMode,cs42888_func_mode dacMode)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
CS42888_SetFuncMode(cs42888_handle_t * handle,cs42888_func_mode mode)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
CS42888_Reset(cs42888_handle_t * handle,cs42888_reset codecReset)164 static void CS42888_Reset(cs42888_handle_t *handle, cs42888_reset codecReset)
165 {
166 if (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
CS42888_Deinit(cs42888_handle_t * handle)177 status_t CS42888_Deinit(cs42888_handle_t *handle)
178 {
179 /* Disable all modules making CS42888 enter a low power mode */
180 if (CS42888_WriteReg(handle, CS42888_FUNCTIONAL_MODE, 0U) != kStatus_Success)
181 {
182 return kStatus_Fail;
183 }
184
185 return CODEC_I2C_Deinit(handle->i2cHandle);
186 }
187
CS42888_SetProtocol(cs42888_handle_t * handle,cs42888_bus_t protocol,uint32_t bitWidth)188 status_t CS42888_SetProtocol(cs42888_handle_t *handle, cs42888_bus_t protocol, uint32_t bitWidth)
189 {
190 uint8_t format = 0U;
191 status_t errorStatus = kStatus_Success;
192
193 switch (protocol)
194 {
195 case kCS42888_BusLeftJustified:
196 if (bitWidth <= 24U)
197 {
198 format = 0U;
199 }
200 else
201 {
202 errorStatus = kStatus_InvalidArgument;
203 }
204 break;
205
206 case kCS42888_BusI2S:
207 if (bitWidth <= 24U)
208 {
209 format = 0x09U;
210 }
211 else
212 {
213 errorStatus = kStatus_InvalidArgument;
214 }
215 break;
216
217 case kCS42888_BusRightJustified:
218 if (bitWidth == 24U)
219 {
220 format = 0x12U;
221 }
222 else if (bitWidth == 16U)
223 {
224 format = 0x1BU;
225 }
226 else
227 {
228 errorStatus = kStatus_InvalidArgument;
229 }
230 break;
231
232 case kCS42888_BusOL1:
233 if (bitWidth == 20U)
234 {
235 format = 0x24U;
236 }
237 else
238 {
239 errorStatus = kStatus_InvalidArgument;
240 }
241 break;
242
243 case kCS42888_BusOL2:
244 if (bitWidth == 24U)
245 {
246 format = 0x2DU;
247 }
248 else
249 {
250 errorStatus = kStatus_InvalidArgument;
251 }
252 break;
253
254 case kCS42888_BusTDM:
255 if (bitWidth == 24U)
256 {
257 format = 0x36U;
258 }
259 else
260 {
261 errorStatus = kStatus_InvalidArgument;
262 }
263 break;
264
265 default:
266 errorStatus = kStatus_InvalidArgument;
267 break;
268 }
269
270 if (errorStatus == kStatus_Success)
271 {
272 errorStatus = CS42888_ModifyReg(handle, CS42888_INTERFACE_FORMATS, 0x3FU, format);
273 }
274
275 return errorStatus;
276 }
277
CS42888_ConfigDataFormat(cs42888_handle_t * handle,uint32_t mclk,uint32_t sample_rate,uint32_t bits)278 status_t CS42888_ConfigDataFormat(cs42888_handle_t *handle, uint32_t mclk, uint32_t sample_rate, uint32_t bits)
279 {
280 status_t retval = kStatus_Success;
281
282 uint8_t val = 0;
283 uint32_t ratio = mclk / sample_rate;
284
285 if (CS42888_ReadReg(handle, CS42888_FUNCTIONAL_MODE, &val) != kStatus_Success)
286 {
287 return kStatus_Fail;
288 }
289
290 /* clear mfreq field */
291 val &= (uint8_t)~0xEU;
292
293 switch (ratio)
294 {
295 case 64:
296 assert(CLOCK_RATE_IN_RANGE(sample_rate, 100000U, 200000U));
297 assert(CLOCK_RATE_IN_RANGE(mclk, 1029000U, 12800000U));
298 break;
299
300 case 128:
301 if (CLOCK_RATE_IN_RANGE(sample_rate, 100000U, 200000U) && CLOCK_RATE_IN_RANGE(mclk, 2048000U, 25600000U))
302 {
303 val |= 4U;
304 }
305 break;
306
307 case 256:
308 if (CLOCK_RATE_IN_RANGE(sample_rate, 50000U, 100000U) && CLOCK_RATE_IN_RANGE(mclk, 2048000U, 25600000U))
309 {
310 val |= 4U;
311 }
312
313 if (CLOCK_RATE_IN_RANGE(sample_rate, 100000U, 200000U) && CLOCK_RATE_IN_RANGE(mclk, 4096000U, 51200000U))
314 {
315 val |= 8U;
316 }
317 break;
318
319 case 512:
320 if (CLOCK_RATE_IN_RANGE(sample_rate, 4000U, 50000U) && CLOCK_RATE_IN_RANGE(mclk, 2048000U, 25600000U))
321 {
322 val |= 4U;
323 }
324
325 if (CLOCK_RATE_IN_RANGE(sample_rate, 50000U, 100000U) && CLOCK_RATE_IN_RANGE(mclk, 4096000U, 51200000U))
326 {
327 val |= 8U;
328 }
329 break;
330
331 case 1024:
332 assert(CLOCK_RATE_IN_RANGE(mclk, 4096000U, 51200000U));
333 assert(CLOCK_RATE_IN_RANGE(sample_rate, 4000U, 50000U));
334 val |= 8U;
335 break;
336
337 default:
338 assert(false);
339 break;
340 }
341
342 retval = CS42888_WriteReg(handle, CS42888_FUNCTIONAL_MODE, val);
343
344 return retval;
345 }
346
CS42888_SetModule(cs42888_handle_t * handle,cs42888_module_t module,bool isEnabled)347 status_t CS42888_SetModule(cs42888_handle_t *handle, cs42888_module_t module, bool isEnabled)
348 {
349 status_t ret = kStatus_Success;
350 uint8_t val = 0;
351
352 /* Read Power control register value */
353 if (CS42888_ReadReg(handle, CS42888_POWER_CONTROL, &val) != kStatus_Success)
354 {
355 return kStatus_Fail;
356 }
357
358 if (isEnabled)
359 {
360 val |= (uint8_t)module;
361 }
362 else
363 {
364 val &= ~(uint8_t)module;
365 }
366
367 ret = CS42888_WriteReg(handle, CS42888_POWER_CONTROL, val);
368 return ret;
369 }
370
CS42888_SetAOUTVolume(cs42888_handle_t * handle,uint8_t channel,uint8_t volume)371 status_t CS42888_SetAOUTVolume(cs42888_handle_t *handle, uint8_t channel, uint8_t volume)
372 {
373 status_t ret = kStatus_Success;
374 uint8_t reg = CS42888_VOL_CONTROL_AOUT1 + (channel - 1U);
375
376 if ((channel < 1U) || (channel > 8U))
377 {
378 ret = kStatus_Fail;
379 }
380 else
381 {
382 ret = CS42888_WriteReg(handle, reg, volume);
383 }
384 return ret;
385 }
386
CS42888_SetAINVolume(cs42888_handle_t * handle,uint8_t channel,uint8_t volume)387 status_t CS42888_SetAINVolume(cs42888_handle_t *handle, uint8_t channel, uint8_t volume)
388 {
389 status_t ret = kStatus_Success;
390 uint8_t reg = CS42888_VOL_CONTROL_AIN1 + (channel - 1U);
391
392 if ((channel < 1U) || (channel > 4U))
393 {
394 ret = kStatus_Fail;
395 }
396 else
397 {
398 ret = CS42888_WriteReg(handle, reg, volume);
399 }
400 return ret;
401 }
402
CS42888_GetAOUTVolume(cs42888_handle_t * handle,uint8_t channel)403 uint8_t CS42888_GetAOUTVolume(cs42888_handle_t *handle, uint8_t channel)
404 {
405 uint8_t val = 0;
406 uint8_t reg = CS42888_VOL_CONTROL_AOUT1 + (channel - 1U);
407 if ((channel < 1U) || (channel > 8U))
408 {
409 val = 0;
410 }
411 else
412 {
413 (void)CS42888_ReadReg(handle, reg, &val);
414 }
415 return val;
416 }
417
CS42888_GetAINVolume(cs42888_handle_t * handle,uint8_t channel)418 uint8_t CS42888_GetAINVolume(cs42888_handle_t *handle, uint8_t channel)
419 {
420 uint8_t val = 0;
421 uint8_t reg = CS42888_VOL_CONTROL_AIN1 + (channel - 1U);
422 if ((channel < 1U) || (channel > 4U))
423 {
424 val = 0;
425 }
426 else
427 {
428 (void)CS42888_ReadReg(handle, reg, &val);
429 }
430 return val;
431 }
432
CS42888_SetMute(cs42888_handle_t * handle,uint8_t channelMask)433 status_t CS42888_SetMute(cs42888_handle_t *handle, uint8_t channelMask)
434 {
435 status_t ret = kStatus_Success;
436
437 ret = CS42888_WriteReg(handle, CS42888_CHANNEL_MUTE, channelMask);
438 return ret;
439 }
440
CS42888_SetChannelMute(cs42888_handle_t * handle,uint8_t channel,bool isMute)441 status_t CS42888_SetChannelMute(cs42888_handle_t *handle, uint8_t channel, bool isMute)
442 {
443 assert(channel >= (uint8_t)kCS42888_AOUT1);
444
445 status_t ret = kStatus_Success;
446
447 uint8_t val = 0U;
448
449 ret = CS42888_ReadReg(handle, CS42888_CHANNEL_MUTE, &val);
450 if (ret != kStatus_Success)
451 {
452 return ret;
453 }
454
455 if (isMute)
456 {
457 val |= 1U << (channel - 1U);
458 }
459 else
460 {
461 val &= ~(1U << (channel - 1u));
462 }
463
464 return CS42888_WriteReg(handle, CS42888_CHANNEL_MUTE, val);
465 ;
466 }
467
CS42888_WriteReg(cs42888_handle_t * handle,uint8_t reg,uint8_t val)468 status_t CS42888_WriteReg(cs42888_handle_t *handle, uint8_t reg, uint8_t val)
469 {
470 assert(handle->config != NULL);
471
472 return CODEC_I2C_Send(handle->i2cHandle, handle->config->slaveAddress, reg, 1U, &val, 1U);
473 }
474
CS42888_ReadReg(cs42888_handle_t * handle,uint8_t reg,uint8_t * val)475 status_t CS42888_ReadReg(cs42888_handle_t *handle, uint8_t reg, uint8_t *val)
476 {
477 assert(handle->config != NULL);
478
479 return CODEC_I2C_Receive(handle->i2cHandle, handle->config->slaveAddress, reg, 1U, val, 1U);
480 }
481
CS42888_ModifyReg(cs42888_handle_t * handle,uint8_t reg,uint8_t mask,uint8_t val)482 status_t CS42888_ModifyReg(cs42888_handle_t *handle, uint8_t reg, uint8_t mask, uint8_t val)
483 {
484 uint8_t reg_val = 0;
485
486 if (CS42888_ReadReg(handle, reg, ®_val) != kStatus_Success)
487 {
488 return kStatus_Fail;
489 }
490
491 reg_val &= (uint8_t)~mask;
492 reg_val |= val;
493
494 return CS42888_WriteReg(handle, reg, reg_val);
495 }
496