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