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