drv_sound.c 15 KB

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