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