acodec_nau88l25.c 14 KB

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