1 /*
2  * SPDX-FileCopyrightText: 2021-2022 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 "soc/soc_caps.h"
12 #include "hal/i2s_hal.h"
13 
14 /**
15  * @brief Calculate the closest sample rate clock configuration.
16  *        clock relationship:
17  *        Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a)
18  *
19  * @param clk_cfg I2S clock configuration(input)
20  * @param cal Point to `i2s_ll_mclk_div_t` structure(output).
21  */
i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t * clk_cfg,i2s_ll_mclk_div_t * cal)22 static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal)
23 {
24     int ma = 0;
25     int mb = 0;
26     cal->mclk_div = clk_cfg->mclk_div;
27     cal->a = 1;
28     cal->b = 0;
29 
30     uint32_t freq_diff = abs(clk_cfg->sclk - clk_cfg->mclk * cal->mclk_div);
31     if (!freq_diff) {
32         return;
33     }
34     float decimal = freq_diff / (float)clk_cfg->mclk;
35     // Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
36     if (decimal > 125.0 / 126.0) {
37         cal->mclk_div++;
38         return;
39     }
40     uint32_t min = ~0;
41     for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
42         // Calculate the closest 'b' in this loop, no need to loop 'b' to seek the closest value
43         int b = (int)(a * (freq_diff / (double)clk_cfg->mclk) + 0.5);
44         ma = freq_diff * a;
45         mb = clk_cfg->mclk * b;
46         if (ma == mb) {
47             cal->a = a;
48             cal->b = b;
49             return;
50         }
51         if (abs((mb - ma)) < min) {
52             cal->a = a;
53             cal->b = b;
54             min = abs(mb - ma);
55         }
56     }
57 }
58 
i2s_hal_set_clock_src(i2s_hal_context_t * hal,i2s_clock_src_t sel)59 void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel)
60 {
61     i2s_ll_tx_clk_set_src(hal->dev, sel);
62     i2s_ll_rx_clk_set_src(hal->dev, sel);
63 }
64 
i2s_hal_tx_clock_config(i2s_hal_context_t * hal,i2s_hal_clock_cfg_t * clk_cfg)65 void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg)
66 {
67     i2s_ll_mclk_div_t mclk_set;
68     i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set);
69     i2s_ll_tx_set_clk(hal->dev, &mclk_set);
70     i2s_ll_tx_set_bck_div_num(hal->dev, clk_cfg->bclk_div);
71 }
72 
i2s_hal_rx_clock_config(i2s_hal_context_t * hal,i2s_hal_clock_cfg_t * clk_cfg)73 void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg)
74 {
75     i2s_ll_mclk_div_t mclk_set;
76     i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set);
77     i2s_ll_rx_set_clk(hal->dev, &mclk_set);
78     i2s_ll_rx_set_bck_div_num(hal->dev, clk_cfg->bclk_div);
79 }
80 
i2s_hal_enable_master_fd_mode(i2s_hal_context_t * hal)81 void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal)
82 {
83     i2s_ll_tx_set_slave_mod(hal->dev, false); //TX master
84     i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave
85 }
86 
i2s_hal_enable_slave_fd_mode(i2s_hal_context_t * hal)87 void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal)
88 {
89     i2s_ll_tx_set_slave_mod(hal->dev, true); //TX Slave
90     i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave
91 }
92 
i2s_hal_init(i2s_hal_context_t * hal,int i2s_num)93 void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num)
94 {
95     /* Get hardware instance */
96     hal->dev = I2S_LL_GET_HW(i2s_num);
97 }
98 
99 #if SOC_I2S_SUPPORTS_PDM_TX
i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t * hal,uint32_t sample_rate)100 void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate)
101 {
102     /* enable pdm tx mode */
103     i2s_ll_tx_enable_pdm(hal->dev, true);
104 #if SOC_I2S_SUPPORTS_TDM
105     i2s_ll_tx_enable_clock(hal->dev);
106     i2s_ll_tx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
107     i2s_ll_mclk_use_tx_clk(hal->dev);
108     /* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
109     i2s_ll_tx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
110 #else
111     i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
112 #endif
113     /* set pdm tx default presacle */
114     i2s_ll_tx_set_pdm_prescale(hal->dev, 0);
115     /* set pdm tx default sacle of high pass filter */
116     i2s_ll_tx_set_pdm_hp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
117     /* set pdm tx default sacle of low pass filter */
118     i2s_ll_tx_set_pdm_lp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
119     /* set pdm tx default sacle of sinc filter */
120     i2s_ll_tx_set_pdm_sinc_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
121     /* set pdm tx default sacle of sigma-delta filter */
122     i2s_ll_tx_set_pdm_sd_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
123     /* set pdm tx sample rate */
124     i2s_ll_tx_set_pdm_fpfs(hal->dev, 960, sample_rate / 100);
125 
126 #if SOC_I2S_SUPPORTS_PDM_CODEC
127     /* enable pdm high pass filter */
128     i2s_ll_tx_enable_pdm_hp_filter(hal->dev, true);
129     /* set pdm tx high pass filter parameters */
130     i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, 6);
131     i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, 7);
132     /* enable pdm sigma-delta codec */
133     i2s_ll_tx_enable_pdm_sd_codec(hal->dev, true);
134     /* set pdm tx sigma-delta codec dither */
135     i2s_ll_tx_set_pdm_sd_dither(hal->dev, 0);
136     i2s_ll_tx_set_pdm_sd_dither2(hal->dev, 0);
137 
138 #endif // SOC_I2S_SUPPORTS_PDM_CODEC
139 }
140 #endif // SOC_I2S_SUPPORTS_PDM_TX
141 
142 #if SOC_I2S_SUPPORTS_PDM_RX
i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t * hal)143 void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal)
144 {
145     /* enable pdm rx mode */
146     i2s_ll_rx_enable_pdm(hal->dev, true);
147     /* set pdm rx downsample number */
148     i2s_ll_rx_set_pdm_dsr(hal->dev, I2S_PDM_DSR_8S);
149 #if !SOC_I2S_SUPPORTS_TDM
150     i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
151 #endif
152 #if SOC_I2S_SUPPORTS_TDM
153     i2s_ll_rx_enable_clock(hal->dev);
154     i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
155     i2s_ll_mclk_use_rx_clk(hal->dev);
156     /* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
157     i2s_ll_rx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
158 #else
159     i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
160 #endif
161 }
162 #endif // SOC_I2S_SUPPORTS_PDM_RX
163 
164 
i2s_hal_tx_set_common_mode(i2s_hal_context_t * hal,const i2s_hal_config_t * hal_cfg)165 void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
166 {
167     /* Disable PDM tx mode and enable TDM mode (if support) */
168     i2s_ll_tx_enable_pdm(hal->dev, false);
169 
170 #if SOC_I2S_SUPPORTS_TDM
171     i2s_ll_tx_enable_clock(hal->dev);
172     i2s_ll_tx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
173     i2s_ll_mclk_use_tx_clk(hal->dev);
174 
175     // In TDM mode(more than 2 channels), the ws polarity should be high first.
176     if (hal_cfg->total_chan > 2) {
177         i2s_ll_tx_set_ws_idle_pol(hal->dev, true);
178     }
179     i2s_ll_tx_enable_left_align(hal->dev, hal_cfg->left_align);
180     i2s_ll_tx_enable_big_endian(hal->dev, hal_cfg->big_edin);
181     i2s_ll_tx_set_bit_order(hal->dev, hal_cfg->bit_order_msb);
182     i2s_ll_tx_set_skip_mask(hal->dev, hal_cfg->skip_msk);
183 #else
184     i2s_ll_tx_enable_msb_right(hal->dev, false);
185     i2s_ll_tx_enable_right_first(hal->dev, false);
186     i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
187 #endif
188 }
189 
i2s_hal_rx_set_common_mode(i2s_hal_context_t * hal,const i2s_hal_config_t * hal_cfg)190 void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
191 {
192     /* Disable PDM rx mode and enable TDM rx mode (if support)*/
193     i2s_ll_rx_enable_pdm(hal->dev, false);
194 
195 #if SOC_I2S_SUPPORTS_TDM
196     i2s_ll_rx_enable_clock(hal->dev);
197     i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
198     i2s_ll_mclk_use_rx_clk(hal->dev);
199 
200     // In TDM mode(more than 2 channels), the ws polarity should be high first.
201     if (hal_cfg->total_chan > 2) {
202         i2s_ll_rx_set_ws_idle_pol(hal->dev, true);
203     }
204     i2s_ll_rx_enable_left_align(hal->dev, hal_cfg->left_align);
205     i2s_ll_rx_enable_big_endian(hal->dev, hal_cfg->big_edin);
206     i2s_ll_rx_set_bit_order(hal->dev, hal_cfg->bit_order_msb);
207 #else
208     i2s_ll_rx_enable_msb_right(hal->dev, false);
209     i2s_ll_rx_enable_right_first(hal->dev, false);
210     i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
211 #endif
212 }
213 
i2s_hal_get_ws_bit(i2s_comm_format_t fmt,uint32_t chan_num,uint32_t chan_bits)214 static uint32_t i2s_hal_get_ws_bit(i2s_comm_format_t fmt, uint32_t chan_num, uint32_t chan_bits)
215 {
216     switch (fmt) {
217     case I2S_COMM_FORMAT_STAND_MSB:
218         return chan_num * chan_bits / 2;
219     case I2S_COMM_FORMAT_STAND_PCM_SHORT:
220         return 1;
221     case I2S_COMM_FORMAT_STAND_PCM_LONG:
222         return chan_bits;
223     default: //I2S_COMM_FORMAT_STAND_I2S
224         return chan_num * chan_bits / 2;
225     }
226 }
227 
i2s_hal_tx_set_channel_style(i2s_hal_context_t * hal,const i2s_hal_config_t * hal_cfg)228 void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
229 {
230     uint32_t chan_num = 2;
231     uint32_t chan_bits = hal_cfg->chan_bits;
232     uint32_t data_bits = hal_cfg->sample_bits;
233     bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) ||
234                    (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT);
235 
236     /* Set channel number and valid data bits */
237 #if SOC_I2S_SUPPORTS_TDM
238     chan_num = hal_cfg->total_chan;
239     i2s_ll_tx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask >> 16);
240     i2s_ll_tx_set_chan_num(hal->dev, chan_num);
241 #endif
242     i2s_ll_tx_set_sample_bit(hal->dev, chan_bits, data_bits);
243     i2s_ll_tx_enable_mono_mode(hal->dev, is_mono);
244 
245     /* Set communication format */
246     bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false;
247     uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits);
248     i2s_ll_tx_enable_msb_shift(hal->dev, shift_en);
249     i2s_ll_tx_set_ws_width(hal->dev, ws_width);
250 #if SOC_I2S_SUPPORTS_TDM
251     i2s_ll_tx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2);
252 #endif
253 }
254 
i2s_hal_rx_set_channel_style(i2s_hal_context_t * hal,const i2s_hal_config_t * hal_cfg)255 void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
256 {
257     uint32_t chan_num = 2;
258     uint32_t chan_bits = hal_cfg->chan_bits;
259     uint32_t data_bits = hal_cfg->sample_bits;
260     bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) ||
261                    (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT);
262 
263 #if SOC_I2S_SUPPORTS_TDM
264     chan_num = hal_cfg->total_chan;
265     i2s_ll_rx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask >> 16);
266     i2s_ll_rx_set_chan_num(hal->dev, chan_num);
267 #endif
268     i2s_ll_rx_set_sample_bit(hal->dev, chan_bits, data_bits);
269     i2s_ll_rx_enable_mono_mode(hal->dev, is_mono);
270 
271     /* Set communication format */
272     bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false;
273     uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits);
274     i2s_ll_rx_enable_msb_shift(hal->dev, shift_en);
275     i2s_ll_rx_set_ws_width(hal->dev, ws_width);
276 #if SOC_I2S_SUPPORTS_TDM
277     i2s_ll_rx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2);
278 #endif
279 }
280 
i2s_hal_config_param(i2s_hal_context_t * hal,const i2s_hal_config_t * hal_cfg)281 void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
282 {
283 #if SOC_I2S_SUPPORTS_ADC
284     if (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN) {
285         /* In ADC built-in mode, we need to call i2s_set_adc_mode to initialize the specific ADC channel.
286          * In the current stage, we only support ADC1 and single channel mode.
287          * In default data mode, the ADC data is in 12-bit resolution mode.
288          */
289         i2s_ll_enable_builtin_adc(hal->dev, true);
290         return;
291     }
292     i2s_ll_enable_builtin_adc(hal->dev, false);
293 #endif
294 #if SOC_I2S_SUPPORTS_DAC
295     if (hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) {
296         i2s_ll_enable_builtin_dac(hal->dev, true);
297         return;
298     }
299     i2s_ll_enable_builtin_dac(hal->dev, false);
300 #endif
301     /* Set configurations for TX mode */
302     if (hal_cfg->mode & I2S_MODE_TX) {
303         i2s_ll_tx_stop(hal->dev);
304         i2s_ll_tx_reset(hal->dev);
305         i2s_ll_tx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //TX Slave
306 #if SOC_I2S_SUPPORTS_PDM_TX
307         if (hal_cfg->mode & I2S_MODE_PDM) {
308             /* Set tx pdm mode */
309             i2s_hal_tx_set_pdm_mode_default(hal, hal_cfg->sample_rate);
310         } else
311 #endif
312         {
313             /* Set tx common mode */
314             i2s_hal_tx_set_common_mode(hal, hal_cfg);
315         }
316         i2s_hal_tx_set_channel_style(hal, hal_cfg);
317     }
318 
319     /* Set configurations for RX mode */
320     if (hal_cfg->mode & I2S_MODE_RX) {
321         i2s_ll_rx_stop(hal->dev);
322         i2s_ll_rx_reset(hal->dev);
323         i2s_ll_rx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //RX Slave
324 #if SOC_I2S_SUPPORTS_PDM_RX
325         if (hal_cfg->mode & I2S_MODE_PDM) {
326             /* Set rx pdm mode */
327             i2s_hal_rx_set_pdm_mode_default(hal);
328         } else
329 #endif
330         {
331             /* Set rx common mode */
332             i2s_hal_rx_set_common_mode(hal, hal_cfg);
333         }
334         i2s_hal_rx_set_channel_style(hal, hal_cfg);
335     }
336 
337     /* Set configurations for full-duplex mode */
338     if ((hal_cfg->mode & I2S_MODE_RX) && (hal_cfg->mode & I2S_MODE_TX)) {
339         i2s_ll_share_bck_ws(hal->dev, true);
340         if (hal_cfg->mode & I2S_MODE_MASTER) {
341             i2s_hal_enable_master_fd_mode(hal);
342         } else {
343             i2s_hal_enable_slave_fd_mode(hal);
344         }
345     }
346 }
347 
i2s_hal_start_tx(i2s_hal_context_t * hal)348 void i2s_hal_start_tx(i2s_hal_context_t *hal)
349 {
350     i2s_ll_tx_start(hal->dev);
351 }
352 
i2s_hal_start_rx(i2s_hal_context_t * hal)353 void i2s_hal_start_rx(i2s_hal_context_t *hal)
354 {
355     i2s_ll_rx_start(hal->dev);
356 }
357 
i2s_hal_stop_tx(i2s_hal_context_t * hal)358 void i2s_hal_stop_tx(i2s_hal_context_t *hal)
359 {
360     i2s_ll_tx_stop(hal->dev);
361 }
362 
i2s_hal_stop_rx(i2s_hal_context_t * hal)363 void i2s_hal_stop_rx(i2s_hal_context_t *hal)
364 {
365     i2s_ll_rx_stop(hal->dev);
366 }
367