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, &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