i2s_hal.c 13 KB

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