acodec_nau8822.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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. #include <rtconfig.h>
  13. #if defined(NU_PKG_USING_NAU8822)
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include "acodec_nau8822.h"
  17. #include "drv_i2s.h"
  18. #define DBG_ENABLE
  19. #define DBG_LEVEL DBG_LOG
  20. #define DBG_SECTION_NAME "acodec.nau8822"
  21. #define DBG_COLOR
  22. #include <rtdbg.h>
  23. #define DEF_NAU8822_ADDR 0x1A
  24. static struct rt_i2c_bus_device *g_I2cBusDev = NULL;
  25. S_NU_NAU8822_CONFIG *g_psCodecConfig = NULL;
  26. static rt_err_t nau8822_init(void);
  27. static rt_err_t nau8822_reset(void);
  28. static rt_err_t nau8822_dsp_control(struct rt_audio_configure *config);
  29. static rt_err_t nau8822_mixer_control(rt_uint32_t ui32Units, rt_uint32_t ui32Value);
  30. static rt_err_t nau8822_mixer_query(rt_uint32_t ui32Units, rt_uint32_t *ui32Value);
  31. nu_acodec_ops nu_acodec_ops_nau8822 =
  32. {
  33. .name = "NAU8822",
  34. .role = NU_ACODEC_ROLE_MASTER,
  35. .config = { // Default settings.
  36. .samplerate = 16000,
  37. .channels = 2,
  38. .samplebits = 16
  39. },
  40. .nu_acodec_init = nau8822_init,
  41. .nu_acodec_reset = nau8822_reset,
  42. .nu_acodec_dsp_control = nau8822_dsp_control,
  43. .nu_acodec_mixer_control = nau8822_mixer_control,
  44. .nu_acodec_mixer_query = nau8822_mixer_query
  45. };
  46. static void nau8822_delay_ms(rt_uint32_t nms)
  47. {
  48. rt_thread_mdelay(nms);
  49. }
  50. static int I2C_ReadNAU8822(uint8_t u8addr, uint16_t *pu16data)
  51. {
  52. struct rt_i2c_msg msgs[2];
  53. uint8_t u8TxData = (u8addr << 1);
  54. RT_ASSERT(g_I2cBusDev != NULL);
  55. RT_ASSERT(pu16data != NULL);
  56. msgs[0].addr = DEF_NAU8822_ADDR; /* Slave address */
  57. msgs[0].flags = RT_I2C_WR; /* Write flag */
  58. msgs[0].buf = (rt_uint8_t *)&u8TxData; /* Number of bytes sent */
  59. msgs[0].len = sizeof(u8TxData); /* Number of bytes read */
  60. msgs[1].addr = DEF_NAU8822_ADDR; /* Slave address */
  61. msgs[1].flags = RT_I2C_RD; /* Read flag */
  62. msgs[1].buf = (rt_uint8_t *)pu16data; /* Read data pointer */
  63. msgs[1].len = 2; /* Number of bytes read */
  64. if (rt_i2c_transfer(g_I2cBusDev, &msgs[0], 2) != 2)
  65. {
  66. return -RT_ERROR;
  67. }
  68. return RT_EOK;
  69. }
  70. static int I2C_WriteNAU8822(uint8_t u8addr, uint16_t u16data)
  71. {
  72. /* Write 9-bit data to 7-bit address register of NAU8822 */
  73. struct rt_i2c_msg msg;
  74. uint8_t au8TxData[2];
  75. RT_ASSERT(g_I2cBusDev != NULL);
  76. au8TxData[0] = (uint8_t)((u8addr << 1) | (u16data >> 8)); //u8addr [7:1] | u16data [8]
  77. au8TxData[1] = (uint8_t)(u16data & 0x00FF); //data [7:0]
  78. msg.addr = DEF_NAU8822_ADDR; /* Slave address */
  79. msg.flags = RT_I2C_WR; /* Write flag */
  80. msg.buf = (rt_uint8_t *)&au8TxData[0]; /* Slave register address */
  81. msg.len = sizeof(au8TxData); /* Number of bytes sent */
  82. if (g_I2cBusDev && rt_i2c_transfer(g_I2cBusDev, &msg, 1) != 1)
  83. {
  84. rt_kprintf("[Failed] addr=%x, data=%d\n", u8addr, u16data);
  85. return -RT_ERROR;
  86. }
  87. {
  88. /* Verify */
  89. uint8_t au8RxData[2];
  90. I2C_ReadNAU8822(u8addr, (uint16_t *)&au8RxData[0]);
  91. rt_kprintf("Wrote addr %02x -> 0x%04x, read back -> 0x%02x%02x\n", u8addr, u16data, au8RxData[0], au8RxData[1]);
  92. }
  93. return RT_EOK;
  94. }
  95. static void nau8822_phonejack_set(S_NU_NAU8822_CONFIG *psCodecConfig, int bEnable)
  96. {
  97. rt_pin_mode(psCodecConfig->pin_phonejack_en, PIN_MODE_OUTPUT);
  98. if (bEnable)
  99. {
  100. rt_pin_write(psCodecConfig->pin_phonejack_en, PIN_LOW);
  101. }
  102. else
  103. {
  104. rt_pin_write(psCodecConfig->pin_phonejack_en, PIN_HIGH);
  105. }
  106. }
  107. static rt_err_t nau8822_probe(void)
  108. {
  109. return RT_EOK;
  110. }
  111. static rt_err_t nau8822_reset(void)
  112. {
  113. I2C_WriteNAU8822(0, 0x000); /* Reset all registers */
  114. nau8822_delay_ms(30);
  115. LOG_I("Software Reset.\n");
  116. return RT_EOK;
  117. }
  118. static rt_err_t nau8822_dsp_config(rt_uint32_t ui32SamplRate, rt_uint8_t u8ChNum, rt_uint8_t u8SamplBit)
  119. {
  120. uint8_t bClkDiv;
  121. uint8_t mClkDiv;
  122. uint16_t u16AudIf = 0x010; /* I2S, 16-bit */
  123. uint16_t u16ClkCtrl;
  124. uint8_t u8WLEN;
  125. if (ui32SamplRate > 48000)
  126. return -RT_ERROR;
  127. if (u8ChNum == 2)
  128. {
  129. u16AudIf = (u16AudIf & 0x1FE) | 0x0;
  130. }
  131. else
  132. {
  133. u16AudIf = (u16AudIf & 0x1FE) | 0x1;
  134. }
  135. /* Force to set Channel number to 2 */
  136. u8ChNum = 2;
  137. switch (u8SamplBit)
  138. {
  139. case 16:
  140. u8WLEN = 0x0;
  141. break;
  142. case 20:
  143. u8WLEN = 0x1;
  144. break;
  145. case 24:
  146. u8WLEN = 0x2;
  147. break;
  148. case 32:
  149. u8WLEN = 0x3;
  150. break;
  151. default:
  152. LOG_E("sample rate not match!\n");
  153. return -RT_ERROR;
  154. }
  155. u16AudIf = (u16AudIf & 0x19F) | (u8WLEN << 5);
  156. if (ui32SamplRate % 11025)
  157. {
  158. I2C_WriteNAU8822(36, 0x008); //12.288Mhz
  159. I2C_WriteNAU8822(37, 0x00C);
  160. I2C_WriteNAU8822(38, 0x093);
  161. I2C_WriteNAU8822(39, 0x0E9);
  162. /* FIXME */
  163. if (ui32SamplRate > 48000)
  164. ui32SamplRate = 8000;
  165. mClkDiv = (48000 * 256 * u8ChNum) / (ui32SamplRate * 256);
  166. bClkDiv = (ui32SamplRate * 256) / (ui32SamplRate * u8ChNum * u8SamplBit);
  167. }
  168. else
  169. {
  170. I2C_WriteNAU8822(36, 0x007); //11.2896Mhz
  171. I2C_WriteNAU8822(37, 0x021);
  172. I2C_WriteNAU8822(38, 0x161);
  173. I2C_WriteNAU8822(39, 0x026);
  174. /* FIXME */
  175. if (ui32SamplRate > 44100)
  176. ui32SamplRate = 11025;
  177. mClkDiv = (44100 * 256 * u8ChNum) / (ui32SamplRate * 256);
  178. bClkDiv = (ui32SamplRate * 256) / (ui32SamplRate * u8ChNum * u8SamplBit);
  179. }
  180. switch (mClkDiv)
  181. {
  182. case 1:
  183. mClkDiv = 0;
  184. break;
  185. case 2:
  186. mClkDiv = 2;
  187. break;
  188. case 3:
  189. mClkDiv = 3;
  190. break;
  191. case 4:
  192. mClkDiv = 4;
  193. break;
  194. case 6:
  195. mClkDiv = 5;
  196. break;
  197. case 8:
  198. mClkDiv = 6;
  199. break;
  200. case 12:
  201. mClkDiv = 7;
  202. break;
  203. default:
  204. LOG_E("mclk divider not match!\n");
  205. mClkDiv = 0;
  206. return -RT_ERROR;
  207. }
  208. switch (bClkDiv)
  209. {
  210. case 1:
  211. bClkDiv = 0;
  212. break;
  213. case 2:
  214. bClkDiv = 1;
  215. break;
  216. case 4:
  217. bClkDiv = 2;
  218. break;
  219. case 8:
  220. bClkDiv = 3;
  221. break;
  222. case 16:
  223. bClkDiv = 4;
  224. break;
  225. case 32:
  226. bClkDiv = 5;
  227. break;
  228. default:
  229. LOG_E("bclk divider not match!\n");
  230. bClkDiv = 0;
  231. return -RT_ERROR;
  232. }
  233. if (nu_acodec_ops_nau8822.role == NU_ACODEC_ROLE_MASTER)
  234. {
  235. u16ClkCtrl = (1 << 8) | (1 << 0); //Use internal PLL, FS/BCLK
  236. }
  237. u16ClkCtrl = (u16ClkCtrl & 0x11F) | (mClkDiv << 5);
  238. u16ClkCtrl = (u16ClkCtrl & 0x1E3) | (bClkDiv << 2);
  239. I2C_WriteNAU8822(4, u16AudIf);
  240. I2C_WriteNAU8822(6, u16ClkCtrl);
  241. return RT_EOK;
  242. }
  243. static rt_err_t nau8822_init(void)
  244. {
  245. //input source is MIC
  246. if (nu_acodec_ops_nau8822.role == NU_ACODEC_ROLE_MASTER)
  247. {
  248. I2C_WriteNAU8822(1, 0x03F); /* PLLEN, MICBIASEN, ABIASEN, IOBUFEN, REFIMP(3kohm) */
  249. }
  250. else
  251. {
  252. I2C_WriteNAU8822(1, 0x01F); /* MICBIASEN, ABIASEN, IOBUFEN, REFIMP(3kohm) */
  253. }
  254. I2C_WriteNAU8822(2, 0x1BF); /* Enable L/R Headphone, ADC Mix/Boost, ADC */
  255. I2C_WriteNAU8822(3, 0x07F); /* Enable L/R main mixer, DAC */
  256. I2C_WriteNAU8822(4, 0x010); /* 16-bit word length, I2S format, Stereo */
  257. I2C_WriteNAU8822(5, 0x000); /* Companding control and loop back mode (all disable) */
  258. nau8822_delay_ms(30);
  259. I2C_WriteNAU8822(6, 0x1AD); /* Divide by 6, 16K */
  260. I2C_WriteNAU8822(7, 0x006); /* 16K for internal filter coefficients */
  261. I2C_WriteNAU8822(10, 0x008); /* DAC soft mute is disabled, DAC oversampling rate is 128x */
  262. I2C_WriteNAU8822(14, 0x108); /* ADC HP filter is disabled, ADC oversampling rate is 128x */
  263. I2C_WriteNAU8822(15, 0x1EF); /* ADC left digital volume control */
  264. I2C_WriteNAU8822(16, 0x1EF); /* ADC right digital volume control */
  265. I2C_WriteNAU8822(44, 0x033); /* LMICN/LMICP is connected to PGA */
  266. I2C_WriteNAU8822(47, 0x100); /* Gain value */
  267. I2C_WriteNAU8822(48, 0x100); /* Gain value */
  268. I2C_WriteNAU8822(50, 0x001); /* Left DAC connected to LMIX */
  269. I2C_WriteNAU8822(51, 0x001); /* Right DAC connected to RMIX */
  270. I2C_WriteNAU8822(0x34, 0x13F);
  271. I2C_WriteNAU8822(0x35, 0x13F);
  272. nu_acodec_ops_nau8822.config.samplerate = 16000;
  273. nu_acodec_ops_nau8822.config.channels = 2;
  274. nu_acodec_ops_nau8822.config.samplebits = 16;
  275. LOG_I("Initialized done.\n");
  276. return RT_EOK;
  277. }
  278. static rt_err_t nau8822_dsp_control(struct rt_audio_configure *config)
  279. {
  280. rt_err_t result = RT_EOK;
  281. RT_ASSERT(config != RT_NULL);
  282. if (rt_memcmp((void *)config, (void *)&nu_acodec_ops_nau8822.config, sizeof(struct rt_audio_configure)) != 0)
  283. {
  284. if ((result = nau8822_dsp_config(config->samplerate, config->channels, config->samplebits)) == RT_EOK)
  285. rt_memcpy((void *)&nu_acodec_ops_nau8822.config, (void *)config, sizeof(struct rt_audio_configure)) ;
  286. }
  287. return result;
  288. }
  289. static rt_err_t nau8822_mixer_control(rt_uint32_t ui32Units, rt_uint32_t ui32Value)
  290. {
  291. switch (ui32Units)
  292. {
  293. case AUDIO_MIXER_MUTE:
  294. {
  295. uint16_t u16Data;
  296. I2C_ReadNAU8822(10, &u16Data);
  297. if (ui32Value)
  298. {
  299. I2C_WriteNAU8822(10, u16Data | (1 << 6));
  300. nau8822_phonejack_set(g_psCodecConfig, 0);
  301. }
  302. else
  303. {
  304. I2C_WriteNAU8822(10, u16Data & ~(1 << 6));
  305. nau8822_phonejack_set(g_psCodecConfig, 1);
  306. }
  307. }
  308. break;
  309. case AUDIO_MIXER_VOLUME:
  310. {
  311. uint8_t u8GAIN = 256 * ui32Value / 100;
  312. I2C_WriteNAU8822(11, 0x100 | u8GAIN);
  313. I2C_WriteNAU8822(12, 0x100 | u8GAIN);
  314. u8GAIN = 0x3F * ui32Value / 100;
  315. I2C_WriteNAU8822(54, 0x100 | u8GAIN);
  316. I2C_WriteNAU8822(55, 0x100 | u8GAIN);
  317. }
  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 nau8822_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_ReadNAU8822(10, (uint16_t *)&u16RV);
  345. if (u16RV & (1 << 6))
  346. *pui32Value = 1;
  347. else
  348. *pui32Value = 0;
  349. break;
  350. case AUDIO_MIXER_VOLUME:
  351. I2C_ReadNAU8822(11, (uint16_t *)&u16RV);
  352. *pui32Value = u16RV * 100 / 256;
  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_nau8822_init(S_NU_NAU8822_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_nau8822_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_nau8822_init;
  387. }
  388. if (nau8822_probe() != RT_EOK)
  389. {
  390. LOG_E("Can't found audio codec..!\n");
  391. goto exit_rt_hw_nau8822_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_nau8822;
  400. /* Use Acodec default settings. */
  401. rt_memcpy(&psNuI2s->config, &nu_acodec_ops_nau8822.config, sizeof(struct rt_audio_configure));
  402. return RT_EOK;
  403. exit_rt_hw_nau8822_init:
  404. return -RT_ERROR;
  405. }
  406. #endif //#if defined(NU_PKG_USING_NAU8822)