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-12-12      Wayne        First version
10 *
11 ******************************************************************************/
12 
13 #include <rtconfig.h>
14 
15 #if defined(NU_PKG_USING_NAU8822)
16 
17 #include <rtthread.h>
18 #include <rtdevice.h>
19 
20 #include "acodec_nau8822.h"
21 #include "drv_i2s.h"
22 
23 #define DBG_ENABLE
24 #define DBG_LEVEL DBG_LOG
25 #define DBG_SECTION_NAME  "acodec.nau8822"
26 #define DBG_COLOR
27 #include <rtdbg.h>
28 
29 #define DEF_NAU8822_ADDR    0x1A
30 
31 static struct rt_i2c_bus_device *g_I2cBusDev = NULL;
32 S_NU_NAU8822_CONFIG *g_psCodecConfig = NULL;
33 
34 static rt_err_t nau8822_init(void);
35 static rt_err_t nau8822_reset(void);
36 static rt_err_t nau8822_dsp_control(struct rt_audio_configure *config);
37 static rt_err_t nau8822_mixer_control(rt_uint32_t ui32Units, rt_uint32_t ui32Value);
38 static rt_err_t nau8822_mixer_query(rt_uint32_t ui32Units, rt_uint32_t *ui32Value);
39 
40 nu_acodec_ops nu_acodec_ops_nau8822 =
41 {
42     .name = "NAU8822",
43     .role = NU_ACODEC_ROLE_MASTER,
44     .config = { // Default settings.
45         .samplerate = 16000,
46         .channels = 2,
47         .samplebits = 16
48     },
49     .nu_acodec_init = nau8822_init,
50     .nu_acodec_reset = nau8822_reset,
51 
52     .nu_acodec_dsp_control = nau8822_dsp_control,
53     .nu_acodec_mixer_control = nau8822_mixer_control,
54     .nu_acodec_mixer_query = nau8822_mixer_query
55 };
56 
nau8822_delay_ms(rt_uint32_t nms)57 static void nau8822_delay_ms(rt_uint32_t nms)
58 {
59     rt_thread_mdelay(nms);
60 }
61 
I2C_ReadNAU8822(uint8_t u8addr,uint16_t * pu16data)62 static int I2C_ReadNAU8822(uint8_t u8addr, uint16_t *pu16data)
63 {
64     struct rt_i2c_msg msgs[2];
65     uint8_t u8TxData = (u8addr << 1);
66 
67     RT_ASSERT(g_I2cBusDev != NULL);
68     RT_ASSERT(pu16data != NULL);
69 
70     msgs[0].addr  = DEF_NAU8822_ADDR;         /* Slave address */
71     msgs[0].flags = RT_I2C_WR;                /* Write flag */
72     msgs[0].buf   = (rt_uint8_t *)&u8TxData;  /* Number of bytes sent */
73     msgs[0].len   = sizeof(u8TxData);         /* Number of bytes read */
74 
75     msgs[1].addr  = DEF_NAU8822_ADDR;         /* Slave address */
76     msgs[1].flags = RT_I2C_RD;                /* Read flag */
77     msgs[1].buf   = (rt_uint8_t *)pu16data;   /* Read data pointer */
78     msgs[1].len   = 2;                        /* Number of bytes read */
79 
80     if (rt_i2c_transfer(g_I2cBusDev, &msgs[0], 2) != 2)
81     {
82         return -RT_ERROR;
83     }
84 
85     return RT_EOK;
86 }
87 
I2C_WriteNAU8822(uint8_t u8addr,uint16_t u16data)88 static int I2C_WriteNAU8822(uint8_t u8addr, uint16_t u16data)
89 {
90     /* Write 9-bit data to 7-bit address register of NAU8822 */
91     struct rt_i2c_msg msg;
92     uint8_t au8TxData[2];
93 
94     RT_ASSERT(g_I2cBusDev != NULL);
95 
96     au8TxData[0] = (uint8_t)((u8addr << 1) | (u16data >> 8));  //u8addr [7:1] | u16data [8]
97     au8TxData[1] = (uint8_t)(u16data & 0x00FF);         //data [7:0]
98 
99     msg.addr  = DEF_NAU8822_ADDR;                /* Slave address */
100     msg.flags = RT_I2C_WR;                       /* Write flag */
101     msg.buf   = (rt_uint8_t *)&au8TxData[0];     /* Slave register address */
102     msg.len   = sizeof(au8TxData);               /* Number of bytes sent */
103 
104     if (g_I2cBusDev && rt_i2c_transfer(g_I2cBusDev, &msg, 1) != 1)
105     {
106         rt_kprintf("[Failed] addr=%x, data=%d\n", u8addr, u16data);
107         return -RT_ERROR;
108     }
109 
110     {
111         /* Verify */
112         uint8_t au8RxData[2];
113         I2C_ReadNAU8822(u8addr, (uint16_t *)&au8RxData[0]);
114         rt_kprintf("Wrote addr %02x -> 0x%04x, read back -> 0x%02x%02x\n", u8addr, u16data, au8RxData[0], au8RxData[1]);
115     }
116 
117     return RT_EOK;
118 }
119 
nau8822_phonejack_set(S_NU_NAU8822_CONFIG * psCodecConfig,int bEnable)120 static void nau8822_phonejack_set(S_NU_NAU8822_CONFIG *psCodecConfig, int bEnable)
121 {
122     rt_pin_mode(psCodecConfig->pin_phonejack_en, PIN_MODE_OUTPUT);
123 
124     if (bEnable)
125     {
126         rt_pin_write(psCodecConfig->pin_phonejack_en, PIN_LOW);
127     }
128     else
129     {
130         rt_pin_write(psCodecConfig->pin_phonejack_en, PIN_HIGH);
131     }
132 }
133 
134 
nau8822_probe(void)135 static rt_err_t nau8822_probe(void)
136 {
137     return RT_EOK;
138 }
139 
nau8822_reset(void)140 static rt_err_t nau8822_reset(void)
141 {
142     I2C_WriteNAU8822(0,  0x000);   /* Reset all registers */
143     nau8822_delay_ms(30);
144 
145     LOG_I("Software Reset.\n");
146 
147     return RT_EOK;
148 }
149 
nau8822_dsp_config(rt_uint32_t ui32SamplRate,rt_uint8_t u8ChNum,rt_uint8_t u8SamplBit)150 static rt_err_t nau8822_dsp_config(rt_uint32_t ui32SamplRate, rt_uint8_t u8ChNum, rt_uint8_t u8SamplBit)
151 {
152     uint8_t   bClkDiv;
153     uint8_t   mClkDiv;
154     uint16_t  u16AudIf = 0x010; /* I2S, 16-bit */
155     uint16_t  u16ClkCtrl;
156     uint8_t   u8WLEN;
157 
158     if (ui32SamplRate > 48000)
159         return -RT_ERROR;
160 
161     if (u8ChNum == 2)
162     {
163         u16AudIf = (u16AudIf & 0x1FE) | 0x0;
164     }
165     else
166     {
167         u16AudIf = (u16AudIf & 0x1FE) | 0x1;
168     }
169 
170     /* Force to set Channel number to 2 */
171     u8ChNum = 2;
172 
173     switch (u8SamplBit)
174     {
175     case 16:
176         u8WLEN = 0x0;
177         break;
178 
179     case 20:
180         u8WLEN = 0x1;
181         break;
182 
183     case 24:
184         u8WLEN = 0x2;
185         break;
186 
187     case 32:
188         u8WLEN = 0x3;
189         break;
190 
191     default:
192         LOG_E("sample rate not match!\n");
193         return -RT_ERROR;
194     }
195     u16AudIf = (u16AudIf & 0x19F) | (u8WLEN << 5);
196 
197     if (ui32SamplRate % 11025)
198     {
199         I2C_WriteNAU8822(36, 0x008);    //12.288Mhz
200         I2C_WriteNAU8822(37, 0x00C);
201         I2C_WriteNAU8822(38, 0x093);
202         I2C_WriteNAU8822(39, 0x0E9);
203 
204         /* FIXME */
205         if (ui32SamplRate > 48000)
206             ui32SamplRate = 8000;
207 
208         mClkDiv = (48000 * 256 * u8ChNum) / (ui32SamplRate * 256);
209         bClkDiv = (ui32SamplRate * 256) / (ui32SamplRate * u8ChNum * u8SamplBit);
210     }
211     else
212     {
213         I2C_WriteNAU8822(36, 0x007);    //11.2896Mhz
214         I2C_WriteNAU8822(37, 0x021);
215         I2C_WriteNAU8822(38, 0x161);
216         I2C_WriteNAU8822(39, 0x026);
217 
218         /* FIXME */
219         if (ui32SamplRate > 44100)
220             ui32SamplRate = 11025;
221 
222         mClkDiv = (44100 * 256 * u8ChNum) / (ui32SamplRate * 256);
223         bClkDiv = (ui32SamplRate * 256) / (ui32SamplRate * u8ChNum * u8SamplBit);
224     }
225 
226     switch (mClkDiv)
227     {
228     case 1:
229         mClkDiv = 0;
230         break;
231     case 2:
232         mClkDiv = 2;
233         break;
234     case 3:
235         mClkDiv = 3;
236         break;
237     case 4:
238         mClkDiv = 4;
239         break;
240     case 6:
241         mClkDiv = 5;
242         break;
243     case 8:
244         mClkDiv = 6;
245         break;
246     case 12:
247         mClkDiv = 7;
248         break;
249     default:
250         LOG_E("mclk divider not match!\n");
251         mClkDiv = 0;
252         return -RT_ERROR;
253     }
254 
255     switch (bClkDiv)
256     {
257     case 1:
258         bClkDiv = 0;
259         break;
260     case 2:
261         bClkDiv = 1;
262         break;
263     case 4:
264         bClkDiv = 2;
265         break;
266     case 8:
267         bClkDiv = 3;
268         break;
269     case 16:
270         bClkDiv = 4;
271         break;
272     case 32:
273         bClkDiv = 5;
274         break;
275     default:
276         LOG_E("bclk divider not match!\n");
277         bClkDiv = 0;
278         return -RT_ERROR;
279     }
280 
281     if (nu_acodec_ops_nau8822.role == NU_ACODEC_ROLE_MASTER)
282     {
283         u16ClkCtrl = (1 << 8) | (1 << 0);  //Use internal PLL, FS/BCLK
284     }
285 
286     u16ClkCtrl = (u16ClkCtrl & 0x11F) | (mClkDiv << 5);
287     u16ClkCtrl = (u16ClkCtrl & 0x1E3) | (bClkDiv << 2);
288 
289     I2C_WriteNAU8822(4,  u16AudIf);
290 
291     I2C_WriteNAU8822(6,  u16ClkCtrl);
292 
293     return RT_EOK;
294 }
295 
nau8822_init(void)296 static rt_err_t nau8822_init(void)
297 {
298     //input source is MIC
299     if (nu_acodec_ops_nau8822.role == NU_ACODEC_ROLE_MASTER)
300     {
301         I2C_WriteNAU8822(1,  0x03F);   /* PLLEN, MICBIASEN, ABIASEN, IOBUFEN, REFIMP(3kohm)  */
302     }
303     else
304     {
305         I2C_WriteNAU8822(1,  0x01F);   /* MICBIASEN, ABIASEN, IOBUFEN, REFIMP(3kohm)  */
306     }
307 
308     I2C_WriteNAU8822(2,  0x1BF);   /* Enable L/R Headphone, ADC Mix/Boost, ADC */
309     I2C_WriteNAU8822(3,  0x07F);   /* Enable L/R main mixer, DAC */
310     I2C_WriteNAU8822(4,  0x010);   /* 16-bit word length, I2S format, Stereo */
311     I2C_WriteNAU8822(5,  0x000);   /* Companding control and loop back mode (all disable) */
312     nau8822_delay_ms(30);
313 
314     I2C_WriteNAU8822(6,  0x1AD);   /* Divide by 6, 16K */
315     I2C_WriteNAU8822(7,  0x006);   /* 16K for internal filter coefficients */
316     I2C_WriteNAU8822(10, 0x008);   /* DAC soft mute is disabled, DAC oversampling rate is 128x */
317     I2C_WriteNAU8822(14, 0x108);   /* ADC HP filter is disabled, ADC oversampling rate is 128x */
318     I2C_WriteNAU8822(15, 0x1EF);   /* ADC left digital volume control */
319     I2C_WriteNAU8822(16, 0x1EF);   /* ADC right digital volume control */
320     I2C_WriteNAU8822(44, 0x033);   /* LMICN/LMICP is connected to PGA */
321     I2C_WriteNAU8822(47, 0x100);   /* Gain value */
322     I2C_WriteNAU8822(48, 0x100);   /* Gain value */
323     I2C_WriteNAU8822(50, 0x001);   /* Left DAC connected to LMIX */
324     I2C_WriteNAU8822(51, 0x001);   /* Right DAC connected to RMIX */
325 
326     I2C_WriteNAU8822(0x34, 0x13F);
327     I2C_WriteNAU8822(0x35, 0x13F);
328 
329     nu_acodec_ops_nau8822.config.samplerate = 16000;
330     nu_acodec_ops_nau8822.config.channels = 2;
331     nu_acodec_ops_nau8822.config.samplebits = 16;
332 
333     LOG_I("Initialized done.\n");
334 
335     return RT_EOK;
336 }
337 
nau8822_dsp_control(struct rt_audio_configure * config)338 static rt_err_t nau8822_dsp_control(struct rt_audio_configure *config)
339 {
340     rt_err_t result = RT_EOK;
341     RT_ASSERT(config != RT_NULL);
342 
343     if (rt_memcmp((void *)config, (void *)&nu_acodec_ops_nau8822.config, sizeof(struct rt_audio_configure)) != 0)
344     {
345         if ((result = nau8822_dsp_config(config->samplerate, config->channels, config->samplebits)) == RT_EOK)
346             rt_memcpy((void *)&nu_acodec_ops_nau8822.config, (void *)config, sizeof(struct rt_audio_configure)) ;
347     }
348     return result;
349 }
350 
nau8822_mixer_control(rt_uint32_t ui32Units,rt_uint32_t ui32Value)351 static rt_err_t nau8822_mixer_control(rt_uint32_t ui32Units, rt_uint32_t ui32Value)
352 {
353     switch (ui32Units)
354     {
355     case AUDIO_MIXER_MUTE:
356     {
357         uint16_t u16Data;
358         I2C_ReadNAU8822(10, &u16Data);
359         if (ui32Value)
360         {
361             I2C_WriteNAU8822(10,  u16Data | (1 << 6));
362             nau8822_phonejack_set(g_psCodecConfig, 0);
363         }
364         else
365         {
366             I2C_WriteNAU8822(10,  u16Data & ~(1 << 6));
367             nau8822_phonejack_set(g_psCodecConfig, 1);
368         }
369     }
370     break;
371     case AUDIO_MIXER_VOLUME:
372     {
373         uint8_t u8GAIN = 256 * ui32Value / 100;
374         I2C_WriteNAU8822(11,  0x100 | u8GAIN);
375         I2C_WriteNAU8822(12,  0x100 | u8GAIN);
376 
377         u8GAIN = 0x3F * ui32Value / 100;
378         I2C_WriteNAU8822(54,  0x100 | u8GAIN);
379         I2C_WriteNAU8822(55,  0x100 | u8GAIN);
380     }
381     break;
382     case AUDIO_MIXER_QUERY:
383     case AUDIO_MIXER_BASS:
384     case AUDIO_MIXER_MID:
385     case AUDIO_MIXER_TREBLE:
386     case AUDIO_MIXER_EQUALIZER:
387     case AUDIO_MIXER_LINE:
388     case AUDIO_MIXER_DIGITAL:
389     case AUDIO_MIXER_MIC:
390     case AUDIO_MIXER_VITURAL:
391     case AUDIO_MIXER_EXTEND:
392     default:
393         return -RT_ERROR;
394     }
395 
396     return RT_EOK;
397 }
398 
nau8822_mixer_query(rt_uint32_t ui32Units,rt_uint32_t * pui32Value)399 static rt_err_t nau8822_mixer_query(rt_uint32_t ui32Units, rt_uint32_t *pui32Value)
400 {
401     RT_ASSERT(pui32Value != RT_NULL);
402     rt_uint16_t u16RV = 0;
403 
404     switch (ui32Units)
405     {
406     case AUDIO_MIXER_QUERY:
407         *pui32Value = AUDIO_MIXER_VOLUME | AUDIO_MIXER_MUTE;
408         break;
409 
410     case AUDIO_MIXER_MUTE:
411         I2C_ReadNAU8822(10, (uint16_t *)&u16RV);
412         if (u16RV & (1 << 6))
413             *pui32Value = 1;
414         else
415             *pui32Value = 0;
416         break;
417 
418     case AUDIO_MIXER_VOLUME:
419         I2C_ReadNAU8822(11, (uint16_t *)&u16RV);
420         *pui32Value = u16RV * 100 / 256;
421         break;
422 
423     case AUDIO_MIXER_BASS:
424     case AUDIO_MIXER_MID:
425     case AUDIO_MIXER_TREBLE:
426     case AUDIO_MIXER_EQUALIZER:
427     case AUDIO_MIXER_LINE:
428     case AUDIO_MIXER_DIGITAL:
429     case AUDIO_MIXER_MIC:
430     case AUDIO_MIXER_VITURAL:
431     case AUDIO_MIXER_EXTEND:
432     default:
433         return -RT_ERROR;
434     }
435     return RT_EOK;
436 }
437 
nu_hw_nau8822_init(S_NU_NAU8822_CONFIG * psCodecConfig)438 int nu_hw_nau8822_init(S_NU_NAU8822_CONFIG *psCodecConfig)
439 {
440     RT_ASSERT(psCodecConfig != RT_NULL);
441     struct rt_i2c_bus_device *psI2cBusDev;
442     struct rt_audio_device *psAudioDev;
443     nu_i2s_t psNuI2s;
444 
445     /* Find I2C bus */
446     psI2cBusDev = (struct rt_i2c_bus_device *)rt_device_find(psCodecConfig->i2c_bus_name);
447     if (psI2cBusDev == RT_NULL)
448     {
449         LOG_E("Can't found I2C bus - %s..!\n", psCodecConfig->i2c_bus_name);
450         goto exit_rt_hw_nau8822_init;
451     }
452 
453     /* Find I2S bus */
454     psAudioDev = (struct rt_audio_device *)rt_device_find(psCodecConfig->i2s_bus_name);
455     if (psAudioDev == RT_NULL)
456     {
457         LOG_E("Can't found I2S bus - %s ..!\n", psCodecConfig->i2s_bus_name);
458         goto exit_rt_hw_nau8822_init;
459     }
460 
461     if (nau8822_probe() != RT_EOK)
462     {
463         LOG_E("Can't found audio codec..!\n");
464         goto exit_rt_hw_nau8822_init;
465     }
466 
467     /* Store this board setting. */
468     g_psCodecConfig = psCodecConfig;
469     g_I2cBusDev = psI2cBusDev;
470 
471     /* Get NuI2S device instance. */
472     psNuI2s = (nu_i2s_t)psAudioDev;
473 
474     /* Register Acodec Ops */
475     psNuI2s->AcodecOps = &nu_acodec_ops_nau8822;
476 
477     /* Use Acodec default settings. */
478     rt_memcpy(&psNuI2s->config, &nu_acodec_ops_nau8822.config, sizeof(struct rt_audio_configure));
479 
480     return RT_EOK;
481 
482 exit_rt_hw_nau8822_init:
483 
484     return -RT_ERROR;
485 }
486 
487 #endif //#if defined(NU_PKG_USING_NAU8822)
488