i2s_hal.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. // The HAL layer for I2S (common part)
  7. #include "soc/soc.h"
  8. #include "hal/i2s_hal.h"
  9. #if SOC_I2S_HW_VERSION_2 && SOC_I2S_SUPPORTS_PDM_TX
  10. /* PDM tx high pass filter cut-off frequency and coeffecients list
  11. * [0]: cut-off frequency; [1]: param0; [2]: param5 */
  12. static const float cut_off_coef[21][3] = {
  13. {185, 0, 0}, {172, 0, 1}, {160, 1, 1},
  14. {150, 1, 2}, {137, 2, 2}, {126, 2, 3},
  15. {120, 0, 3}, {115, 3, 3}, {106, 1, 7},
  16. {104, 2, 4}, {92, 4, 4}, {91.5, 2, 7},
  17. {81, 4, 5}, {77.2, 3, 7}, {69, 5, 5},
  18. {63, 4, 7}, {58, 5, 6}, {49, 5, 7},
  19. {46, 6, 6}, {35.5, 6, 7}, {23.3, 7, 7}
  20. };
  21. #endif
  22. void i2s_hal_init(i2s_hal_context_t *hal, int port_id)
  23. {
  24. /* Get hardware instance */
  25. hal->dev = I2S_LL_GET_HW(port_id);
  26. }
  27. void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src)
  28. {
  29. #if SOC_I2S_HW_VERSION_2
  30. i2s_ll_tx_enable_clock(hal->dev);
  31. i2s_ll_mclk_bind_to_tx_clk(hal->dev);
  32. #endif
  33. i2s_ll_tx_clk_set_src(hal->dev, clk_src);
  34. i2s_ll_tx_set_mclk(hal->dev, clk_info->sclk, clk_info->mclk, clk_info->mclk_div);
  35. i2s_ll_tx_set_bck_div_num(hal->dev, clk_info->bclk_div);
  36. }
  37. void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src)
  38. {
  39. #if SOC_I2S_HW_VERSION_2
  40. i2s_ll_rx_enable_clock(hal->dev);
  41. i2s_ll_mclk_bind_to_rx_clk(hal->dev);
  42. #endif
  43. i2s_ll_rx_clk_set_src(hal->dev, clk_src);
  44. i2s_ll_rx_set_mclk(hal->dev, clk_info->sclk, clk_info->mclk, clk_info->mclk_div);
  45. i2s_ll_rx_set_bck_div_num(hal->dev, clk_info->bclk_div);
  46. }
  47. /*-------------------------------------------------------------------------
  48. | STD Specific Slot Configurations |
  49. -------------------------------------------------------------------------*/
  50. void i2s_hal_std_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg)
  51. {
  52. uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
  53. slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
  54. i2s_ll_tx_reset(hal->dev);
  55. i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
  56. i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
  57. i2s_ll_tx_enable_msb_shift(hal->dev, slot_cfg->std.bit_shift);
  58. i2s_ll_tx_set_ws_width(hal->dev, slot_cfg->std.ws_width);
  59. #if SOC_I2S_HW_VERSION_1
  60. i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
  61. i2s_ll_tx_select_std_slot(hal->dev, slot_cfg->std.slot_mask, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
  62. // According to the test, the behavior of tx_msb_right is opposite with TRM, TRM is wrong?
  63. i2s_ll_tx_enable_msb_right(hal->dev, slot_cfg->std.msb_right);
  64. i2s_ll_tx_enable_right_first(hal->dev, slot_cfg->std.ws_pol);
  65. /* Should always enable fifo */
  66. i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
  67. #elif SOC_I2S_HW_VERSION_2
  68. bool is_copy_mono = slot_cfg->slot_mode == I2S_SLOT_MODE_MONO && slot_cfg->std.slot_mask == I2S_STD_SLOT_BOTH;
  69. i2s_ll_tx_enable_mono_mode(hal->dev, is_copy_mono);
  70. i2s_ll_tx_select_std_slot(hal->dev, is_copy_mono ? I2S_STD_SLOT_LEFT : slot_cfg->std.slot_mask);
  71. i2s_ll_tx_set_skip_mask(hal->dev, (slot_cfg->std.slot_mask != I2S_STD_SLOT_BOTH) &&
  72. (slot_cfg->slot_mode == I2S_SLOT_MODE_STEREO));
  73. i2s_ll_tx_set_half_sample_bit(hal->dev, slot_bit_width);
  74. i2s_ll_tx_set_ws_idle_pol(hal->dev, slot_cfg->std.ws_pol);
  75. i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->std.bit_order_lsb);
  76. i2s_ll_tx_enable_left_align(hal->dev, slot_cfg->std.left_align);
  77. i2s_ll_tx_enable_big_endian(hal->dev, slot_cfg->std.big_endian);
  78. #endif
  79. }
  80. void i2s_hal_std_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg)
  81. {
  82. uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
  83. slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
  84. i2s_ll_rx_reset(hal->dev);
  85. i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
  86. i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
  87. i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
  88. i2s_ll_rx_enable_msb_shift(hal->dev, slot_cfg->std.bit_shift);
  89. i2s_ll_rx_set_ws_width(hal->dev, slot_cfg->std.ws_width);
  90. #if SOC_I2S_HW_VERSION_1
  91. i2s_ll_rx_select_std_slot(hal->dev, slot_cfg->std.slot_mask, slot_cfg->std.msb_right);
  92. i2s_ll_rx_enable_msb_right(hal->dev, slot_cfg->std.msb_right);
  93. i2s_ll_rx_enable_right_first(hal->dev, slot_cfg->std.ws_pol);
  94. /* Should always enable fifo */
  95. i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
  96. #elif SOC_I2S_HW_VERSION_2
  97. i2s_ll_rx_select_std_slot(hal->dev, slot_cfg->std.slot_mask);
  98. i2s_ll_rx_set_half_sample_bit(hal->dev, slot_bit_width);
  99. i2s_ll_rx_set_ws_idle_pol(hal->dev, slot_cfg->std.ws_pol);
  100. i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->std.bit_order_lsb);
  101. i2s_ll_rx_enable_left_align(hal->dev, slot_cfg->std.left_align);
  102. i2s_ll_rx_enable_big_endian(hal->dev, slot_cfg->std.big_endian);
  103. #endif
  104. }
  105. void i2s_hal_std_enable_tx_channel(i2s_hal_context_t *hal)
  106. {
  107. i2s_ll_tx_enable_std(hal->dev);
  108. }
  109. void i2s_hal_std_enable_rx_channel(i2s_hal_context_t *hal)
  110. {
  111. i2s_ll_rx_enable_std(hal->dev);
  112. }
  113. /*-------------------------------------------------------------------------
  114. | PDM Specific Slot Configurations |
  115. -------------------------------------------------------------------------*/
  116. #if SOC_I2S_SUPPORTS_PDM_TX
  117. void i2s_hal_pdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg)
  118. {
  119. bool is_mono = slot_cfg->slot_mode == I2S_SLOT_MODE_MONO;
  120. i2s_ll_tx_reset(hal->dev);
  121. i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
  122. i2s_ll_tx_enable_msb_shift(hal->dev, false);
  123. i2s_ll_tx_set_pdm_prescale(hal->dev, slot_cfg->pdm_tx.sd_prescale);
  124. i2s_ll_tx_set_pdm_hp_scale(hal->dev, slot_cfg->pdm_tx.hp_scale);
  125. i2s_ll_tx_set_pdm_lp_scale(hal->dev, slot_cfg->pdm_tx.lp_scale);
  126. i2s_ll_tx_set_pdm_sinc_scale(hal->dev, slot_cfg->pdm_tx.sinc_scale);
  127. i2s_ll_tx_set_pdm_sd_scale(hal->dev, slot_cfg->pdm_tx.sd_scale);
  128. #if SOC_I2S_HW_VERSION_1
  129. uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
  130. slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
  131. i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
  132. i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
  133. i2s_ll_tx_enable_mono_mode(hal->dev, is_mono);
  134. i2s_ll_tx_select_pdm_slot(hal->dev, slot_cfg->pdm_tx.slot_mask, is_mono);
  135. i2s_ll_tx_enable_msb_right(hal->dev, false);
  136. i2s_ll_tx_enable_right_first(hal->dev, false);
  137. #elif SOC_I2S_HW_VERSION_2
  138. /* PDM TX line mode */
  139. i2s_ll_tx_pdm_line_mode(hal->dev, slot_cfg->pdm_tx.line_mode);
  140. /* Force use 32 bit in PDM TX stereo mode to satisfy the frequency */
  141. uint32_t slot_bit_width = is_mono ? 16 : 32;
  142. i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_bit_width);
  143. i2s_ll_tx_set_half_sample_bit(hal->dev, 16); // Fixed to 16 in PDM mode
  144. /* By default, taking the DMA data at the first half period of WS */
  145. i2s_ll_tx_pdm_dma_take_mode(hal->dev, is_mono, true);
  146. i2s_ll_tx_set_ws_idle_pol(hal->dev, false);
  147. /* Slot mode seems not take effect according to the test, leave it default here */
  148. i2s_ll_tx_pdm_slot_mode(hal->dev, is_mono, false, I2S_PDM_SLOT_BOTH);
  149. uint8_t cnt = 0;
  150. float min = 1000;
  151. float expt_cut_off = slot_cfg->pdm_tx.hp_cut_off_freq_hz;
  152. /* Find the closest cut-off frequency and its coefficients */
  153. for (int i = 0; i < 21; i++) {
  154. float tmp = cut_off_coef[i][0] < expt_cut_off ? expt_cut_off - cut_off_coef[i][0] : cut_off_coef[i][0] - expt_cut_off;
  155. if (tmp < min) {
  156. min = tmp;
  157. cnt = i;
  158. }
  159. }
  160. i2s_ll_tx_enable_pdm_hp_filter(hal->dev, slot_cfg->pdm_tx.hp_en);
  161. i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, cut_off_coef[cnt][1]);
  162. i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, cut_off_coef[cnt][2]);
  163. i2s_ll_tx_set_pdm_sd_dither(hal->dev, slot_cfg->pdm_tx.sd_dither);
  164. i2s_ll_tx_set_pdm_sd_dither2(hal->dev, slot_cfg->pdm_tx.sd_dither2);
  165. #endif
  166. }
  167. void i2s_hal_pdm_enable_tx_channel(i2s_hal_context_t *hal)
  168. {
  169. i2s_ll_tx_enable_pdm(hal->dev);
  170. }
  171. #endif
  172. #if SOC_I2S_SUPPORTS_PDM_RX
  173. void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg)
  174. {
  175. uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
  176. slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
  177. i2s_ll_rx_reset(hal->dev);
  178. i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
  179. i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
  180. #if SOC_I2S_HW_VERSION_1
  181. i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
  182. i2s_ll_rx_select_pdm_slot(hal->dev, slot_cfg->pdm_rx.slot_mask);
  183. i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
  184. i2s_ll_rx_enable_msb_right(hal->dev, false);
  185. i2s_ll_rx_enable_right_first(hal->dev, false);
  186. #elif SOC_I2S_HW_VERSION_2
  187. i2s_ll_tx_set_half_sample_bit(hal->dev, 16);
  188. i2s_ll_rx_enable_mono_mode(hal->dev, false);
  189. /* Set the channel mask to enable corresponding slots, always enable two slots for stereo mode */
  190. i2s_ll_rx_set_active_chan_mask(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_STEREO ?
  191. I2S_PDM_SLOT_BOTH : slot_cfg->pdm_rx.slot_mask);
  192. #endif
  193. }
  194. void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal)
  195. {
  196. i2s_ll_rx_enable_pdm(hal->dev);
  197. }
  198. #endif
  199. /*-------------------------------------------------------------------------
  200. | TDM Specific Slot Configurations |
  201. -------------------------------------------------------------------------*/
  202. #if SOC_I2S_SUPPORTS_TDM
  203. void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg)
  204. {
  205. uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
  206. slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
  207. uint32_t cnt;
  208. uint32_t msk = slot_cfg->tdm.slot_mask;
  209. /* Get the maximum slot number */
  210. cnt = 32 - __builtin_clz(msk);
  211. /* There should be at least 2 slots in total even for mono mode */
  212. cnt = cnt < 2 ? 2 : cnt;
  213. uint32_t total_slot = slot_cfg->tdm.total_slot > cnt ? slot_cfg->tdm.total_slot : cnt;
  214. i2s_ll_tx_reset(hal->dev);
  215. i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
  216. i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
  217. i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
  218. i2s_ll_tx_enable_msb_shift(hal->dev, slot_cfg->tdm.bit_shift);
  219. if (slot_cfg->tdm.ws_width == 0) { // 0: I2S_TDM_AUTO_WS_WIDTH
  220. i2s_ll_tx_set_ws_width(hal->dev, (total_slot * slot_bit_width) / 2);
  221. } else {
  222. i2s_ll_tx_set_ws_width(hal->dev, slot_cfg->tdm.ws_width);
  223. }
  224. i2s_ll_tx_set_ws_idle_pol(hal->dev, slot_cfg->tdm.ws_pol);
  225. i2s_ll_tx_set_chan_num(hal->dev, total_slot);
  226. /* In mono mode, there only should be one slot enabled, other inactive slots will transmit same data as enabled slot */
  227. i2s_ll_tx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ?
  228. I2S_TDM_SLOT0 : (uint32_t)slot_cfg->tdm.slot_mask);
  229. i2s_ll_tx_set_skip_mask(hal->dev, slot_cfg->tdm.skip_mask);
  230. i2s_ll_tx_set_half_sample_bit(hal->dev, __builtin_popcount(slot_cfg->tdm.slot_mask) * slot_bit_width / 2);
  231. i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->tdm.bit_order_lsb);
  232. i2s_ll_tx_enable_left_align(hal->dev, slot_cfg->tdm.left_align);
  233. i2s_ll_tx_enable_big_endian(hal->dev, slot_cfg->tdm.big_endian);
  234. }
  235. void i2s_hal_tdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg)
  236. {
  237. uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
  238. slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
  239. uint32_t cnt;
  240. uint32_t msk = slot_cfg->tdm.slot_mask;
  241. /* Get the maximum slot number */
  242. cnt = 32 - __builtin_clz(msk);
  243. /* There should be at least 2 slots in total even for mono mode */
  244. cnt = cnt < 2 ? 2 : cnt;
  245. uint32_t total_slot = slot_cfg->tdm.total_slot > cnt ? slot_cfg->tdm.total_slot : cnt;
  246. i2s_ll_rx_reset(hal->dev);
  247. i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
  248. i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
  249. i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
  250. i2s_ll_rx_enable_msb_shift(hal->dev, slot_cfg->tdm.bit_shift);
  251. if (slot_cfg->tdm.ws_width == 0) { // 0: I2S_TDM_AUTO_WS_WIDTH
  252. i2s_ll_rx_set_ws_width(hal->dev, (total_slot * slot_bit_width) / 2);
  253. } else {
  254. i2s_ll_rx_set_ws_width(hal->dev, slot_cfg->tdm.ws_width);
  255. }
  256. i2s_ll_rx_set_ws_idle_pol(hal->dev, slot_cfg->tdm.ws_pol);
  257. i2s_ll_rx_set_chan_num(hal->dev, total_slot);
  258. /* In mono mode, there only should be one slot enabled, other inactive slots will transmit same data as enabled slot */
  259. i2s_ll_rx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ?
  260. I2S_TDM_SLOT0 : (uint32_t)slot_cfg->tdm.slot_mask);
  261. i2s_ll_rx_set_half_sample_bit(hal->dev, __builtin_popcount(slot_cfg->tdm.slot_mask) * slot_bit_width / 2);
  262. i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->tdm.bit_order_lsb);
  263. i2s_ll_rx_enable_left_align(hal->dev, slot_cfg->tdm.left_align);
  264. i2s_ll_rx_enable_big_endian(hal->dev, slot_cfg->tdm.big_endian);
  265. }
  266. void i2s_hal_tdm_enable_tx_channel(i2s_hal_context_t *hal)
  267. {
  268. i2s_ll_tx_enable_tdm(hal->dev);
  269. }
  270. void i2s_hal_tdm_enable_rx_channel(i2s_hal_context_t *hal)
  271. {
  272. i2s_ll_rx_enable_tdm(hal->dev);
  273. }
  274. #endif