drv_sound.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /*
  2. * Copyright (c) 2020-2021, Bluetrum Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Date Author Notes
  7. * 2020-12-12 greedyhao first implementation
  8. */
  9. #include <board.h>
  10. #define DBG_TAG "drv.snd_dev"
  11. #define DBG_LVL DBG_INFO
  12. #include <rtdbg.h>
  13. #define SAI_AUDIO_FREQUENCY_48K ((uint32_t)48000u)
  14. #define SAI_AUDIO_FREQUENCY_44K ((uint32_t)44100u)
  15. #define SAI_AUDIO_FREQUENCY_38K ((uint32_t)38000u)
  16. #define TX_FIFO_SIZE (1024)
  17. struct sound_device
  18. {
  19. struct rt_audio_device audio;
  20. struct rt_audio_configure replay_config;
  21. rt_sem_t semaphore;
  22. rt_thread_t thread;
  23. rt_uint8_t *tx_fifo;
  24. rt_uint8_t *rx_fifo;
  25. rt_uint8_t volume;
  26. rt_uint8_t dma_to_aubuf;
  27. };
  28. static struct sound_device snd_dev = {0};
  29. //apll = 采样率*ADPLL_DIV*512
  30. //audio pll init
  31. void adpll_init(uint8_t out_spr)
  32. {
  33. PLL1CON &= ~(BIT(16) | BIT(17)); //PLL1 refclk select xosc26m
  34. CLKCON2 &= ~(BIT(4)| BIT(5) | BIT(6) | BIT(7));
  35. PLL1CON &= ~(BIT(3) | BIT(4) | BIT(5));
  36. PLL1CON |= BIT(3); //Select PLL/VCO frequency band (PLL大于206M vcos = 0x01, 否则为0)
  37. PLL1CON |= BIT(12); //enable pll1 ldo
  38. hal_mdelay(1);
  39. PLL1CON |= BIT(18); //pll1 sdm enable
  40. if (out_spr) {
  41. CLKCON2 |= BIT(4) | BIT(7); //adpll_div = 10
  42. PLL1DIV = (245.76 * 65536) / 26; //245.76Mhz for 48K
  43. // sys.aupll_type = 1;
  44. } else {
  45. CLKCON2 |= BIT(5) | BIT(7); //adpll_div = 11
  46. PLL1DIV = (248.3712 * 65536) / 26; //248.3712MHz for 44.1k
  47. // sys.aupll_type = 0;
  48. }
  49. hal_mdelay(1);
  50. PLL1CON |= BIT(20); //update pll1div
  51. PLL1CON |= BIT(6); //enable analog pll1
  52. hal_mdelay(1); //wait pll1 stable
  53. }
  54. void dac_start(void)
  55. {
  56. AUANGCON0 |= BIT(0) | BIT(1) | BIT(3); // bg ldoh bias enable
  57. AUANGCON0 &= ~(BIT(6)|BIT(5)|BIT(4)); // LDOH voltage select:3bit
  58. AUANGCON0 |= (3<<4); // 2.4/2.5/2.7/2.9/3.1/3.2
  59. AUANGCON0 |= BIT(2); // LDOL enable
  60. AUANGCON0 |= BIT(9); //VCM enable
  61. AUANGCON0 &= ~(BIT(13)|BIT(12)); // VCM voltage select, 2bit
  62. AUANGCON0 |= (2<<12);
  63. AUANGCON0 |= BIT(15) | BIT(16) | BIT(17) | BIT(18); // d2a lpf audpa audpa_dly
  64. AUANGCON0 &= ~BIT(11); //VCM type: 0-->res divider with off-chip cap; 1-->internal VCM
  65. //AUANGCON0 |= BIT(11);
  66. AUANGCON0 &= ~BIT(19); // dac type: 0-->SC; 1-->SR
  67. //AUANGCON0 |= BIT(19);
  68. AUANGCON0 |= BIT(20); // pa type: 0-->diff; 1-->3.3V single
  69. AUANGCON3 &= ~(0x7<<4); //BIT[6:4]=PA_GF[2:0]
  70. AUANGCON3 |= (0<<4);
  71. AUANGCON3 &= ~(0xf); //BIT[3:0]=PA_GX[3:0]
  72. AUANGCON3 |= 0;
  73. AUANGCON3 &= ~(0xF<<8); //BIT[11:8]=PA2_GX[3:0]
  74. AUANGCON3 |= (0<<8);
  75. AUANGCON3 &= ~(0x7<<12); //BIT[14:12]=PA2_GF[2:0]
  76. AUANGCON3 |= (0<<12);
  77. AUANGCON1 |= BIT(0) | BIT(1); // dac enable: BIT(0)-->right channel; BIT(1)-->left channel
  78. //AUANGCON1 &= ~BIT(1); //disable left channel
  79. AUANGCON1 |= BIT(12); // lpf2pa enable
  80. AUANGCON1 &= ~BIT(29); // vcmbuf enable: 0-->disable
  81. //AUANGCON1 |= BIT(29);
  82. //AUANGCON1 |= BIT(30); // mirror enable
  83. //AUANGCON2 |= BIT(29) | BIT(30); // adc mute
  84. //AUANGCON1 |= BIT(3); // pa mute
  85. }
  86. rt_section(".irq.audio")
  87. void audio_sem_post(void)
  88. {
  89. rt_sem_release(snd_dev.semaphore);
  90. }
  91. void audio_sem_pend(void)
  92. {
  93. rt_sem_take(snd_dev.semaphore, RT_WAITING_FOREVER);
  94. }
  95. void saia_frequency_set(uint32_t frequency)
  96. {
  97. DACDIGCON0 &= ~(0xf << 2);
  98. if (frequency == SAI_AUDIO_FREQUENCY_48K) {
  99. DACDIGCON0 |= (0 << 2);
  100. } else if (frequency == SAI_AUDIO_FREQUENCY_44K) {
  101. DACDIGCON0 |= (1 << 2);
  102. } else if (frequency == SAI_AUDIO_FREQUENCY_38K) {
  103. DACDIGCON0 |= (2 << 2);
  104. }
  105. DACDIGCON0 |= BIT(6);
  106. }
  107. void saia_channels_set(uint8_t channels)
  108. {
  109. LOG_D("saia_channels_set=%d", channels);
  110. if (channels == 1) {
  111. AU0LMIXCOEF = 0x00007FFF;
  112. AU1LMIXCOEF = 0x00007FFF;
  113. DACDIGCON0 |= BIT(7);
  114. DACDIGCON0 |= BIT(8);
  115. AUANGCON1 &= ~BIT(0);
  116. } else {
  117. AUANGCON1 |= BIT(0);
  118. DACDIGCON0 &= ~BIT(7);
  119. DACDIGCON0 &= ~BIT(8);
  120. }
  121. }
  122. void saia_volume_set(rt_uint8_t volume)
  123. {
  124. if (volume > 100)
  125. volume = 100;
  126. uint32_t dvol = volume * 327; // max is 0x7ffff
  127. LOG_D("dvol=0x%x", dvol);
  128. DACVOLCON = dvol | (0x02 << 16); // dac fade in
  129. }
  130. uint8_t saia_volume_get(void)
  131. {
  132. return ((DACVOLCON & 0xffff) / 327);
  133. }
  134. static rt_err_t sound_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  135. {
  136. rt_err_t result = RT_EOK;
  137. struct sound_device *snd_dev = RT_NULL;
  138. RT_ASSERT(audio != RT_NULL);
  139. snd_dev = (struct sound_device *)audio->parent.user_data;
  140. switch (caps->main_type)
  141. {
  142. case AUDIO_TYPE_QUERY: /* qurey the types of hw_codec device */
  143. {
  144. switch (caps->sub_type)
  145. {
  146. case AUDIO_TYPE_QUERY:
  147. caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER;
  148. break;
  149. default:
  150. result = -RT_ERROR;
  151. break;
  152. }
  153. break;
  154. }
  155. case AUDIO_TYPE_OUTPUT: /* Provide capabilities of OUTPUT unit */
  156. {
  157. switch (caps->sub_type)
  158. {
  159. case AUDIO_DSP_PARAM:
  160. caps->udata.config.samplerate = snd_dev->replay_config.samplerate;
  161. caps->udata.config.channels = snd_dev->replay_config.channels;
  162. caps->udata.config.samplebits = snd_dev->replay_config.samplebits;
  163. break;
  164. case AUDIO_DSP_SAMPLERATE:
  165. caps->udata.config.samplerate = snd_dev->replay_config.samplerate;
  166. break;
  167. case AUDIO_DSP_CHANNELS:
  168. caps->udata.config.channels = snd_dev->replay_config.channels;
  169. break;
  170. case AUDIO_DSP_SAMPLEBITS:
  171. caps->udata.config.samplebits = snd_dev->replay_config.samplebits;
  172. break;
  173. default:
  174. result = -RT_ERROR;
  175. break;
  176. }
  177. break;
  178. }
  179. case AUDIO_TYPE_MIXER: /* report the Mixer Units */
  180. {
  181. switch (caps->sub_type)
  182. {
  183. case AUDIO_MIXER_QUERY:
  184. caps->udata.mask = AUDIO_MIXER_VOLUME;
  185. break;
  186. case AUDIO_MIXER_VOLUME:
  187. caps->udata.value = saia_volume_get();
  188. break;
  189. default:
  190. result = -RT_ERROR;
  191. break;
  192. }
  193. break;
  194. }
  195. default:
  196. result = -RT_ERROR;
  197. break;
  198. }
  199. return RT_EOK;
  200. }
  201. static rt_err_t sound_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  202. {
  203. rt_err_t result = RT_EOK;
  204. struct sound_device *snd_dev = RT_NULL;
  205. RT_ASSERT(audio != RT_NULL);
  206. snd_dev = (struct sound_device *)audio->parent.user_data;
  207. switch (caps->main_type)
  208. {
  209. case AUDIO_TYPE_MIXER:
  210. {
  211. switch (caps->sub_type)
  212. {
  213. case AUDIO_MIXER_VOLUME:
  214. {
  215. rt_uint8_t volume = caps->udata.value;
  216. saia_volume_set(volume);
  217. snd_dev->volume = volume;
  218. LOG_D("set volume %d", volume);
  219. break;
  220. }
  221. case AUDIO_MIXER_EXTEND:
  222. snd_dev->dma_to_aubuf = caps->udata.value;
  223. break;
  224. default:
  225. result = -RT_ERROR;
  226. break;
  227. }
  228. break;
  229. }
  230. case AUDIO_TYPE_OUTPUT:
  231. {
  232. switch (caps->sub_type)
  233. {
  234. case AUDIO_DSP_PARAM:
  235. {
  236. /* set samplerate */
  237. saia_frequency_set(caps->udata.config.samplerate);
  238. /* set channels */
  239. saia_channels_set(caps->udata.config.channels);
  240. /* save configs */
  241. snd_dev->replay_config.samplerate = caps->udata.config.samplerate;
  242. snd_dev->replay_config.channels = caps->udata.config.channels;
  243. snd_dev->replay_config.samplebits = caps->udata.config.samplebits;
  244. LOG_D("set samplerate %d", snd_dev->replay_config.samplerate);
  245. break;
  246. }
  247. case AUDIO_DSP_SAMPLERATE:
  248. {
  249. saia_frequency_set(caps->udata.config.samplerate);
  250. snd_dev->replay_config.samplerate = caps->udata.config.samplerate;
  251. LOG_D("set samplerate %d", snd_dev->replay_config.samplerate);
  252. break;
  253. }
  254. case AUDIO_DSP_CHANNELS:
  255. {
  256. saia_channels_set(caps->udata.config.channels);
  257. snd_dev->replay_config.channels = caps->udata.config.channels;
  258. LOG_D("set channels %d", snd_dev->replay_config.channels);
  259. break;
  260. }
  261. case AUDIO_DSP_SAMPLEBITS:
  262. {
  263. /* not support */
  264. snd_dev->replay_config.samplebits = caps->udata.config.samplebits;
  265. break;
  266. }
  267. default:
  268. result = -RT_ERROR;
  269. break;
  270. }
  271. break;
  272. }
  273. default:
  274. break;
  275. }
  276. return RT_EOK;
  277. }
  278. static rt_err_t sound_init(struct rt_audio_device *audio)
  279. {
  280. struct sound_device *snd_dev = RT_NULL;
  281. RT_ASSERT(audio != RT_NULL);
  282. snd_dev = (struct sound_device *)audio->parent.user_data;
  283. adpll_init(0);
  284. dac_start();
  285. /* set default params */
  286. saia_frequency_set(snd_dev->replay_config.samplerate);
  287. saia_channels_set(snd_dev->replay_config.channels);
  288. saia_volume_set(snd_dev->volume);
  289. return RT_EOK;
  290. }
  291. static rt_err_t sound_start(struct rt_audio_device *audio, int stream)
  292. {
  293. struct sound_device *snd_dev = RT_NULL;
  294. RT_ASSERT(audio != RT_NULL);
  295. snd_dev = (struct sound_device *)audio->parent.user_data;
  296. if (stream == AUDIO_STREAM_REPLAY)
  297. {
  298. LOG_D("open sound device");
  299. AUBUFSIZE = (TX_FIFO_SIZE / 4 - 1);
  300. AUBUFSIZE |= (TX_FIFO_SIZE / 8) << 16;
  301. AUBUFSTARTADDR = DMA_ADR(snd_dev->rx_fifo);
  302. DACDIGCON0 |= BIT(0) | BIT(10); // (0x01<<2)
  303. AUBUFCON |= BIT(1);
  304. }
  305. return RT_EOK;
  306. }
  307. static rt_err_t sound_stop(struct rt_audio_device *audio, int stream)
  308. {
  309. RT_ASSERT(audio != RT_NULL);
  310. if (stream == AUDIO_STREAM_REPLAY)
  311. {
  312. LOG_D("close sound device");
  313. }
  314. return RT_EOK;
  315. }
  316. rt_size_t sound_transmit(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size)
  317. {
  318. struct sound_device *snd_dev = RT_NULL;
  319. rt_size_t tmp_size = size / 4;
  320. rt_size_t count = 0;
  321. RT_ASSERT(audio != RT_NULL);
  322. snd_dev = (struct sound_device *)audio->parent.user_data;
  323. while (tmp_size-- > 0) {
  324. if (AUBUFCON & BIT(8)) { // aubuf full
  325. AUBUFCON |= BIT(1) | BIT(4);
  326. audio_sem_pend();
  327. }
  328. AUBUFDATA = ((const uint32_t *)writeBuf)[count++];
  329. }
  330. return size;
  331. }
  332. static void sound_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info)
  333. {
  334. struct sound_device *snd_dev = RT_NULL;
  335. RT_ASSERT(audio != RT_NULL);
  336. snd_dev = (struct sound_device *)audio->parent.user_data;
  337. /**
  338. * TX_FIFO
  339. * +----------------+----------------+
  340. * | block1 | block2 |
  341. * +----------------+----------------+
  342. * \ block_size /
  343. */
  344. info->buffer = snd_dev->tx_fifo;
  345. info->total_size = TX_FIFO_SIZE;
  346. info->block_size = TX_FIFO_SIZE / 2;
  347. info->block_count = 2;
  348. }
  349. static struct rt_audio_ops ops =
  350. {
  351. .getcaps = sound_getcaps,
  352. .configure = sound_configure,
  353. .init = sound_init,
  354. .start = sound_start,
  355. .stop = sound_stop,
  356. .transmit = sound_transmit,
  357. .buffer_info = sound_buffer_info,
  358. };
  359. rt_section(".irq.audio")
  360. static void audio_isr(int vector, void *param)
  361. {
  362. rt_interrupt_enter();
  363. //Audio buffer pend
  364. if (AUBUFCON & BIT(5)) {
  365. AUBUFCON |= BIT(1); //Audio Buffer Pend Clear
  366. AUBUFCON &= ~BIT(4);
  367. audio_sem_post();
  368. }
  369. rt_interrupt_leave();
  370. }
  371. static void audio_thread_entry(void *parameter)
  372. {
  373. while (1)
  374. {
  375. if ((snd_dev.dma_to_aubuf == RT_FALSE) && (snd_dev.audio.replay->activated == RT_TRUE)) {
  376. rt_audio_tx_complete(&snd_dev.audio);
  377. } else {
  378. rt_thread_mdelay(50);
  379. }
  380. }
  381. }
  382. static int rt_hw_sound_init(void)
  383. {
  384. rt_uint8_t *tx_fifo = RT_NULL;
  385. rt_uint8_t *rx_fifo = RT_NULL;
  386. /* 分配 DMA 搬运 buffer */
  387. tx_fifo = rt_calloc(1, TX_FIFO_SIZE);
  388. if(tx_fifo == RT_NULL)
  389. {
  390. return -RT_ENOMEM;
  391. }
  392. snd_dev.tx_fifo = tx_fifo;
  393. /* 分配 DMA 搬运 buffer */
  394. rx_fifo = rt_calloc(1, TX_FIFO_SIZE);
  395. if(rx_fifo == RT_NULL)
  396. {
  397. return -RT_ENOMEM;
  398. }
  399. snd_dev.rx_fifo = rx_fifo;
  400. snd_dev.semaphore = rt_sem_create("snd", 0, RT_IPC_FLAG_FIFO);
  401. if (snd_dev.semaphore == RT_NULL)
  402. {
  403. return -RT_ENOMEM;
  404. }
  405. snd_dev.thread = rt_thread_create(
  406. "audio",
  407. audio_thread_entry,
  408. RT_NULL,
  409. 1024,
  410. 20, // must equal or lower than tshell priority
  411. 1
  412. );
  413. if (snd_dev.thread != RT_NULL)
  414. {
  415. rt_thread_startup(snd_dev.thread);
  416. }
  417. /* init default configuration */
  418. {
  419. snd_dev.replay_config.samplerate = SAI_AUDIO_FREQUENCY_48K;
  420. snd_dev.replay_config.channels = 2;
  421. snd_dev.replay_config.samplebits = 16;
  422. snd_dev.volume = 55;
  423. }
  424. /* register snd_dev device */
  425. snd_dev.audio.ops = &ops;
  426. rt_audio_register(&snd_dev.audio, "sound0", RT_DEVICE_FLAG_WRONLY, &snd_dev);
  427. rt_hw_interrupt_install(IRQ_AUBUF0_1_VECTOR, audio_isr, RT_NULL, "au_isr");
  428. return RT_EOK;
  429. }
  430. INIT_DEVICE_EXPORT(rt_hw_sound_init);