1 /**************************************************************************//**
2 *
3 * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date            Author       Notes
9 * 2020-1-16       Wayne        First version
10 *
11 ******************************************************************************/
12 
13 #include <rtconfig.h>
14 
15 #if defined(NU_PKG_USING_NAU88L25)
16 
17 #include <rtthread.h>
18 #include <rtdevice.h>
19 
20 #include "acodec_nau88l25.h"
21 #include "drv_i2s.h"
22 
23 #define DBG_ENABLE
24 #define DBG_LEVEL DBG_LOG
25 #define DBG_SECTION_NAME  "acodec.nau88l25"
26 #define DBG_COLOR
27 #include <rtdbg.h>
28 
29 #define DEF_NAU88L25_ADDR    0x1A
30 
31 static struct rt_i2c_bus_device *g_I2cBusDev = NULL;
32 S_NU_NAU88L25_CONFIG *g_psCodecConfig = NULL;
33 
34 static rt_err_t nau88l25_init(void);
35 static rt_err_t nau88l25_reset(void);
36 static rt_err_t nau88l25_dsp_control(struct rt_audio_configure *config);
37 static rt_err_t nau88l25_mixer_control(rt_uint32_t ui32Units, rt_uint32_t ui32Value);
38 static rt_err_t nau88l25_mixer_query(rt_uint32_t ui32Units, rt_uint32_t *ui32Value);
39 
40 nu_acodec_ops nu_acodec_ops_nau88l25 =
41 {
42     .name = "NAU88L25",
43     .role = NU_ACODEC_ROLE_MASTER,
44     .config = { // Default settings.
45         .samplerate = 48000,
46         .channels = 2,
47         .samplebits = 16
48     },
49     .nu_acodec_init = nau88l25_init,
50     .nu_acodec_reset = nau88l25_reset,
51 
52     .nu_acodec_dsp_control = nau88l25_dsp_control,
53     .nu_acodec_mixer_control = nau88l25_mixer_control,
54     .nu_acodec_mixer_query = nau88l25_mixer_query
55 };
56 
nau88l25_delay_ms(rt_uint32_t nms)57 static void nau88l25_delay_ms(rt_uint32_t nms)
58 {
59     rt_thread_mdelay(nms);
60 }
61 
I2C_WriteNAU88L25(uint16_t u16addr,uint16_t u16data)62 static int I2C_WriteNAU88L25(uint16_t u16addr, uint16_t u16data)
63 {
64     struct rt_i2c_msg msg;
65     char au8TxData[4];
66 
67     RT_ASSERT(g_I2cBusDev != NULL);
68 
69     au8TxData[0] = (uint8_t)((u16addr >> 8) & 0x00FF);   //addr [15:8]
70     au8TxData[1] = (uint8_t)(u16addr & 0x00FF);          //addr [ 7:0]
71     au8TxData[2] = (uint8_t)((u16data >> 8) & 0x00FF);   //data [15:8]
72     au8TxData[3] = (uint8_t)(u16data & 0x00FF);          //data [ 7:0]
73 
74     msg.addr  = DEF_NAU88L25_ADDR;               /* Slave address */
75     msg.flags = RT_I2C_WR;                       /* Write flag */
76     msg.buf   = (rt_uint8_t *)&au8TxData[0];     /* Slave register address */
77     msg.len   = sizeof(au8TxData);               /* Number of bytes sent */
78 
79     if (g_I2cBusDev && rt_i2c_transfer(g_I2cBusDev, &msg, 1) != 1)
80     {
81         rt_kprintf("[Failed] addr=%x, data=%d\n", u16addr, u16data);
82         return -RT_ERROR;
83     }
84 
85     return RT_EOK;
86 }
87 
I2C_ReadNAU88L25(uint16_t u16addr,uint16_t * pu16data)88 static int I2C_ReadNAU88L25(uint16_t u16addr, uint16_t *pu16data)
89 {
90     struct rt_i2c_msg msgs[2];
91     char au8TxData[2];
92 
93     RT_ASSERT(g_I2cBusDev != NULL);
94     RT_ASSERT(pu16data != NULL);
95 
96     au8TxData[0] = (uint8_t)((u16addr >> 8) & 0x00FF);   //addr [15:8]
97     au8TxData[1] = (uint8_t)(u16addr & 0x00FF);          //addr [ 7:0]
98 
99     msgs[0].addr  = DEF_NAU88L25_ADDR;        /* Slave address */
100     msgs[0].flags = RT_I2C_WR;                /* Write flag */
101     msgs[0].buf   = (rt_uint8_t *)&au8TxData; /* Number of bytes sent */
102     msgs[0].len   = sizeof(au8TxData);        /* Number of bytes read */
103 
104     msgs[1].addr  = DEF_NAU88L25_ADDR;        /* Slave address */
105     msgs[1].flags = RT_I2C_RD;                /* Read flag */
106     msgs[1].buf   = (rt_uint8_t *)pu16data;   /* Read data pointer */
107     msgs[1].len   = sizeof(uint16_t);         /* Number of bytes read */
108 
109     if (rt_i2c_transfer(g_I2cBusDev, &msgs[0], 2) != 2)
110     {
111         return -RT_ERROR;
112     }
113 
114     return RT_EOK;
115 }
116 
nau88l25_phonejack_set(S_NU_NAU88L25_CONFIG * psCodecConfig,int bEnable)117 static void nau88l25_phonejack_set(S_NU_NAU88L25_CONFIG *psCodecConfig, int bEnable)
118 {
119     rt_pin_mode(psCodecConfig->pin_phonejack_en, PIN_MODE_OUTPUT);
120 
121     if (bEnable)
122     {
123         rt_pin_write(psCodecConfig->pin_phonejack_en, PIN_LOW);
124     }
125     else
126     {
127         rt_pin_write(psCodecConfig->pin_phonejack_en, PIN_HIGH);
128     }
129 }
130 
nau88l25_probe(void)131 static rt_err_t nau88l25_probe(void)
132 {
133     return RT_EOK;
134 }
135 
nau88l25_reset(void)136 static rt_err_t nau88l25_reset(void)
137 {
138     I2C_WriteNAU88L25(0,  0x1);
139     I2C_WriteNAU88L25(0,  0);   // Reset all registers
140     nau88l25_delay_ms(30);
141 
142     LOG_I("Software Reset.\n");
143 
144     return RT_EOK;
145 }
146 
nau88l25_dsp_config(rt_uint32_t ui32SamplRate,rt_uint8_t u8ChNum,rt_uint8_t u8SamplBit)147 static rt_err_t nau88l25_dsp_config(rt_uint32_t ui32SamplRate, rt_uint8_t u8ChNum, rt_uint8_t u8SamplBit)
148 {
149     int  clkDivider;
150     int  i2sPcmCtrl2;
151     int  lrClkDiv;
152     char bClkDiv;
153     char mClkDiv;
154 
155     /* Force to set Channel number to 2 */
156     u8ChNum = 2;
157 
158     I2C_WriteNAU88L25(REG_I2S_PCM_CTRL1, AIFMT0_STANDI2S | ((u8SamplBit <= 24) ? ((u8SamplBit - 16) >> 2) : WLEN0_32BIT));
159     u8SamplBit = (u8SamplBit > 16) ? 32 : 16;
160 
161     if (ui32SamplRate % 11025)
162     {
163         /* 48000 series 12.288Mhz */
164         I2C_WriteNAU88L25(REG_FLL2, 0x3126);
165         I2C_WriteNAU88L25(REG_FLL3, 0x0008);
166 
167         mClkDiv = 49152000 / (ui32SamplRate * 256);
168     }
169     else
170     {
171         /* 44100 series 11.2896Mhz */
172         I2C_WriteNAU88L25(REG_FLL2, 0x86C2);
173         I2C_WriteNAU88L25(REG_FLL3, 0x0007);
174 
175         /* FIXME */
176         if (ui32SamplRate > 44100)
177             ui32SamplRate = 11025;
178 
179         mClkDiv = 45158400 / (ui32SamplRate * 256);
180     }
181 
182     lrClkDiv = u8ChNum * u8SamplBit;
183     bClkDiv = 256 / lrClkDiv;
184 
185     switch (mClkDiv)
186     {
187     case 1:
188         mClkDiv = 0;
189         break;
190     case 2:
191         mClkDiv = 2;
192         break;
193     case 4:
194         mClkDiv = 3;
195         break;
196     case 8:
197         mClkDiv = 4;
198         break;
199     case 16:
200         mClkDiv = 5;
201         break;
202     case 32:
203         mClkDiv = 6;
204         break;
205     case 3:
206         mClkDiv = 7;
207         break;
208     case 6:
209         mClkDiv = 10;
210         break;
211     case 12:
212         mClkDiv = 11;
213         break;
214     case 24:
215         mClkDiv = 12;
216         break;
217     case 48:
218         mClkDiv = 13;
219         break;
220     case 96:
221         mClkDiv = 14;
222         break;
223     case 5:
224         mClkDiv = 15;
225         break;
226     default:
227         LOG_E("mclk divider not match!\n");
228         mClkDiv = 0;
229         return -RT_ERROR;
230     }
231 
232     clkDivider = CLK_SYSCLK_SRC_VCO | CLK_ADC_SRC_DIV2 | CLK_DAC_SRC_DIV2 | mClkDiv;
233     I2C_WriteNAU88L25(REG_CLK_DIVIDER, clkDivider);
234 
235     switch (bClkDiv)
236     {
237     case 2:
238         bClkDiv = 0;
239         break;
240     case 4:
241         bClkDiv = 1;
242         break;
243     case 8:
244         bClkDiv = 2;
245         break;
246     case 16:
247         bClkDiv = 3;
248         break;
249     case 32:
250         bClkDiv = 4;
251         break;
252     case 64:
253         bClkDiv = 5;
254         break;
255     default:
256         LOG_E("bclk divider not match!\n");
257         bClkDiv = 0;
258         return -RT_ERROR;
259     }
260 
261     switch (lrClkDiv)
262     {
263     case 256:
264         lrClkDiv = 0;
265         break;
266     case 128:
267         lrClkDiv = 1;
268         break;
269     case 64:
270         lrClkDiv = 2;
271         break;
272     case 32:
273         lrClkDiv = 3;
274         break;
275     default:
276         LOG_E("lrclk divider not match!\n");
277         lrClkDiv = 0;
278         return -RT_ERROR;
279     }
280 
281     i2sPcmCtrl2 =  ADCDAT0_OE | MS0_MASTER | (lrClkDiv << 12) | bClkDiv;
282 
283     I2C_WriteNAU88L25(REG_I2S_PCM_CTRL2, i2sPcmCtrl2);
284 
285     return RT_EOK;
286 }
287 
nau88l25_init(void)288 static rt_err_t nau88l25_init(void)
289 {
290     I2C_WriteNAU88L25(REG_CLK_DIVIDER,  CLK_SYSCLK_SRC_VCO | CLK_ADC_SRC_DIV2 | CLK_DAC_SRC_DIV2 | MCLK_SRC_DIV4);
291     I2C_WriteNAU88L25(REG_FLL1,  FLL_RATIO_512K);
292     I2C_WriteNAU88L25(REG_FLL2,  0x3126);
293     I2C_WriteNAU88L25(REG_FLL3,  0x0008);
294     I2C_WriteNAU88L25(REG_FLL4,  0x0010);
295     I2C_WriteNAU88L25(REG_FLL5,  PDB_DACICTRL | CHB_FILTER_EN);
296     I2C_WriteNAU88L25(REG_FLL6,  SDM_EN | CUTOFF500);
297     I2C_WriteNAU88L25(REG_FLL_VCO_RSV,  0xF13C);
298     I2C_WriteNAU88L25(REG_HSD_CTRL,  HSD_AUTO_MODE | MANU_ENGND1_GND);
299     I2C_WriteNAU88L25(REG_SAR_CTRL,  RES_SEL_70K_OHMS | COMP_SPEED_1US | SAMPLE_SPEED_4US);
300     I2C_WriteNAU88L25(REG_I2S_PCM_CTRL1,  AIFMT0_STANDI2S);
301 
302     if (nu_acodec_ops_nau88l25.role == NU_ACODEC_ROLE_MASTER)
303     {
304         I2C_WriteNAU88L25(REG_I2S_PCM_CTRL2,  LRC_DIV_DIV32 | ADCDAT0_OE | MS0_MASTER | BLCKDIV_DIV8);   //301A:Master 3012:Slave
305     }
306     else
307     {
308         I2C_WriteNAU88L25(REG_I2S_PCM_CTRL2,  LRC_DIV_DIV32 | ADCDAT0_OE | MS0_SLAVE | BLCKDIV_DIV8);
309         I2C_WriteNAU88L25(REG_LEFT_TIME_SLOT,  DIS_FS_SHORT_DET);
310     }
311 
312     I2C_WriteNAU88L25(REG_ADC_RATE,  0x10 | ADC_RATE_128);
313     I2C_WriteNAU88L25(REG_DAC_CTRL1,  0x80 | DAC_RATE_128);
314 
315     I2C_WriteNAU88L25(REG_MUTE_CTRL,  0x0000); // 0x10000
316     I2C_WriteNAU88L25(REG_ADC_DGAIN_CTRL,  DGAINL_ADC0(0xEF));
317     I2C_WriteNAU88L25(REG_DACL_CTRL,  DGAINL_DAC(0xAE));
318     I2C_WriteNAU88L25(REG_DACR_CTRL,  DGAINR_DAC(0xAE) | DAC_CH_SEL1_RIGHT);
319 
320     I2C_WriteNAU88L25(REG_CLASSG_CTRL,  CLASSG_TIMER_64MS | CLASSG_CMP_EN_R_DAC | CLASSG_CMP_EN_L_DAC | CLASSG_EN);
321     I2C_WriteNAU88L25(REG_BIAS_ADJ,  VMIDEN | VMIDSEL_125K_OHM);
322     I2C_WriteNAU88L25(REG_TRIM_SETTINGS,  DRV_IBCTRHS | DRV_ICUTHS | INTEG_IBCTRHS | INTEG_ICUTHS);
323     I2C_WriteNAU88L25(REG_ANALOG_CONTROL_2,  AB_ADJ | CAP_1 | CAP_0);
324     I2C_WriteNAU88L25(REG_ANALOG_ADC_1,  CHOPRESETN | CHOPF0_DIV4);
325     I2C_WriteNAU88L25(REG_ANALOG_ADC_2,  VREFSEL_VMIDE_P5DB | PDNOTL | LFSRRESETN);
326     I2C_WriteNAU88L25(REG_RDAC,  DAC_EN_L | DAC_EN_R | CLK_DAC_EN_L | CLK_DAC_EN_R | CLK_DAC_DELAY_2NSEC | DACVREFSEL(0x3));
327     I2C_WriteNAU88L25(REG_MIC_BIAS,  INT2KB | LOWNOISE | POWERUP | MICBIASLVL1_1P1x);
328     I2C_WriteNAU88L25(REG_BOOST,  PDVMDFST | BIASEN | BOOSTGDIS | EN_SHRT_SHTDWN);
329     I2C_WriteNAU88L25(REG_POWER_UP_CONTROL,  PUFEPGA | FEPGA_GAIN(21) | PUP_INTEG_LEFT_HP | PUP_INTEG_RIGHT_HP | PUP_DRV_INSTG_RIGHT_HP | PUP_DRV_INSTG_LEFT_HP | PUP_MAIN_DRV_RIGHT_HP | PUP_MAIN_DRV_LEFT_HP);
330     I2C_WriteNAU88L25(REG_CHARGE_PUMP_AND_DOWN_CONTROL, JAMNODCLOW | RNIN);
331     I2C_WriteNAU88L25(REG_ENA_CTRL,  RDAC_EN | LDAC_EN | ADC_EN | DCLK_ADC_EN | DCLK_DAC_EN | CLK_I2S_EN | 0x4);
332 
333     nu_acodec_ops_nau88l25.config.samplerate = 48000;
334     nu_acodec_ops_nau88l25.config.channels = 2;
335     nu_acodec_ops_nau88l25.config.samplebits = 16;
336 
337     LOG_I("Initialized done.\n");
338 
339     return RT_EOK;
340 }
341 
nau88l25_dsp_control(struct rt_audio_configure * config)342 static rt_err_t nau88l25_dsp_control(struct rt_audio_configure *config)
343 {
344     rt_err_t result = RT_EOK;
345 
346     RT_ASSERT(config != RT_NULL);
347 
348     if (rt_memcmp((void *)config, (void *)&nu_acodec_ops_nau88l25.config, sizeof(struct rt_audio_configure)) != 0)
349     {
350         if ((result = nau88l25_dsp_config(config->samplerate, config->channels, config->samplebits)) == RT_EOK)
351             rt_memcpy((void *)&nu_acodec_ops_nau88l25.config, (void *)config, sizeof(struct rt_audio_configure)) ;
352     }
353     return result;
354 }
355 
nau88l25_mixer_control(rt_uint32_t ui32Units,rt_uint32_t ui32Value)356 static rt_err_t nau88l25_mixer_control(rt_uint32_t ui32Units, rt_uint32_t ui32Value)
357 {
358     switch (ui32Units)
359     {
360     case AUDIO_MIXER_MUTE:
361         if (ui32Value)
362         {
363             I2C_WriteNAU88L25(REG_MUTE_CTRL,  SMUTE_EN);
364             nau88l25_phonejack_set(g_psCodecConfig, 0);
365         }
366         else
367         {
368             I2C_WriteNAU88L25(REG_MUTE_CTRL,  0x0000);
369             nau88l25_phonejack_set(g_psCodecConfig, 1);
370         }
371         break;
372 
373     case AUDIO_MIXER_VOLUME:
374         I2C_WriteNAU88L25(REG_DACL_CTRL,  DGAINL_DAC(ui32Value * 2));
375         I2C_WriteNAU88L25(REG_DACR_CTRL,  DGAINR_DAC(ui32Value * 2) | DAC_CH_SEL1_RIGHT);
376         break;
377 
378     case AUDIO_MIXER_QUERY:
379     case AUDIO_MIXER_BASS:
380     case AUDIO_MIXER_MID:
381     case AUDIO_MIXER_TREBLE:
382     case AUDIO_MIXER_EQUALIZER:
383     case AUDIO_MIXER_LINE:
384     case AUDIO_MIXER_DIGITAL:
385     case AUDIO_MIXER_MIC:
386     case AUDIO_MIXER_VITURAL:
387     case AUDIO_MIXER_EXTEND:
388     default:
389         return -RT_ERROR;
390     }
391     return RT_EOK;
392 }
393 
nau88l25_mixer_query(rt_uint32_t ui32Units,rt_uint32_t * pui32Value)394 static rt_err_t nau88l25_mixer_query(rt_uint32_t ui32Units, rt_uint32_t *pui32Value)
395 {
396     RT_ASSERT(pui32Value != RT_NULL);
397     rt_uint16_t u16RV = 0;
398 
399     switch (ui32Units)
400     {
401     case AUDIO_MIXER_QUERY:
402         *pui32Value = AUDIO_MIXER_VOLUME | AUDIO_MIXER_MUTE;
403         break;
404 
405     case AUDIO_MIXER_MUTE:
406         I2C_ReadNAU88L25(REG_MUTE_CTRL, (uint16_t *)&u16RV);
407         if (u16RV & SMUTE_EN)
408             *pui32Value = 1;
409         else
410             *pui32Value = 0;
411         break;
412 
413     case AUDIO_MIXER_VOLUME:
414         I2C_ReadNAU88L25(REG_DACL_CTRL, (uint16_t *)&u16RV);
415         *pui32Value = u16RV / 2;
416         break;
417 
418     case AUDIO_MIXER_BASS:
419     case AUDIO_MIXER_MID:
420     case AUDIO_MIXER_TREBLE:
421     case AUDIO_MIXER_EQUALIZER:
422     case AUDIO_MIXER_LINE:
423     case AUDIO_MIXER_DIGITAL:
424     case AUDIO_MIXER_MIC:
425     case AUDIO_MIXER_VITURAL:
426     case AUDIO_MIXER_EXTEND:
427     default:
428         return -RT_ERROR;
429     }
430     return RT_EOK;
431 }
432 
nu_hw_nau88l25_init(S_NU_NAU88L25_CONFIG * psCodecConfig)433 int nu_hw_nau88l25_init(S_NU_NAU88L25_CONFIG *psCodecConfig)
434 {
435     RT_ASSERT(psCodecConfig != RT_NULL);
436     struct rt_i2c_bus_device *psI2cBusDev;
437     struct rt_audio_device *psAudioDev;
438     nu_i2s_t psNuI2s;
439 
440     /* Find I2C bus */
441     psI2cBusDev = (struct rt_i2c_bus_device *)rt_device_find(psCodecConfig->i2c_bus_name);
442     if (psI2cBusDev == RT_NULL)
443     {
444         LOG_E("Can't found I2C bus - %s..!\n", psCodecConfig->i2c_bus_name);
445         goto exit_rt_hw_nau88l25_init;
446     }
447 
448     /* Find I2S bus */
449     psAudioDev = (struct rt_audio_device *)rt_device_find(psCodecConfig->i2s_bus_name);
450     if (psAudioDev == RT_NULL)
451     {
452         LOG_E("Can't found I2S bus - %s ..!\n", psCodecConfig->i2s_bus_name);
453         goto exit_rt_hw_nau88l25_init;
454     }
455 
456     if (nau88l25_probe() != RT_EOK)
457     {
458         LOG_E("Can't found audio codec..!\n");
459         goto exit_rt_hw_nau88l25_init;
460     }
461 
462     /* Store this board setting. */
463     g_psCodecConfig = psCodecConfig;
464     g_I2cBusDev = psI2cBusDev;
465 
466     /* Get NuI2S device instance. */
467     psNuI2s = (nu_i2s_t)psAudioDev;
468 
469     /* Register Acodec Ops */
470     psNuI2s->AcodecOps = &nu_acodec_ops_nau88l25;
471 
472     /* Use Acodec default settings. */
473     rt_memcpy(&psNuI2s->config, &nu_acodec_ops_nau88l25.config, sizeof(struct rt_audio_configure));
474 
475     return RT_EOK;
476 
477 exit_rt_hw_nau88l25_init:
478 
479     return -RT_ERROR;
480 }
481 
482 #endif //#if defined(NU_PKG_USING_NAU88L25)
483