drv_sound.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-07-31 Zero-Free first implementation
  9. * 2020-07-02 thread-liu Porting for STM32MP1
  10. */
  11. #include "board.h"
  12. #ifdef BSP_USING_AUDIO
  13. #include "drv_wm8994.h"
  14. #include <dfs_posix.h>
  15. #define DRV_DEBUG
  16. #define LOG_TAG "drv.sound"
  17. #include <drv_log.h>
  18. #define SOUND_BUS_NAME "i2c2"
  19. #define TX_FIFO_SIZE (4096)
  20. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  21. __attribute__((at(0x2FFC2000))) static rt_uint8_t AUDIO_TX_FIFO[TX_FIFO_SIZE];
  22. #elif defined ( __GNUC__ )
  23. static rt_uint8_t AUDIO_TX_FIFO[TX_FIFO_SIZE] __attribute__((section(".AudioSection")));
  24. #elif defined(__ICCARM__)
  25. #pragma location = 0x2FFC2000
  26. __no_init static rt_uint8_t AUDIO_TX_FIFO[TX_FIFO_SIZE];
  27. #endif
  28. struct sound_device
  29. {
  30. struct rt_audio_device audio;
  31. struct rt_audio_configure replay_config;
  32. rt_device_t decoder;
  33. rt_uint8_t *tx_fifo;
  34. rt_uint8_t volume;
  35. };
  36. static struct sound_device snd_dev = {0};
  37. SAI_HandleTypeDef hsai_BlockA2 = {0};
  38. extern DMA_HandleTypeDef hdma_sai2_a;
  39. static void rt_hw_sai2a_init(void)
  40. {
  41. hsai_BlockA2.Instance = SAI2_Block_A;
  42. hsai_BlockA2.Init.Protocol = SAI_FREE_PROTOCOL;
  43. hsai_BlockA2.Init.AudioMode = SAI_MODEMASTER_TX;
  44. hsai_BlockA2.Init.DataSize = SAI_DATASIZE_16;
  45. hsai_BlockA2.Init.FirstBit = SAI_FIRSTBIT_MSB;
  46. hsai_BlockA2.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
  47. hsai_BlockA2.Init.Synchro = SAI_ASYNCHRONOUS;
  48. hsai_BlockA2.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
  49. hsai_BlockA2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
  50. hsai_BlockA2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
  51. hsai_BlockA2.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K;
  52. hsai_BlockA2.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
  53. hsai_BlockA2.Init.MonoStereoMode = SAI_STEREOMODE;
  54. hsai_BlockA2.Init.CompandingMode = SAI_NOCOMPANDING;
  55. hsai_BlockA2.Init.TriState = SAI_OUTPUT_NOTRELEASED;
  56. hsai_BlockA2.Init.PdmInit.Activation = DISABLE;
  57. hsai_BlockA2.Init.PdmInit.MicPairsNbr = 0;
  58. hsai_BlockA2.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
  59. hsai_BlockA2.FrameInit.FrameLength = 64;
  60. hsai_BlockA2.FrameInit.ActiveFrameLength = 32;
  61. hsai_BlockA2.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
  62. hsai_BlockA2.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
  63. hsai_BlockA2.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
  64. hsai_BlockA2.SlotInit.FirstBitOffset = 0;
  65. hsai_BlockA2.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
  66. hsai_BlockA2.SlotInit.SlotNumber = 2;
  67. hsai_BlockA2.SlotInit.SlotActive = (SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1 | SAI_SLOTACTIVE_2 | SAI_SLOTACTIVE_3);
  68. if(HAL_OK != HAL_SAI_Init(&hsai_BlockA2))
  69. {
  70. Error_Handler();
  71. }
  72. /* Enable SAI to generate clock used by audio driver */
  73. __HAL_SAI_ENABLE(&hsai_BlockA2);
  74. }
  75. void DMA1_Stream0_IRQHandler(void)
  76. {
  77. HAL_DMA_IRQHandler(&hdma_sai2_a);
  78. }
  79. void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
  80. {
  81. if (hsai == &hsai_BlockA2)
  82. {
  83. rt_audio_tx_complete(&snd_dev.audio);
  84. }
  85. }
  86. void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
  87. {
  88. if (hsai == &hsai_BlockA2)
  89. {
  90. rt_audio_tx_complete(&snd_dev.audio);
  91. }
  92. }
  93. void SAIA_Frequency_Set(uint32_t frequency)
  94. {
  95. /* Disable SAI peripheral to allow access to SAI internal registers */
  96. __HAL_SAI_DISABLE(&hsai_BlockA2);
  97. /* Update the SAI audio frequency configuration */
  98. hsai_BlockA2.Init.AudioFrequency = frequency;
  99. HAL_SAI_Init(&hsai_BlockA2);
  100. /* Enable SAI peripheral to generate MCLK */
  101. __HAL_SAI_ENABLE(&hsai_BlockA2);
  102. }
  103. void SAIA_Channels_Set(uint8_t channels)
  104. {
  105. if (channels == 1)
  106. {
  107. hsai_BlockA2.Init.MonoStereoMode = SAI_MONOMODE;
  108. }
  109. else
  110. {
  111. hsai_BlockA2.Init.MonoStereoMode = SAI_STEREOMODE;
  112. }
  113. __HAL_SAI_DISABLE(&hsai_BlockA2);
  114. HAL_SAI_Init(&hsai_BlockA2);
  115. __HAL_SAI_ENABLE(&hsai_BlockA2);
  116. }
  117. /**
  118. * RT-Thread Audio Device Driver Interface
  119. */
  120. static rt_err_t sound_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  121. {
  122. rt_err_t result = RT_EOK;
  123. struct sound_device *snd_dev;
  124. RT_ASSERT(audio != RT_NULL);
  125. snd_dev = (struct sound_device *)audio->parent.user_data;
  126. switch (caps->main_type)
  127. {
  128. case AUDIO_TYPE_QUERY: /* qurey the types of hw_codec device */
  129. {
  130. switch (caps->sub_type)
  131. {
  132. case AUDIO_TYPE_QUERY:
  133. caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER;
  134. break;
  135. default:
  136. result = -RT_ERROR;
  137. break;
  138. }
  139. break;
  140. }
  141. case AUDIO_TYPE_OUTPUT: /* Provide capabilities of OUTPUT unit */
  142. {
  143. switch (caps->sub_type)
  144. {
  145. case AUDIO_DSP_PARAM:
  146. caps->udata.config.samplerate = snd_dev->replay_config.samplerate;
  147. caps->udata.config.channels = snd_dev->replay_config.channels;
  148. caps->udata.config.samplebits = snd_dev->replay_config.samplebits;
  149. break;
  150. case AUDIO_DSP_SAMPLERATE:
  151. caps->udata.config.samplerate = snd_dev->replay_config.samplerate;
  152. break;
  153. case AUDIO_DSP_CHANNELS:
  154. caps->udata.config.channels = snd_dev->replay_config.channels;
  155. break;
  156. case AUDIO_DSP_SAMPLEBITS:
  157. caps->udata.config.samplebits = snd_dev->replay_config.samplebits;
  158. break;
  159. default:
  160. result = -RT_ERROR;
  161. break;
  162. }
  163. break;
  164. }
  165. case AUDIO_TYPE_MIXER: /* report the Mixer Units */
  166. {
  167. switch (caps->sub_type)
  168. {
  169. case AUDIO_MIXER_QUERY:
  170. caps->udata.mask = AUDIO_MIXER_VOLUME;
  171. break;
  172. case AUDIO_MIXER_VOLUME:
  173. rt_device_control(snd_dev->decoder, GET_VOLUME, &(caps->udata.value));
  174. break;
  175. default:
  176. result = -RT_ERROR;
  177. break;
  178. }
  179. break;
  180. }
  181. default:
  182. result = -RT_ERROR;
  183. break;
  184. }
  185. return result;
  186. }
  187. static rt_err_t sound_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  188. {
  189. rt_err_t result = RT_EOK;
  190. struct sound_device *snd_dev;
  191. RT_ASSERT(audio != RT_NULL);
  192. snd_dev = (struct sound_device *)audio->parent.user_data;
  193. switch (caps->main_type)
  194. {
  195. case AUDIO_TYPE_MIXER:
  196. {
  197. switch (caps->sub_type)
  198. {
  199. case AUDIO_MIXER_VOLUME:
  200. {
  201. rt_uint8_t volume = caps->udata.value;
  202. rt_device_control(snd_dev->decoder, SET_VOLUME, &volume);
  203. snd_dev->volume = volume;
  204. LOG_D("set volume %d", volume);
  205. break;
  206. }
  207. default:
  208. result = -RT_ERROR;
  209. break;
  210. }
  211. break;
  212. }
  213. case AUDIO_TYPE_OUTPUT:
  214. {
  215. switch (caps->sub_type)
  216. {
  217. case AUDIO_DSP_PARAM:
  218. {
  219. /* set samplerate */
  220. SAIA_Frequency_Set(caps->udata.config.samplerate);
  221. /* set channels */
  222. SAIA_Channels_Set(caps->udata.config.channels);
  223. /* save configs */
  224. snd_dev->replay_config.samplerate = caps->udata.config.samplerate;
  225. snd_dev->replay_config.channels = caps->udata.config.channels;
  226. snd_dev->replay_config.samplebits = caps->udata.config.samplebits;
  227. LOG_D("set samplerate %d", snd_dev->replay_config.samplerate);
  228. break;
  229. }
  230. case AUDIO_DSP_SAMPLERATE:
  231. {
  232. SAIA_Frequency_Set(caps->udata.config.samplerate);
  233. snd_dev->replay_config.samplerate = caps->udata.config.samplerate;
  234. LOG_D("set samplerate %d", snd_dev->replay_config.samplerate);
  235. break;
  236. }
  237. case AUDIO_DSP_CHANNELS:
  238. {
  239. SAIA_Channels_Set(caps->udata.config.channels);
  240. snd_dev->replay_config.channels = caps->udata.config.channels;
  241. LOG_D("set channels %d", snd_dev->replay_config.channels);
  242. break;
  243. }
  244. case AUDIO_DSP_SAMPLEBITS:
  245. {
  246. /* not support */
  247. snd_dev->replay_config.samplebits = caps->udata.config.samplebits;
  248. break;
  249. }
  250. default:
  251. result = -RT_ERROR;
  252. break;
  253. }
  254. break;
  255. }
  256. default:
  257. break;
  258. }
  259. return result;
  260. }
  261. static rt_err_t sound_init(struct rt_audio_device *audio)
  262. {
  263. rt_err_t result = RT_EOK;
  264. struct sound_device *snd_dev;
  265. rt_uint16_t play_type = OUTPUT_DEVICE_HEADPHONE;
  266. RT_ASSERT(audio != RT_NULL);
  267. snd_dev = (struct sound_device *)audio->parent.user_data;
  268. rt_hw_sai2a_init();
  269. /* set default params */
  270. SAIA_Frequency_Set(snd_dev->replay_config.samplerate);
  271. SAIA_Channels_Set(snd_dev->replay_config.channels);
  272. /* set audio play type */
  273. rt_device_control(snd_dev->decoder, SET_PLAY_TYPE, &play_type);
  274. /* open lowlevel audio device */
  275. rt_device_open(snd_dev->decoder, RT_DEVICE_OFLAG_WRONLY);
  276. rt_device_init(snd_dev->decoder);
  277. /* check device id */
  278. result = rt_device_control(snd_dev->decoder, GET_ID, RT_NULL);
  279. if (result != RT_EOK)
  280. {
  281. LOG_E("can't find low level audio device!");
  282. return RT_ERROR;
  283. }
  284. return result;
  285. }
  286. static rt_err_t sound_start(struct rt_audio_device *audio, int stream)
  287. {
  288. struct sound_device *snd_dev;
  289. rt_uint16_t play_type = OUTPUT_DEVICE_HEADPHONE;
  290. RT_ASSERT(audio != RT_NULL);
  291. snd_dev = (struct sound_device *)audio->parent.user_data;
  292. if (stream == AUDIO_STREAM_REPLAY)
  293. {
  294. LOG_D("open sound device");
  295. rt_device_control(snd_dev->decoder, SET_PLAY_TYPE, &play_type);
  296. rt_device_control(snd_dev->decoder, START_PLAY, RT_NULL);
  297. if (HAL_SAI_Transmit_DMA(&hsai_BlockA2, snd_dev->tx_fifo, TX_FIFO_SIZE / 2) != HAL_OK)
  298. {
  299. return RT_ERROR;
  300. }
  301. }
  302. return RT_EOK;
  303. }
  304. static rt_err_t sound_stop(struct rt_audio_device *audio, int stream)
  305. {
  306. RT_ASSERT(audio != RT_NULL);
  307. if (stream == AUDIO_STREAM_REPLAY)
  308. {
  309. HAL_SAI_DMAStop(&hsai_BlockA2);
  310. LOG_D("close sound device");
  311. }
  312. return RT_EOK;
  313. }
  314. static void sound_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info)
  315. {
  316. struct sound_device *device;
  317. RT_ASSERT(audio != RT_NULL);
  318. device = (struct sound_device *)audio->parent.user_data;
  319. info->buffer = device->tx_fifo;
  320. info->total_size = TX_FIFO_SIZE;
  321. info->block_size = TX_FIFO_SIZE / 2;
  322. info->block_count = 2;
  323. }
  324. static struct rt_audio_ops snd_ops =
  325. {
  326. .getcaps = sound_getcaps,
  327. .configure = sound_configure,
  328. .init = sound_init,
  329. .start = sound_start,
  330. .stop = sound_stop,
  331. .transmit = RT_NULL,
  332. .buffer_info = sound_buffer_info,
  333. };
  334. int rt_hw_sound_init(void)
  335. {
  336. rt_err_t result = RT_EOK;
  337. struct rt_device *device = RT_NULL;
  338. rt_memset(AUDIO_TX_FIFO, 0, TX_FIFO_SIZE);
  339. snd_dev.tx_fifo = AUDIO_TX_FIFO;
  340. /* init default configuration */
  341. snd_dev.replay_config.samplerate = 44100;
  342. snd_dev.replay_config.channels = 2;
  343. snd_dev.replay_config.samplebits = 16;
  344. snd_dev.volume = 55;
  345. /* find lowlevel decoder device*/
  346. snd_dev.decoder = rt_device_find("decoder");
  347. if (snd_dev.decoder == RT_NULL)
  348. {
  349. LOG_E("cant't find lowlevel decoder deivce!");
  350. return RT_ERROR;
  351. }
  352. /* register sound device */
  353. snd_dev.audio.ops = &snd_ops;
  354. result = rt_audio_register(&snd_dev.audio, "sound0", RT_DEVICE_FLAG_WRONLY, &snd_dev);
  355. /* check sound device register success or not */
  356. if (result != RT_EOK)
  357. {
  358. device = &(snd_dev.audio.parent);
  359. rt_device_unregister(device);
  360. LOG_E("sound device init error!");
  361. return RT_ERROR;
  362. }
  363. return RT_EOK;
  364. }
  365. INIT_APP_EXPORT(rt_hw_sound_init);
  366. struct RIFF_HEADER_DEF
  367. {
  368. char riff_id[4]; // 'R','I','F','F'
  369. uint32_t riff_size;
  370. char riff_format[4]; // 'W','A','V','E'
  371. };
  372. struct WAVE_FORMAT_DEF
  373. {
  374. uint16_t FormatTag;
  375. uint16_t Channels;
  376. uint32_t SamplesPerSec;
  377. uint32_t AvgBytesPerSec;
  378. uint16_t BlockAlign;
  379. uint16_t BitsPerSample;
  380. };
  381. struct FMT_BLOCK_DEF
  382. {
  383. char fmt_id[4]; // 'f','m','t',' '
  384. uint32_t fmt_size;
  385. struct WAVE_FORMAT_DEF wav_format;
  386. };
  387. struct DATA_BLOCK_DEF
  388. {
  389. char data_id[4]; // 'R','I','F','F'
  390. uint32_t data_size;
  391. };
  392. struct wav_info
  393. {
  394. struct RIFF_HEADER_DEF header;
  395. struct FMT_BLOCK_DEF fmt_block;
  396. struct DATA_BLOCK_DEF data_block;
  397. };
  398. int wavplay_sample(int argc, char **argv)
  399. {
  400. #define BUFSZ 1024
  401. #define SOUND_DEVICE_NAME "sound0"
  402. static rt_device_t sound_dev;
  403. int fd = -1;
  404. uint8_t *buffer = NULL;
  405. struct wav_info *info = NULL;
  406. struct rt_audio_caps caps = {0};
  407. if (argc != 2)
  408. {
  409. rt_kprintf("Usage:\n");
  410. rt_kprintf("wavplay_sample song.wav\n");
  411. return 0;
  412. }
  413. fd = open(argv[1], O_WRONLY);
  414. if (fd < 0)
  415. {
  416. rt_kprintf("open file failed!\n");
  417. goto __exit;
  418. }
  419. buffer = rt_malloc(BUFSZ);
  420. if (buffer == RT_NULL)
  421. goto __exit;
  422. info = (struct wav_info *) rt_malloc(sizeof * info);
  423. if (info == RT_NULL)
  424. goto __exit;
  425. if (read(fd, &(info->header), sizeof(struct RIFF_HEADER_DEF)) <= 0)
  426. goto __exit;
  427. if (read(fd, &(info->fmt_block), sizeof(struct FMT_BLOCK_DEF)) <= 0)
  428. goto __exit;
  429. if (read(fd, &(info->data_block), sizeof(struct DATA_BLOCK_DEF)) <= 0)
  430. goto __exit;
  431. rt_kprintf("wav information:\n");
  432. rt_kprintf("samplerate %d\n", info->fmt_block.wav_format.SamplesPerSec);
  433. rt_kprintf("channel %d\n", info->fmt_block.wav_format.Channels);
  434. sound_dev = rt_device_find(SOUND_DEVICE_NAME);
  435. rt_device_open(sound_dev, RT_DEVICE_OFLAG_WRONLY);
  436. caps.main_type = AUDIO_TYPE_OUTPUT;
  437. caps.sub_type = AUDIO_DSP_PARAM;
  438. caps.udata.config.samplerate = info->fmt_block.wav_format.SamplesPerSec;
  439. caps.udata.config.channels = info->fmt_block.wav_format.Channels;
  440. caps.udata.config.samplebits = 16;
  441. rt_device_control(sound_dev, AUDIO_CTL_CONFIGURE, &caps);
  442. while (1)
  443. {
  444. int length;
  445. length = read(fd, buffer, BUFSZ);
  446. if (length <= 0)
  447. break;
  448. rt_device_write(sound_dev, 0, buffer, length);
  449. }
  450. rt_device_close(sound_dev);
  451. __exit:
  452. if (fd >= 0)
  453. close(fd);
  454. if (buffer)
  455. rt_free(buffer);
  456. if (info)
  457. rt_free(info);
  458. return 0;
  459. }
  460. MSH_CMD_EXPORT(wavplay_sample, play wav file);
  461. #endif