1
0

drv_sai.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  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. * 2018-4-30 misonyo the first version.
  9. */
  10. #include <rtthread.h>
  11. #include <rthw.h>
  12. #include <rtdef.h>
  13. #ifdef BSP_USING_AUDIO
  14. #define LOG_TAG "drv.sai"
  15. #include <drv_log.h>
  16. #include <rtdevice.h>
  17. #include "drivers/audio.h"
  18. #include "bsp_wm8960.h"
  19. #include "drv_i2c.h"
  20. #include "drv_sai.h"
  21. #define RX_DMA_FIFO_SIZE (2048)
  22. volatile rt_uint16_t rx_busy = 0;
  23. volatile rt_uint16_t tx_busy = 0;
  24. struct drv_sai sai_tx = {0};
  25. struct drv_sai sai_rx = {0};
  26. wm8960_config_t wm8960Config = {
  27. .route = kWM8960_RoutePlaybackandRecord,
  28. .rightInputSource = kWM8960_InputDifferentialMicInput2,
  29. .playSource = kWM8960_PlaySourceDAC,
  30. .slaveAddress = WM8960_I2C_ADDR,
  31. .bus = kWM8960_BusI2S,
  32. .format = {.mclk_HZ = 6144000U, .sampleRate = kWM8960_AudioSampleRate16KHz, .bitWidth = kWM8960_AudioBitWidth16bit},
  33. .master_slave = false,
  34. };
  35. const clock_audio_pll_config_t audioPllConfig =
  36. {
  37. .loopDivider = 32, /* PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
  38. .postDivider = 1, /* Divider after the PLL, should only be 1, 2, 4, 8, 16. */
  39. .numerator = 77, /* 30 bit numerator of fractional loop divider. */
  40. .denominator = 100, /* 30 bit denominator of fractional loop divider */
  41. };
  42. sai_transfer_format_t format;
  43. sai_config_t config;
  44. sai_transfer_t xfer;
  45. struct imxrt_sai
  46. {
  47. struct rt_audio_device audio;
  48. struct rt_audio_configure play_config;
  49. rt_uint16_t volume;
  50. rt_uint8_t* tx_fifo;
  51. struct rt_i2c_bus_device* i2c_bus;
  52. rt_uint8_t* rx_fifo;
  53. };
  54. struct imxrt_sai imxrt_payer_dev = { 0 };
  55. static void sai_config(void)
  56. {
  57. #ifdef BSP_AUDIO_USING_DMA
  58. static struct saidma_tx_config sai_txdma = { .channel = 0U, .request = kDmaRequestMuxSai1Tx };
  59. sai_tx.dma_tx = &sai_txdma;
  60. sai_tx.dma_flag |= RT_DEVICE_FLAG_DMA_TX;
  61. #if defined (BSP_USING_AUDIO_RECORD)
  62. static struct saidma_rx_config sai_rxdma = { .channel = 1U, .request = kDmaRequestMuxSai1Rx };
  63. sai_rx.dma_rx = &sai_rxdma;
  64. #endif
  65. #endif
  66. }
  67. static void sai_TxDmaCallback(I2S_Type* base, sai_edma_handle_t* handle, rt_int32_t status, void* userData)
  68. {
  69. tx_busy = 1;
  70. rt_audio_tx_complete(&imxrt_payer_dev.audio);
  71. }
  72. #if defined (BSP_USING_AUDIO_RECORD)
  73. static void sai_RxDmaCallback(I2S_Type* base, sai_edma_handle_t* handle, rt_int32_t status, void* userData)
  74. {
  75. rx_busy = 1;
  76. rt_audio_rx_done(&imxrt_payer_dev.audio, &imxrt_payer_dev.rx_fifo[0], RX_DMA_FIFO_SIZE / 2);
  77. }
  78. #endif
  79. void BOARD_EnableSaiMclkOutput(rt_bool_t enable)
  80. {
  81. if(enable)
  82. {
  83. IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK;
  84. }
  85. else
  86. {
  87. IOMUXC_GPR->GPR1 &= (~IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK);
  88. }
  89. }
  90. void sai_format(void)
  91. {
  92. SAI_TransferTxCreateHandleEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, sai_TxDmaCallback, NULL, &sai_tx.dma_tx->edma);
  93. SAI_TransferTxSetFormatEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, &format, DEMO_SAI_CLK_FREQ, DEMO_SAI_CLK_FREQ);
  94. #if defined (BSP_USING_AUDIO_RECORD)
  95. SAI_TransferRxCreateHandleEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle, sai_RxDmaCallback, NULL, &sai_rx.dma_rx->edma);
  96. SAI_TransferRxSetFormatEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle, &format, DEMO_SAI_CLK_FREQ, DEMO_SAI_CLK_FREQ);
  97. #endif
  98. }
  99. void sai_init(void)
  100. {
  101. CLOCK_InitAudioPll(&audioPllConfig);
  102. CLOCK_SetMux(kCLOCK_Sai1Mux, DEMO_SAI1_CLOCK_SOURCE_SELECT);
  103. CLOCK_SetDiv(kCLOCK_Sai1PreDiv, DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER);
  104. CLOCK_SetDiv(kCLOCK_Sai1Div, DEMO_SAI1_CLOCK_SOURCE_DIVIDER);
  105. BOARD_EnableSaiMclkOutput(RT_TRUE);
  106. EDMA_CreateHandle(&sai_tx.dma_tx->edma, DMA0, sai_tx.dma_tx->channel);
  107. DMAMUX_SetSource(DMAMUX, sai_tx.dma_tx->channel, (rt_uint8_t)sai_tx.dma_tx->request);
  108. DMAMUX_EnableChannel(DMAMUX, sai_tx.dma_tx->channel);
  109. SAI_TxGetDefaultConfig(&config);
  110. SAI_TxInit(sai_tx.base, &config);
  111. #if defined (BSP_USING_AUDIO_RECORD)
  112. EDMA_CreateHandle(&sai_rx.dma_rx->edma, DMA0, sai_rx.dma_rx->channel);
  113. DMAMUX_SetSource(DMAMUX, sai_rx.dma_rx->channel, (rt_uint8_t)sai_rx.dma_rx->request);
  114. DMAMUX_EnableChannel(DMAMUX, sai_rx.dma_rx->channel);
  115. SAI_RxGetDefaultConfig(&config);
  116. SAI_RxInit(sai_rx.base, &config);
  117. #endif
  118. format.bitWidth = kSAI_WordWidth16bits;
  119. format.channel = 0U;
  120. format.sampleRate_Hz = kSAI_SampleRate16KHz;
  121. format.masterClockHz = DEMO_SAI_CLK_FREQ;
  122. format.protocol = config.protocol;
  123. format.stereo = kSAI_Stereo;
  124. format.isFrameSyncCompact = true;
  125. format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
  126. SAI_TransferTxCreateHandleEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, sai_TxDmaCallback, NULL, &sai_tx.dma_tx->edma);
  127. SAI_TransferTxSetFormatEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, &format, DEMO_SAI_CLK_FREQ, DEMO_SAI_CLK_FREQ);
  128. #if defined (BSP_USING_AUDIO_RECORD)
  129. SAI_TransferRxCreateHandleEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle, sai_RxDmaCallback, NULL, &sai_rx.dma_rx->edma);
  130. SAI_TransferRxSetFormatEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle, &format, DEMO_SAI_CLK_FREQ, DEMO_SAI_CLK_FREQ);
  131. #endif
  132. }
  133. void SAI_samplerate_set(rt_uint32_t freq)
  134. {
  135. switch(freq)
  136. {
  137. case 48000:
  138. format.sampleRate_Hz = kSAI_SampleRate48KHz;
  139. break;
  140. case 44100:
  141. format.sampleRate_Hz = kSAI_SampleRate44100Hz;
  142. break;
  143. case 32000:
  144. format.sampleRate_Hz = kSAI_SampleRate32KHz;
  145. break;
  146. case 24000:
  147. format.sampleRate_Hz = kSAI_SampleRate24KHz;
  148. break;
  149. case 22050:
  150. format.sampleRate_Hz = kSAI_SampleRate22050Hz;
  151. break;
  152. case 16000:
  153. format.sampleRate_Hz = kSAI_SampleRate16KHz;
  154. break;
  155. case 12000:
  156. format.sampleRate_Hz = kSAI_SampleRate12KHz;
  157. break;
  158. case 11025:
  159. format.sampleRate_Hz = kSAI_SampleRate11025Hz;
  160. break;
  161. case 8000:
  162. format.sampleRate_Hz = kSAI_SampleRate8KHz;
  163. break;
  164. default:
  165. format.sampleRate_Hz = kSAI_SampleRate16KHz;
  166. break;
  167. }
  168. }
  169. void SAI_channels_set(rt_uint16_t channels)
  170. {
  171. switch(channels)
  172. {
  173. case 2:
  174. format.stereo = kSAI_Stereo;
  175. break;
  176. case 1:
  177. format.stereo = kSAI_MonoRight;
  178. break;
  179. case 0:
  180. format.stereo = kSAI_MonoLeft;
  181. break;
  182. default:
  183. format.stereo = kSAI_Stereo;
  184. break;
  185. }
  186. }
  187. void SAI_samplebits_set(rt_uint16_t samplebits)
  188. {
  189. switch(samplebits)
  190. {
  191. case 16:
  192. format.bitWidth = kSAI_WordWidth16bits;
  193. break;
  194. case 24:
  195. format.bitWidth = kSAI_WordWidth24bits;
  196. break;
  197. case 32:
  198. format.bitWidth = kSAI_WordWidth32bits;
  199. break;
  200. default:
  201. format.bitWidth = kSAI_WordWidth16bits;
  202. break;
  203. }
  204. }
  205. static rt_err_t imxrt_payer_getcaps(struct rt_audio_device* audio, struct rt_audio_caps* caps)
  206. {
  207. rt_err_t result = RT_EOK;
  208. RT_ASSERT(audio != RT_NULL);
  209. struct imxrt_sai* imxrt_audio = (struct imxrt_sai*)audio->parent.user_data;
  210. switch(caps->main_type)
  211. {
  212. case AUDIO_TYPE_QUERY: /* qurey the types of hw_codec device */
  213. {
  214. switch(caps->sub_type)
  215. {
  216. case AUDIO_TYPE_QUERY:
  217. caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER;
  218. break;
  219. default:
  220. result = -RT_ERROR;
  221. break;
  222. }
  223. break;
  224. }
  225. case AUDIO_TYPE_INPUT:
  226. {
  227. switch(caps->sub_type)
  228. {
  229. case AUDIO_DSP_PARAM:
  230. caps->udata.config.channels = imxrt_audio->play_config.channels;
  231. caps->udata.config.samplebits = imxrt_audio->play_config.samplebits;
  232. caps->udata.config.samplerate = imxrt_audio->play_config.samplerate;
  233. break;
  234. case AUDIO_DSP_SAMPLERATE:
  235. caps->udata.config.samplerate = imxrt_audio->play_config.samplerate;
  236. break;
  237. case AUDIO_DSP_CHANNELS:
  238. caps->udata.config.channels = imxrt_audio->play_config.channels;
  239. break;
  240. case AUDIO_DSP_SAMPLEBITS:
  241. caps->udata.config.samplebits = imxrt_audio->play_config.samplebits;
  242. break;
  243. default:
  244. result = -RT_ERROR;
  245. break;
  246. }
  247. break;
  248. }
  249. case AUDIO_TYPE_OUTPUT: /* Provide capabilities of OUTPUT unit */
  250. {
  251. switch(caps->sub_type)
  252. {
  253. case AUDIO_DSP_PARAM:
  254. caps->udata.config.samplerate = imxrt_audio->play_config.samplerate;
  255. caps->udata.config.channels = imxrt_audio->play_config.channels;
  256. caps->udata.config.samplebits = imxrt_audio->play_config.samplebits;
  257. break;
  258. case AUDIO_DSP_SAMPLERATE:
  259. caps->udata.config.samplerate = imxrt_audio->play_config.samplerate;
  260. break;
  261. case AUDIO_DSP_CHANNELS:
  262. caps->udata.config.channels = imxrt_audio->play_config.channels;
  263. break;
  264. case AUDIO_DSP_SAMPLEBITS:
  265. caps->udata.config.samplebits = imxrt_audio->play_config.samplebits;
  266. break;
  267. default:
  268. result = -RT_ERROR;
  269. break;
  270. }
  271. break;
  272. }
  273. case AUDIO_TYPE_MIXER: /* report the Mixer Units */
  274. {
  275. switch(caps->sub_type)
  276. {
  277. case AUDIO_MIXER_QUERY:
  278. caps->udata.mask = AUDIO_MIXER_VOLUME;
  279. break;
  280. case AUDIO_MIXER_VOLUME:
  281. caps->udata.value = WM8960_GetVolume(imxrt_payer_dev.i2c_bus,kWM8960_ModuleDAC);
  282. break;
  283. default:
  284. result = -RT_ERROR;
  285. break;
  286. }
  287. break;
  288. }
  289. default:
  290. result = -RT_ERROR;
  291. break;
  292. }
  293. return result;
  294. }
  295. static rt_err_t imxrt_payer_configure(struct rt_audio_device* audio, struct rt_audio_caps* caps)
  296. {
  297. rt_err_t result = RT_EOK;
  298. RT_ASSERT(audio != RT_NULL);
  299. struct imxrt_sai* imxrt_audio = (struct imxrt_sai*)audio->parent.user_data;
  300. switch(caps->main_type)
  301. {
  302. case AUDIO_TYPE_MIXER:
  303. {
  304. switch(caps->sub_type)
  305. {
  306. case AUDIO_MIXER_MUTE:
  307. {
  308. /* set mute mode */
  309. WM8960_SetMute(imxrt_payer_dev.i2c_bus, kWM8960_ModuleDAC, RT_FALSE);
  310. break;
  311. }
  312. case AUDIO_MIXER_VOLUME:
  313. {
  314. int volume = caps->udata.value;
  315. imxrt_audio->volume = volume;
  316. /* set mixer volume */
  317. WM8960_SetVolume(imxrt_payer_dev.i2c_bus, kWM8960_ModuleDAC, volume);
  318. break;
  319. }
  320. default:
  321. result = -RT_ERROR;
  322. break;
  323. }
  324. break;
  325. }
  326. case AUDIO_TYPE_OUTPUT:
  327. {
  328. switch(caps->sub_type)
  329. {
  330. case AUDIO_DSP_PARAM:
  331. {
  332. struct rt_audio_configure config = caps->udata.config;
  333. imxrt_audio->play_config.samplerate = config.samplerate;
  334. imxrt_audio->play_config.samplebits = config.samplebits;
  335. imxrt_audio->play_config.channels = config.channels;
  336. SAI_channels_set(config.channels);
  337. SAI_samplerate_set(config.samplerate);
  338. SAI_samplebits_set(config.samplebits);
  339. break;
  340. }
  341. case AUDIO_DSP_SAMPLERATE:
  342. {
  343. imxrt_audio->play_config.samplerate = caps->udata.config.samplerate;
  344. SAI_samplerate_set(caps->udata.config.samplerate);
  345. break;
  346. }
  347. case AUDIO_DSP_CHANNELS:
  348. {
  349. imxrt_audio->play_config.channels = caps->udata.config.channels;
  350. SAI_channels_set(caps->udata.config.channels);
  351. break;
  352. }
  353. case AUDIO_DSP_SAMPLEBITS:
  354. {
  355. imxrt_audio->play_config.samplebits = caps->udata.config.samplebits;
  356. SAI_samplebits_set(caps->udata.config.samplebits);
  357. break;
  358. }
  359. default:
  360. result = -RT_ERROR;
  361. break;
  362. }
  363. break;
  364. }
  365. case AUDIO_TYPE_INPUT:
  366. {
  367. switch(caps->sub_type)
  368. {
  369. case AUDIO_DSP_PARAM:
  370. {
  371. imxrt_audio->play_config.samplerate = caps->udata.config.samplerate;
  372. imxrt_audio->play_config.channels = caps->udata.config.channels;
  373. imxrt_audio->play_config.samplebits = caps->udata.config.samplebits;
  374. SAI_TransferTerminateReceiveEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle);
  375. SAI_samplerate_set(caps->udata.config.samplerate);
  376. SAI_channels_set(caps->udata.config.channels);
  377. SAI_samplebits_set(caps->udata.config.samplebits);
  378. break;
  379. }
  380. case AUDIO_DSP_SAMPLERATE:
  381. {
  382. imxrt_audio->play_config.samplerate = caps->udata.config.samplerate;
  383. SAI_samplerate_set(caps->udata.config.samplerate);
  384. break;
  385. }
  386. case AUDIO_DSP_CHANNELS:
  387. {
  388. imxrt_audio->play_config.channels = caps->udata.config.channels;
  389. SAI_channels_set(caps->udata.config.channels);
  390. break;
  391. }
  392. case AUDIO_DSP_SAMPLEBITS:
  393. {
  394. imxrt_audio->play_config.samplebits = caps->udata.config.samplebits;
  395. SAI_samplebits_set(caps->udata.config.samplebits);
  396. break;
  397. }
  398. default:
  399. result = -RT_ERROR;
  400. break;
  401. }
  402. /* After set config, MCLK will stop */
  403. SAI_TxSoftwareReset(sai_tx.base, kSAI_ResetTypeSoftware);
  404. SAI_RxSoftwareReset(sai_rx.base, kSAI_ResetTypeSoftware);
  405. xfer.data = imxrt_payer_dev.tx_fifo; // +i * (AUD_FIFO_SIZE / 4);
  406. xfer.dataSize = AUD_BLOCK_SIZE;
  407. SAI_TransferSendEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, &xfer);
  408. SAI_TransferReceiveEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle, &xfer);
  409. break;
  410. }
  411. default:
  412. break;
  413. }
  414. return result;
  415. }
  416. static rt_err_t imxrt_payer_init(struct rt_audio_device* audio)
  417. {
  418. RT_ASSERT(audio != RT_NULL);
  419. imxrt_payer_dev.i2c_bus = (struct rt_i2c_bus_device*)rt_device_find(CODEC_I2C_NAME);
  420. sai_init();
  421. return RT_EOK;
  422. }
  423. static rt_err_t imxrt_payer_start(struct rt_audio_device* audio, int stream)
  424. {
  425. RT_ASSERT(audio != RT_NULL);
  426. sai_format();
  427. WM8960_init(imxrt_payer_dev.i2c_bus, &wm8960Config);
  428. xfer.data = imxrt_payer_dev.rx_fifo;
  429. xfer.dataSize = AUD_BLOCK_SIZE;
  430. #if defined (BSP_USING_AUDIO_RECORD)
  431. SAI_TransferReceiveEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle, &xfer);
  432. #endif
  433. SAI_TransferSendEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, &xfer);
  434. return RT_EOK;
  435. }
  436. static rt_err_t imxrt_payer_stop(struct rt_audio_device* audio, int stream)
  437. {
  438. RT_ASSERT(audio != RT_NULL);
  439. SAI_TransferTerminateSendEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle);
  440. SAI_TransferTerminateReceiveEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle);
  441. WM8960_Deinit(imxrt_payer_dev.i2c_bus);
  442. return RT_EOK;
  443. }
  444. static rt_size_t imxrt_payer_transmit(struct rt_audio_device* audio, const void* writeBuf, void* readBuf, rt_size_t size)
  445. {
  446. RT_ASSERT(audio != RT_NULL);
  447. #if defined (BSP_USING_AUDIO_RECORD)
  448. xfer.data = imxrt_payer_dev.rx_fifo;
  449. xfer.dataSize = RX_DMA_FIFO_SIZE;
  450. SAI_TransferReceiveEDMA(sai_rx.base, &sai_rx.dma_rx->rxHandle, &xfer);
  451. SAI_TransferSendEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, &xfer);
  452. #else
  453. xfer.data = (rt_uint8_t*)writeBuf;
  454. xfer.dataSize = size;
  455. SAI_TransferSendEDMA(sai_tx.base, &sai_tx.dma_tx->txHandle, &xfer);
  456. #endif
  457. return size;
  458. }
  459. static void imxrt_payer_buffer_info(struct rt_audio_device* audio, struct rt_audio_buf_info* info)
  460. {
  461. RT_ASSERT(audio != RT_NULL);
  462. /**
  463. * AUD_FIFO
  464. * +----------------+----------------+
  465. * | block1 | block2 |
  466. * +----------------+----------------+
  467. * \ block_size /
  468. */
  469. info->buffer = imxrt_payer_dev.tx_fifo;
  470. info->total_size = AUD_DMA_FIFO_SIZE;
  471. info->block_size = AUD_DMA_FIFO_SIZE / 2;
  472. info->block_count = 2;
  473. }
  474. static struct rt_audio_ops imxrt_payer_ops =
  475. {
  476. .getcaps = imxrt_payer_getcaps,
  477. .configure = imxrt_payer_configure,
  478. .init = imxrt_payer_init,
  479. .start = imxrt_payer_start,
  480. .stop = imxrt_payer_stop,
  481. .transmit = imxrt_payer_transmit,
  482. .buffer_info = imxrt_payer_buffer_info,
  483. };
  484. int rt_hw_sound_init(void)
  485. {
  486. rt_uint8_t* tx_fifo = RT_NULL;
  487. rt_uint8_t* rx_fifo = RT_NULL;
  488. sai_tx.base = SAI1;
  489. sai_rx.base = SAI1;
  490. sai_tx.irqn = SAI1_IRQn;
  491. sai_config();
  492. tx_fifo = rt_calloc(1, AUD_DMA_FIFO_SIZE);
  493. rx_fifo = rt_calloc(1, AUD_DMA_FIFO_SIZE);
  494. if(tx_fifo == RT_NULL)
  495. {
  496. return -RT_ENOMEM;
  497. }
  498. rt_memset(tx_fifo, 0, AUD_DMA_FIFO_SIZE);
  499. imxrt_payer_dev.tx_fifo = tx_fifo;
  500. rt_memset(rx_fifo, 0, AUD_DMA_FIFO_SIZE);
  501. imxrt_payer_dev.rx_fifo = rx_fifo;
  502. imxrt_payer_dev.audio.ops = &imxrt_payer_ops;
  503. rt_audio_register(&imxrt_payer_dev.audio, "mic", RT_DEVICE_FLAG_RDWR, &imxrt_payer_dev);
  504. return RT_EOK;
  505. }
  506. INIT_DEVICE_EXPORT(rt_hw_sound_init);
  507. #endif /* BSP_USING_AUDIO*/