hpm_i2s_drv.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. * Copyright (c) 2021-2023 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #ifndef HPM_I2S_DRV_H
  8. #define HPM_I2S_DRV_H
  9. #include "hpm_common.h"
  10. #include "hpm_soc_feature.h"
  11. #include "hpm_i2s_regs.h"
  12. #include "hpm_i2s_common.h"
  13. /**
  14. * @brief I2S driver APIs
  15. * @defgroup i2s_interface I2S driver APIs
  16. * @ingroup io_interfaces
  17. * @{
  18. */
  19. /* i2s channel slot mask */
  20. #define I2S_CHANNEL_SLOT_MASK(x) (1U << (x))
  21. /* convert audio depth value into CFGR[DATASIZ] value map */
  22. #define I2S_CFGR_DATASIZ(x) ((x - 16) >> 3)
  23. /* convert channel length value into CFGR[CHSIZ] value map */
  24. #define I2S_CFGR_CHSIZ(x) ((x - 16) >> 4)
  25. /**
  26. * @brief I2S data line
  27. */
  28. #define I2S_DATA_LINE_0 (0U)
  29. #define I2S_DATA_LINE_1 (1U)
  30. #define I2S_DATA_LINE_2 (2U)
  31. #define I2S_DATA_LINE_3 (3U)
  32. #define I2S_DATA_LINE_MAX I2S_DATA_LINE_3
  33. /**
  34. * @brief I2S config
  35. */
  36. typedef struct i2s_config {
  37. bool invert_mclk_out;
  38. bool invert_mclk_in;
  39. bool use_external_mclk;
  40. bool invert_bclk_out;
  41. bool invert_bclk_in;
  42. bool use_external_bclk;
  43. bool invert_fclk_out;
  44. bool invert_fclk_in;
  45. bool use_external_fclk;
  46. bool enable_mclk_out;
  47. bool frame_start_at_rising_edge;
  48. uint16_t fifo_threshold;
  49. } i2s_config_t;
  50. /**
  51. * @brief I2S transfer config
  52. */
  53. typedef struct i2x_transfer_config {
  54. uint32_t sample_rate;
  55. bool enable_tdm_mode;
  56. uint8_t channel_num_per_frame;
  57. uint8_t channel_length; /* 16-bit or 32-bit */
  58. uint8_t audio_depth; /* 16-bit, 24-bit, 32-bit */
  59. bool master_mode;
  60. uint8_t protocol;
  61. uint8_t data_line;
  62. uint32_t channel_slot_mask;
  63. } i2s_transfer_config_t;
  64. typedef enum {
  65. i2s_tx_fifo_threshold_irq_mask = I2S_CTRL_TXDNIE_MASK,
  66. i2s_rx_fifo_threshold_irq_mask = I2S_CTRL_RXDAIE_MASK,
  67. i2s_fifo_error_irq_mask = I2S_CTRL_ERRIE_MASK, /*<! rx fifo overrun, tx fifo underrun */
  68. } i2s_irq_mask_t;
  69. typedef enum {
  70. i2s_data_line_rx_fifo_avail = 1U, /*<! data avail */
  71. i2s_data_line_tx_fifo_avail = 2U, /*<! fifo empty avail */
  72. i2s_data_line_rx_fifo_overrun = 4U,
  73. i2s_data_line_tx_fifo_underrun = 8U,
  74. } i2s_data_line_stat_t;
  75. #ifdef __cplusplus
  76. extern "C" {
  77. #endif
  78. /**
  79. * @brief enable TDM
  80. *
  81. * @param [in] ptr I2S base address
  82. */
  83. static inline void i2s_enable_tdm(I2S_Type *ptr)
  84. {
  85. ptr->CFGR |= I2S_CFGR_TDM_EN_MASK;
  86. }
  87. /**
  88. * @brief disable TDM
  89. *
  90. * @param [in] ptr I2S base address
  91. */
  92. static inline void i2s_disable_tdm(I2S_Type *ptr)
  93. {
  94. ptr->CFGR &= ~I2S_CFGR_TDM_EN_MASK;
  95. }
  96. /**
  97. * @brief update rx fifo threshold
  98. *
  99. * @param [in] ptr I2S base address
  100. * @param [in] threshold fifo threshold value
  101. */
  102. static inline void i2s_update_rx_fifo_threshold(I2S_Type *ptr, uint8_t threshold)
  103. {
  104. ptr->FIFO_THRESH = (ptr->FIFO_THRESH & ~I2S_FIFO_THRESH_RX_MASK)
  105. | I2S_FIFO_THRESH_RX_SET(threshold);
  106. }
  107. /**
  108. * @brief update tx fifo threshold
  109. *
  110. * @param [in] ptr I2S base address
  111. * @param [in] threshold fifo threshold value
  112. */
  113. static inline void i2s_update_tx_fifo_threshold(I2S_Type *ptr, uint8_t threshold)
  114. {
  115. ptr->FIFO_THRESH = (ptr->FIFO_THRESH & ~I2S_FIFO_THRESH_TX_MASK)
  116. | I2S_FIFO_THRESH_TX_SET(threshold);
  117. }
  118. /**
  119. * @brief open BCLK
  120. *
  121. * @param [in] ptr I2S base address
  122. */
  123. static inline void i2s_ungate_bclk(I2S_Type *ptr)
  124. {
  125. ptr->CFGR &= ~I2S_CFGR_BCLK_GATEOFF_MASK;
  126. }
  127. /**
  128. * @brief gete off BCLK
  129. *
  130. * @param [in] ptr I2S base address
  131. */
  132. static inline void i2s_gate_bclk(I2S_Type *ptr)
  133. {
  134. ptr->CFGR |= I2S_CFGR_BCLK_GATEOFF_MASK;
  135. }
  136. /**
  137. * @brief open MCLK
  138. *
  139. * @param [in] ptr I2S base address
  140. */
  141. static inline void i2s_ungate_mclk(I2S_Type *ptr)
  142. {
  143. ptr->MISC_CFGR &= ~I2S_MISC_CFGR_MCLK_GATEOFF_MASK;
  144. }
  145. /**
  146. * @brief gate off MCLK
  147. *
  148. * @param [in] ptr I2S base address
  149. */
  150. static inline void i2s_gate_mclk(I2S_Type *ptr)
  151. {
  152. ptr->MISC_CFGR |= I2S_MISC_CFGR_MCLK_GATEOFF_MASK;
  153. }
  154. /**
  155. * @brief enable TX dma request
  156. *
  157. * @param [in] ptr I2S base address
  158. */
  159. static inline void i2s_enable_tx_dma_request(I2S_Type *ptr)
  160. {
  161. ptr->CTRL |= I2S_CTRL_TX_DMA_EN_MASK;
  162. }
  163. /**
  164. * @brief disable TX dma request
  165. *
  166. * @param [in] ptr I2S base address
  167. */
  168. static inline void i2s_disable_tx_dma_request(I2S_Type *ptr)
  169. {
  170. ptr->CTRL &= ~I2S_CTRL_TX_DMA_EN_MASK;
  171. }
  172. /**
  173. * @brief enable RX dma request
  174. *
  175. * @param [in] ptr I2S base address
  176. */
  177. static inline void i2s_enable_rx_dma_request(I2S_Type *ptr)
  178. {
  179. ptr->CTRL |= I2S_CTRL_RX_DMA_EN_MASK;
  180. }
  181. /**
  182. * @brief disable RX dma request
  183. *
  184. * @param [in] ptr I2S base address
  185. */
  186. static inline void i2s_disable_rx_dma_request(I2S_Type *ptr)
  187. {
  188. ptr->CTRL &= ~I2S_CTRL_RX_DMA_EN_MASK;
  189. }
  190. /**
  191. * @brief enable IRQ
  192. *
  193. * @param [in] ptr I2S base address
  194. * @param [in] mask irq bit mask
  195. */
  196. static inline void i2s_enable_irq(I2S_Type *ptr, uint32_t mask)
  197. {
  198. ptr->CTRL |= mask;
  199. }
  200. /**
  201. * @brief disable IRQ
  202. *
  203. * @param [in] ptr I2S base address
  204. * @param [in] mask irq bit mask
  205. */
  206. static inline void i2s_disable_irq(I2S_Type *ptr, uint32_t mask)
  207. {
  208. ptr->CTRL &= ~mask;
  209. }
  210. /**
  211. * @brief I2S enable
  212. *
  213. * @param [in] ptr I2S base address
  214. */
  215. static inline void i2s_enable(I2S_Type *ptr)
  216. {
  217. ptr->CTRL |= I2S_CTRL_I2S_EN_MASK;
  218. }
  219. /**
  220. * @brief I2S disable
  221. *
  222. * @param [in] ptr I2S base address
  223. */
  224. static inline void i2s_disable(I2S_Type *ptr)
  225. {
  226. ptr->CTRL &= ~I2S_CTRL_I2S_EN_MASK;
  227. }
  228. /**
  229. * @brief I2S enable rx function
  230. *
  231. * @param [in] ptr I2S base address
  232. * @param [in] rx_mask rx data line mask
  233. */
  234. static inline void i2s_enable_rx(I2S_Type *ptr, uint8_t rx_mask)
  235. {
  236. ptr->CTRL |= I2S_CTRL_RX_EN_SET(rx_mask);
  237. }
  238. /**
  239. * @brief I2S disable rx function
  240. *
  241. * @param [in] ptr I2S base address
  242. * @param [in] rx_mask rx data line mask
  243. */
  244. static inline void i2s_disable_rx(I2S_Type *ptr, uint8_t rx_mask)
  245. {
  246. ptr->CTRL &= ~I2S_CTRL_RX_EN_SET(rx_mask);
  247. }
  248. /**
  249. * @brief I2S enable tx function
  250. *
  251. * @param [in] ptr I2S base address
  252. * @param [in] tx_mask tx data line mask
  253. */
  254. static inline void i2s_enable_tx(I2S_Type *ptr, uint8_t tx_mask)
  255. {
  256. ptr->CTRL |= I2S_CTRL_TX_EN_SET(tx_mask);
  257. }
  258. /**
  259. * @brief I2S disbale tx function
  260. *
  261. * @param [in] ptr I2S base address
  262. * @param [in] tx_mask tx data line mask
  263. */
  264. static inline void i2s_disable_tx(I2S_Type *ptr, uint8_t tx_mask)
  265. {
  266. ptr->CTRL &= ~I2S_CTRL_TX_EN_SET(tx_mask);
  267. }
  268. /**
  269. * @brief I2S clear tx fifo
  270. *
  271. * @param [in] ptr I2S base address
  272. */
  273. static inline void i2s_clear_tx_fifo(I2S_Type *ptr)
  274. {
  275. ptr->CTRL |= I2S_CTRL_TXFIFOCLR_MASK;
  276. while (ptr->CTRL & I2S_CTRL_TXFIFOCLR_MASK) {
  277. }
  278. }
  279. /**
  280. * @brief I2S clear rx fifo
  281. *
  282. * @param [in] ptr I2S base address
  283. */
  284. static inline void i2s_clear_rx_fifo(I2S_Type *ptr)
  285. {
  286. ptr->CTRL |= I2S_CTRL_RXFIFOCLR_MASK;
  287. while (ptr->CTRL & I2S_CTRL_RXFIFOCLR_MASK) {
  288. }
  289. }
  290. /**
  291. * @brief I2S reset clock generator
  292. *
  293. * @param [in] ptr I2S base address
  294. */
  295. static inline void i2s_reset_clock_gen(I2S_Type *ptr)
  296. {
  297. ptr->CTRL |= I2S_CTRL_SFTRST_CLKGEN_MASK;
  298. ptr->CTRL &= ~I2S_CTRL_SFTRST_CLKGEN_MASK;
  299. }
  300. /**
  301. * @brief I2S reset tx function
  302. *
  303. * @param [in] ptr I2S base address
  304. */
  305. static inline void i2s_reset_tx(I2S_Type *ptr)
  306. {
  307. ptr->CTRL |= I2S_CTRL_SFTRST_TX_MASK;
  308. ptr->CTRL &= ~I2S_CTRL_SFTRST_TX_MASK;
  309. }
  310. /**
  311. * @brief I2S reset rx function
  312. *
  313. * @param [in] ptr I2S base address
  314. */
  315. static inline void i2s_reset_rx(I2S_Type *ptr)
  316. {
  317. ptr->CTRL |= I2S_CTRL_SFTRST_RX_MASK;
  318. ptr->CTRL &= ~I2S_CTRL_SFTRST_RX_MASK;
  319. }
  320. /**
  321. * @brief I2S get tx fifo level
  322. *
  323. * @param [in] ptr I2S base address
  324. *
  325. * @retval I2S tx fifo level
  326. */
  327. static inline uint32_t i2s_get_tx_fifo_level(I2S_Type *ptr)
  328. {
  329. return ptr->TFIFO_FILLINGS;
  330. }
  331. /**
  332. * @brief I2S get data line tx fifo level
  333. *
  334. * @param [in] ptr I2S base address
  335. * @param [in] line I2S data line
  336. *
  337. * @retval I2S data line tx fifo level
  338. */
  339. static inline uint32_t i2s_get_tx_line_fifo_level(I2S_Type *ptr, uint8_t line)
  340. {
  341. return (i2s_get_tx_fifo_level(ptr) & (0xFF << (line << 3))) >> (line << 3);
  342. }
  343. /**
  344. * @brief I2S get rx fifo level
  345. *
  346. * @param [in] ptr I2S base address
  347. *
  348. * @retval I2S rx fifo level
  349. */
  350. static inline uint32_t i2s_get_rx_fifo_level(I2S_Type *ptr)
  351. {
  352. return ptr->RFIFO_FILLINGS;
  353. }
  354. /**
  355. * @brief I2S get data line rx fifo level
  356. *
  357. * @param [in] ptr I2S base address
  358. * @param [in] line I2S data line
  359. *
  360. * @retval I2S data line rx fifo level
  361. */
  362. static inline uint32_t i2s_get_rx_line_fifo_level(I2S_Type *ptr, uint8_t line)
  363. {
  364. return (i2s_get_rx_fifo_level(ptr) & (0xFF << (line << 3))) >> (line << 3);
  365. }
  366. /**
  367. * @brief Check I2S data line status
  368. *
  369. * @param[in] ptr I2S base address
  370. * @param[in] line I2S data line
  371. *
  372. * @retval i2s_data_line_rx_fifo_avail data in rx fifo >= threshold
  373. * @retval i2s_data_line_tx_fifo_avail data in tx fifo <= threshold
  374. * @retval i2s_data_line_rx_fifo_overrun rx fifo overrun occured
  375. * @retval i2s_data_line_tx_fifo_underrun tx fifo underrun occured
  376. */
  377. static inline uint32_t i2s_check_data_line_status(I2S_Type *ptr, uint8_t line)
  378. {
  379. volatile uint32_t reg_val = ptr->STA;
  380. uint32_t bit_mask;
  381. uint32_t stat = 0;
  382. bit_mask = 1 << (I2S_STA_RX_DA_SHIFT + line);
  383. if ((bit_mask & reg_val) != 0) {
  384. stat |= i2s_data_line_rx_fifo_avail;
  385. }
  386. bit_mask = 1 << (I2S_STA_TX_DN_SHIFT + line);
  387. if ((bit_mask & reg_val) != 0) {
  388. stat |= i2s_data_line_tx_fifo_avail;
  389. }
  390. bit_mask = 1 << (I2S_STA_RX_OV_SHIFT + line);
  391. if ((bit_mask & reg_val) != 0) {
  392. stat |= i2s_data_line_rx_fifo_overrun;
  393. ptr->STA = bit_mask; /* clear flag: W1C*/
  394. }
  395. bit_mask = 1 << (I2S_STA_TX_UD_SHIFT + line);
  396. if ((bit_mask & reg_val) != 0) {
  397. stat |= i2s_data_line_tx_fifo_underrun;
  398. ptr->STA = bit_mask; /* clear flag: W1C*/
  399. }
  400. return stat;
  401. }
  402. /**
  403. * @brief I2S get IRQ status
  404. *
  405. * @param [in] ptr I2S base address
  406. *
  407. * @retval I2S STA register value
  408. */
  409. static inline uint32_t i2s_get_irq_status(I2S_Type *ptr)
  410. {
  411. return ptr->STA;
  412. }
  413. /**
  414. * @brief I2S stop transfer
  415. *
  416. * @param [in] ptr I2S base address
  417. */
  418. static inline void i2s_stop_transfer(I2S_Type *ptr)
  419. {
  420. i2s_disable(ptr);
  421. }
  422. /**
  423. * @brief I2S config tx
  424. *
  425. * @param [in] ptr I2S base address
  426. * @param [in] mclk_in_hz mclk frequency in Hz
  427. * @param [in] config i2s_transfer_config_t
  428. * @retval hpm_stat_t status_invalid_argument or status_success
  429. */
  430. hpm_stat_t i2s_config_tx(I2S_Type *ptr, uint32_t mclk_in_hz, i2s_transfer_config_t *config);
  431. /**
  432. * @brief I2S config tx for slave
  433. *
  434. * @param [in] ptr I2S base address
  435. * @param [in] config i2s_transfer_config_t
  436. */
  437. hpm_stat_t i2s_config_tx_slave(I2S_Type *ptr, i2s_transfer_config_t *config);
  438. /**
  439. * @brief I2S config rx
  440. *
  441. * @param [in] ptr I2S base address
  442. * @param [in] mclk_in_hz mclk frequency in Hz
  443. * @param [in] config i2s_transfer_config_t
  444. * @retval hpm_stat_t status_invalid_argument or status_success
  445. */
  446. hpm_stat_t i2s_config_rx(I2S_Type *ptr, uint32_t mclk_in_hz, i2s_transfer_config_t *config);
  447. /**
  448. * @brief I2S config rx for slave
  449. *
  450. * @param [in] ptr I2S base address
  451. * @param [in] config i2s_transfer_config_t
  452. * @retval hpm_stat_t status_invalid_argument or status_success
  453. */
  454. hpm_stat_t i2s_config_rx_slave(I2S_Type *ptr, i2s_transfer_config_t *config);
  455. /**
  456. * @brief I2S config transfer
  457. *
  458. * @param [in] ptr I2S base address
  459. * @param [in] mclk_in_hz mclk frequency in Hz
  460. * @param [in] config i2s_transfer_config_t
  461. * @retval hpm_stat_t status_invalid_argument or status_success
  462. */
  463. hpm_stat_t i2s_config_transfer(I2S_Type *ptr, uint32_t mclk_in_hz, i2s_transfer_config_t *config);
  464. /**
  465. * @brief I2S config transfer for slave
  466. *
  467. * @param [in] ptr I2S base address
  468. * @param [in] config i2s_transfer_config_t
  469. * @retval hpm_stat_t status_invalid_argument or status_success
  470. */
  471. hpm_stat_t i2s_config_transfer_slave(I2S_Type *ptr, i2s_transfer_config_t *config);
  472. /**
  473. * @brief I2S send data
  474. *
  475. * @param [in] ptr I2S base address
  476. * @param [in] tx_line_index data line
  477. * @param [in] data data to be written
  478. */
  479. static inline void i2s_send_data(I2S_Type *ptr, uint8_t tx_line_index, uint32_t data)
  480. {
  481. ptr->TXD[tx_line_index] = data;
  482. }
  483. /**
  484. * @brief I2S receive data
  485. *
  486. * @param [in] ptr I2S base address
  487. * @param [in] rx_line_index data line
  488. * @param [out] data point to store data address
  489. */
  490. static inline void i2s_receive_data(I2S_Type *ptr, uint8_t rx_line_index, uint32_t *data)
  491. {
  492. *data = ptr->RXD[rx_line_index];
  493. }
  494. /**
  495. * @brief I2S send data in buff
  496. *
  497. * @param [in] ptr I2S base address
  498. * @param [in] tx_line_index data line
  499. * @param [in] samplebits audio data width
  500. * @param [in] src source data buff
  501. * @param [in] size data size
  502. *
  503. * @retval I2S sent data size in byte
  504. */
  505. uint32_t i2s_send_buff(I2S_Type *ptr, uint8_t tx_line_index, uint8_t samplebits, uint8_t *src, uint32_t size);
  506. /**
  507. * @brief I2S receive data in buff
  508. *
  509. * @param [in] ptr I2S base address
  510. * @param [in] rx_line_index data line
  511. * @param [in] samplebits audio data width
  512. * @param [out] dst target data buff
  513. * @param [in] size data size
  514. *
  515. * @retval I2S sent data size in byte
  516. */
  517. uint32_t i2s_receive_buff(I2S_Type *ptr, uint8_t rx_line_index, uint8_t samplebits, uint8_t *dst, uint32_t size);
  518. /**
  519. * @brief I2S get default config
  520. *
  521. * @param [in] ptr I2S base address
  522. * @param [out] config i2s_config_t
  523. */
  524. void i2s_get_default_config(I2S_Type *ptr, i2s_config_t *config);
  525. /**
  526. * @brief I2S initialization
  527. *
  528. * @param [in] ptr I2S base address
  529. * @param [in] config i2s_config_t
  530. */
  531. void i2s_init(I2S_Type *ptr, i2s_config_t *config);
  532. /**
  533. * @brief I2S get default transfer config for pdm
  534. *
  535. * @param [out] transfer i2s_transfer_config_t
  536. */
  537. void i2s_get_default_transfer_config_for_pdm(i2s_transfer_config_t *transfer);
  538. /**
  539. * @brief I2S get default transfer config for dao
  540. *
  541. * @param [out] transfer i2s_transfer_config_t
  542. */
  543. void i2s_get_default_transfer_config_for_dao(i2s_transfer_config_t *transfer);
  544. /**
  545. * @brief I2S get default transfer config
  546. *
  547. * @param [out] transfer i2s_transfer_config_t
  548. */
  549. void i2s_get_default_transfer_config(i2s_transfer_config_t *transfer);
  550. /**
  551. * @}
  552. */
  553. #ifdef __cplusplus
  554. }
  555. #endif
  556. #endif /* HPM_I2S_DRV_H */