• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Description: Provides v151 hal sio \n
16  *
17  * History: \n
18  * 2023-03-07, Create file. \n
19  */
20 #include <stdint.h>
21 #include "securec.h"
22 #include "soc_osal.h"
23 #include "tcxo.h"
24 #include "sio_porting.h"
25 #include "hal_sio_v151.h"
26 
27 #define SIO_LOOP_INTMASK                0x3c
28 #define SIO_WRITE_INTMASK               0x3d
29 #define SIO_READ_INTMASK                0x3e
30 #define SIO_FIFO_SIZE                   8
31 #define SIO_RX_THRESHOLD                7
32 #define SIO_TX_THRESHOLD                4
33 #define SIO_FIRST_TRANSFER_LEN          8
34 #define SIO_FIRST_DELAY_US              25
35 #define SIO_LAST_DELAY_US               295
36 #define SIO_ONCE_TRANSFER_LEN           (SIO_FIFO_SIZE - SIO_TX_THRESHOLD)
37 
38 typedef struct hal_i2s_trans_inf {
39     bool trans_succ;
40     osal_semaphore trans_sem;
41 } hal_i2s_trans_inf_t;
42 
43 static hal_i2s_trans_inf_t g_tx_trans[I2S_MAX_NUMBER] = { 0 };
44 static hal_sio_rx_data_t g_sio_read_data[I2S_MAX_NUMBER] = { 0 };
45 static hal_sio_callback_t g_hal_sio_callbacks[I2S_MAX_NUMBER] = { 0 };
46 static hal_sio_config_t g_hal_sio_config[I2S_MAX_NUMBER] = { 0 };
47 static uint32_t g_i2s_tx_length = 0;
48 static uint32_t g_i2s_index = 0;
49 static uint32_t *g_write_left_data = NULL;
50 static uint32_t *g_write_right_data = NULL;
51 
hal_sio_v151_init(sio_bus_t bus)52 static errcode_t hal_sio_v151_init(sio_bus_t bus)
53 {
54     if (hal_sio_regs_init(bus) != ERRCODE_SUCC) {
55         return ERRCODE_SIO_REG_ADDR_INVALID;
56     }
57     g_i2s_tx_length = 0;
58     g_i2s_index = 0;
59     sio_porting_register_irq(bus);
60     osal_sem_init(&(g_tx_trans[bus].trans_sem), 0);
61     return ERRCODE_SUCC;
62 }
63 
hal_sio_v151_deinit(sio_bus_t bus)64 static void hal_sio_v151_deinit(sio_bus_t bus)
65 {
66     hal_sio_regs_deinit(bus);
67     osal_sem_destroy(&(g_tx_trans[bus].trans_sem));
68 }
69 
hal_sio_v151_set_intmask(sio_bus_t bus,uint32_t intmask)70 static void hal_sio_v151_set_intmask(sio_bus_t bus, uint32_t intmask)
71 {
72     sios_v151_regs(bus)->intmask = intmask;
73 }
74 
hal_sio_v151_clear_interrupt(sio_bus_t bus,uint32_t intclr)75 static void hal_sio_v151_clear_interrupt(sio_bus_t bus, uint32_t intclr)
76 {
77     sios_v151_regs(bus)->intclr = intclr;
78 }
79 
hal_sio_v151_get_intstatus(sio_bus_t bus)80 static uint32_t hal_sio_v151_get_intstatus(sio_bus_t bus)
81 {
82     return sios_v151_regs(bus)->intstatus;
83 }
84 
85 #pragma weak hal_sio_set_crg_clock_enable = hal_sio_v151_crg_clock_enable
hal_sio_v151_crg_clock_enable(sio_bus_t bus,bool enable)86 void hal_sio_v151_crg_clock_enable(sio_bus_t bus, bool enable)
87 {
88     hal_sio_v151_i2s_crg_set_crg_clken(bus, (uint32_t)enable);
89 }
90 
91 #pragma weak hal_sio_set_tx_enable = hal_sio_v151_set_tx_enable
hal_sio_v151_set_tx_enable(sio_bus_t bus,uint32_t val)92 void hal_sio_v151_set_tx_enable(sio_bus_t bus, uint32_t val)
93 {
94     hal_sio_v151_ct_set_set_tx_enable(bus, val);
95 }
96 
97 #pragma weak hal_sio_set_rx_enable = hal_sio_v151_set_rx_enable
hal_sio_v151_set_rx_enable(sio_bus_t bus,uint32_t val)98 void hal_sio_v151_set_rx_enable(sio_bus_t bus, uint32_t val)
99 {
100     hal_sio_v151_ct_set_set_rx_enable(bus, val);
101 }
102 
hal_sio_v151_extend_receive_config(sio_bus_t bus,hal_sio_channel_number_t channel)103 static void hal_sio_v151_extend_receive_config(sio_bus_t bus, hal_sio_channel_number_t channel)
104 {
105     hal_sio_v151_mode_set_ext_rec_en(bus, 1);
106     hal_sio_v151_mode_set_chn_num(bus, channel);
107 }
108 
hal_sio_v151_data_width_set(sio_bus_t bus,hal_sio_data_width_t data_width)109 static void hal_sio_v151_data_width_set(sio_bus_t bus, hal_sio_data_width_t data_width)
110 {
111     hal_sio_v151_data_width_set_tx_mode(bus, data_width);
112     hal_sio_v151_data_width_set_rx_mode(bus, data_width);
113 }
114 
hal_sio_v151_master_mode_sel(sio_bus_t bus,bool enable)115 void hal_sio_v151_master_mode_sel(sio_bus_t bus, bool enable)
116 {
117     if (enable) {
118         hal_sio_v151_mode_set_cfg_i2s_ms_mode_sel(bus, 1);
119     } else {
120         hal_sio_v151_mode_set_cfg_i2s_ms_mode_sel(bus, 0);
121     }
122 }
123 
hal_sio_v151_i2s_pos(sio_bus_t bus)124 static void hal_sio_v151_i2s_pos(sio_bus_t bus)
125 {
126     sios_v151_regs(bus)->i2s_start_pos = 0;
127     sios_v151_regs(bus)->i2s_pos_flag = 0;
128 }
hal_sio_v151_i2s_clk_sel(sio_bus_t bus)129 static void hal_sio_v151_i2s_clk_sel(sio_bus_t bus)
130 {
131     hal_sio_v151_i2s_crg_set_bclk_sel(bus, 0);
132     hal_sio_v151_i2s_crg_set_fs_sel(bus, 0);
133 }
134 
hal_sio_v151_i2s_set_fs(sio_bus_t bus,uint8_t data_width,uint32_t number_of_channels)135 static void hal_sio_v151_i2s_set_fs(sio_bus_t bus, uint8_t data_width, uint32_t number_of_channels)
136 {
137     hal_sio_v151_crg_clock_enable(bus, false);
138     hal_sio_v151_fs_div_num_set_num(bus, (data_width * number_of_channels));
139     hal_sio_v151_fs_div_ratio_num_set_num(bus, (data_width * number_of_channels) / I2S_DUTY_CYCLE);
140 }
141 
hal_i2s_set_bclk(sio_bus_t bus,uint8_t data_width,uint32_t ch)142 void hal_i2s_set_bclk(sio_bus_t bus, uint8_t data_width, uint32_t ch)
143 {
144     uint32_t bclk_div_num;
145     bclk_div_num = sio_porting_get_bclk_div_num(data_width, ch);
146     hal_sio_v151_crg_clock_enable(bus, false);
147     hal_sio_v151_i2s_crg_set_bclk_div_en(bus, 0);
148     hal_sio_v151_bclk_div_num_set_num(bus, bclk_div_num);
149     hal_sio_v151_i2s_crg_set_bclk_div_en(bus, 1);
150 }
151 
hal_sio_v151_i2s_drive_mode(sio_bus_t bus,uint8_t drive_mode,uint8_t data_width,uint8_t number_of_channels)152 void hal_sio_v151_i2s_drive_mode(sio_bus_t bus, uint8_t drive_mode, uint8_t data_width, uint8_t number_of_channels)
153 {
154     hal_sio_v151_i2s_clk_sel(bus);
155     if (drive_mode == 0) {
156         hal_sio_v151_master_mode_sel(bus, false);
157         return;
158     }
159     hal_sio_v151_master_mode_sel(bus, true);
160     hal_sio_v151_i2s_set_fs(bus, data_width, number_of_channels);
161     hal_i2s_set_bclk(bus, data_width, number_of_channels);
162 }
163 
hal_i2s_config(sio_bus_t bus,hal_sio_mode_t mode)164 static void hal_i2s_config(sio_bus_t bus, hal_sio_mode_t mode)
165 {
166     hal_sio_v151_set_intmask(bus, SIO_LOOP_INTMASK);
167     hal_sio_v151_mode_set_mode(bus, mode);
168     hal_sio_v151_i2s_drive_mode(bus, g_hal_sio_config[bus].drive_mode, g_hal_sio_config[bus].div_number,
169                                g_hal_sio_config[bus].number_of_channels);
170     hal_sio_v151_mode_set_clk_edge(bus, 1);
171 
172     if (g_hal_sio_config[bus].transfer_mode == MULTICHANNEL_MODE) {
173         hal_sio_v151_extend_receive_config(bus, g_hal_sio_config[bus].channels_num);
174     }
175 
176     hal_sio_v151_data_width_set(bus, g_hal_sio_config[bus].data_width);
177     hal_sio_v151_i2s_pos(bus);
178     hal_sio_v151_ct_clr_set_rst_n(bus, 1);
179     hal_sio_v151_ct_set_set_rst_n(bus, 1);
180     hal_sio_v151_ct_set_set_intr_en(bus, 1);
181     hal_sio_v151_fifo_threshold_set_rx_fifo_threshold(bus, SIO_RX_THRESHOLD);
182     hal_sio_v151_fifo_threshold_set_tx_fifo_threshold(bus, SIO_TX_THRESHOLD);
183 }
184 
hal_sio_v151_set_config(sio_bus_t bus,const hal_sio_config_t * config)185 static void hal_sio_v151_set_config(sio_bus_t bus, const hal_sio_config_t *config)
186 {
187     (void)memcpy_s(&g_hal_sio_config[bus], sizeof(hal_sio_config_t), config, sizeof(hal_sio_config_t));
188 }
189 
hal_sio_v151_get_config(sio_bus_t bus,hal_sio_config_t * config)190 static errcode_t hal_sio_v151_get_config(sio_bus_t bus, hal_sio_config_t *config)
191 {
192     hal_sio_config_t *config_temp = (hal_sio_config_t *)config;
193     if (config_temp == NULL) {
194         return ERRCODE_INVALID_PARAM;
195     }
196 
197     (void)memcpy_s(config_temp, sizeof(hal_sio_config_t), &g_hal_sio_config[bus], sizeof(hal_sio_config_t));
198 
199     return ERRCODE_SUCC;
200 }
201 
hal_sio_v151_rx_enable(sio_bus_t bus,bool en)202 static void hal_sio_v151_rx_enable(sio_bus_t bus, bool en)
203 {
204     hal_i2s_config(bus, I2S_MODE);
205     hal_sio_v151_set_intmask(bus, SIO_READ_INTMASK);
206     hal_sio_v151_ct_set_set_rx_enable(bus, (uint32_t)en);
207 }
208 
hal_sio_read_data(sio_bus_t bus,hal_sio_voice_channel_t voice_channe)209 static uint32_t hal_sio_read_data(sio_bus_t bus, hal_sio_voice_channel_t voice_channe)
210 {
211     uint32_t data_temp = 0;
212     if (voice_channe == SIO_LEFT) {
213         data_temp = hal_sio_v151_i2s_left_rd_get_rx_left_data(bus);
214     } else {
215         data_temp = hal_sio_v151_i2s_right_rd_get_rx_right_data(bus);
216     }
217     return data_temp;
218 }
219 
hal_sio_write_data(sio_bus_t bus,uint32_t data,hal_sio_voice_channel_t voice_channe)220 static void hal_sio_write_data(sio_bus_t bus, uint32_t data, hal_sio_voice_channel_t voice_channe)
221 {
222     uint32_t data_temp = data;
223     if (voice_channe == SIO_LEFT) {
224         hal_sio_v151_i2s_left_xd_set_tx_left_data(bus, data_temp);
225     } else {
226         hal_sio_v151_i2s_right_xd_set_tx_right_data(bus, data_temp);
227     }
228 }
229 
hal_i2s_write(sio_bus_t bus,hal_sio_tx_data_t * data,hal_sio_mode_t mode)230 static void hal_i2s_write(sio_bus_t bus, hal_sio_tx_data_t *data, hal_sio_mode_t mode)
231 {
232     hal_i2s_config(bus, mode);
233     hal_sio_v151_set_intmask(bus, SIO_WRITE_INTMASK);
234     g_i2s_tx_length = data->length;
235     g_write_left_data = data->left_buff;
236     g_write_right_data = data->right_buff;
237 
238     if (g_i2s_tx_length < SIO_FIRST_TRANSFER_LEN) {
239         for (uint32_t i = 0; i < g_i2s_tx_length; i++) {
240             hal_sio_write_data(bus, g_write_left_data[i], SIO_LEFT);
241             hal_sio_write_data(bus, g_write_right_data[i], SIO_RIGHT);
242         }
243         g_i2s_index = g_i2s_tx_length;
244     } else {
245         for (uint32_t i = 0; i < SIO_FIRST_TRANSFER_LEN; i++) {
246             hal_sio_write_data(bus, g_write_left_data[i], SIO_LEFT);
247             hal_sio_write_data(bus, g_write_right_data[i], SIO_RIGHT);
248         }
249         g_i2s_index += SIO_FIRST_TRANSFER_LEN;
250     }
251 
252     hal_sio_v151_crg_clock_enable(bus, true);
253     uapi_tcxo_delay_us(SIO_FIRST_DELAY_US);
254     hal_sio_v151_ct_set_set_tx_enable(bus, 1);
255 
256     if (osal_sem_down(&(g_tx_trans[bus].trans_sem)) != OSAL_SUCCESS) {
257         return;
258     }
259     if (!g_tx_trans[bus].trans_succ) {
260         return;
261     }
262     uapi_tcxo_delay_us(SIO_LAST_DELAY_US);
263     hal_sio_v151_ct_clr_set_tx_enable(bus, 1);
264     hal_sio_v151_crg_clock_enable(bus, false);
265     g_tx_trans[bus].trans_succ = false;
266 }
267 
268 static hal_sio_write_t g_sio_write_func[NONE_SIO_MODE] = {
269     hal_i2s_write,
270 };
271 
hal_sio_v151_write(sio_bus_t bus,hal_sio_tx_data_t * data,hal_sio_mode_t mode)272 static void hal_sio_v151_write(sio_bus_t bus, hal_sio_tx_data_t *data, hal_sio_mode_t mode)
273 {
274     g_sio_write_func[mode](bus, data, mode);
275 }
276 
hal_sio_v151_register(sio_bus_t bus,hal_sio_callback_t callback)277 static void hal_sio_v151_register(sio_bus_t bus, hal_sio_callback_t callback)
278 {
279     g_hal_sio_callbacks[bus] = callback;
280 }
281 
hal_sio_v151_unregister(sio_bus_t bus)282 static void hal_sio_v151_unregister(sio_bus_t bus)
283 {
284     g_hal_sio_callbacks[bus] = NULL;
285 }
286 
hal_sio_v151_get_data(sio_bus_t bus,hal_sio_rx_data_t * data)287 static void hal_sio_v151_get_data(sio_bus_t bus, hal_sio_rx_data_t *data)
288 {
289     *data = g_sio_read_data[bus];
290 }
291 
hal_sio_v151_irq_handler(sio_bus_t bus)292 void hal_sio_v151_irq_handler(sio_bus_t bus)
293 {
294     uint32_t int_status;
295     int_status = hal_sio_v151_get_intstatus(bus);
296     if ((bit(0) & int_status) != 0) {
297         uint32_t trans_frames = hal_sio_v151_rx_sta_get_rx_right_depth(bus);
298         while (trans_frames-- > 0) {
299             g_sio_read_data[bus].left_buff[g_sio_read_data[bus].length] = hal_sio_read_data(bus, SIO_LEFT);
300             g_sio_read_data[bus].right_buff[g_sio_read_data[bus].length] = hal_sio_read_data(bus, SIO_RIGHT);
301             g_sio_read_data[bus].length++;
302         }
303         if (g_hal_sio_callbacks[bus]) {
304             g_hal_sio_callbacks[bus](g_sio_read_data[bus].left_buff, g_sio_read_data[bus].right_buff,
305                                      g_sio_read_data[bus].length);
306             (void)memset_s(((void *)&g_sio_read_data), sizeof(hal_sio_rx_data_t), 0,
307                            sizeof(hal_sio_rx_data_t));
308             g_sio_read_data[bus].length = 0;
309         }
310         hal_sio_v151_clear_interrupt(bus, bit(0));
311     }
312 
313     if ((bit(1) & int_status) != 0) {
314         if (g_i2s_index == 0) {
315             hal_sio_v151_clear_interrupt(bus, bit(1));
316         } else if (g_i2s_index < g_i2s_tx_length) {
317             uint32_t write_len = SIO_ONCE_TRANSFER_LEN;
318             if ((g_i2s_tx_length - g_i2s_index) < SIO_ONCE_TRANSFER_LEN) {
319                 write_len = g_i2s_tx_length - g_i2s_index;
320             }
321             for (uint32_t i = 0; i < write_len; i++) {
322                 hal_sio_write_data(bus, g_write_left_data[g_i2s_index + i], SIO_LEFT);
323                 hal_sio_write_data(bus, g_write_right_data[g_i2s_index + i], SIO_RIGHT);
324             }
325             g_i2s_index += write_len;
326             hal_sio_v151_clear_interrupt(bus, bit(1));
327         } else {
328             hal_sio_v151_clear_interrupt(bus, bit(1));
329             hal_sio_v151_set_intmask(bus, SIO_READ_INTMASK);
330             g_i2s_index = 0;
331             g_tx_trans[bus].trans_succ = true;
332             osal_sem_up(&(g_tx_trans[bus].trans_sem));
333         }
334     }
335 }
336 
337 #if defined(CONFIG_I2S_SUPPORT_LOOPBACK)
hal_sio_v151_loop(sio_bus_t bus,bool en)338 static void hal_sio_v151_loop(sio_bus_t bus, bool en)
339 {
340     hal_sio_v151_version_set_loop(bus, (uint32_t)en);
341 }
342 
hal_sio_v151_loop_trans(sio_bus_t bus,hal_sio_tx_data_t * data,hal_sio_mode_t mode)343 void hal_sio_v151_loop_trans(sio_bus_t bus, hal_sio_tx_data_t *data, hal_sio_mode_t mode)
344 {
345     hal_i2s_config(bus, mode);
346     g_i2s_tx_length = 0;
347     g_i2s_tx_length = data->length;
348     g_write_left_data = data->left_buff;
349     g_write_right_data = data->right_buff;
350 
351     if (g_i2s_tx_length < SIO_FIRST_TRANSFER_LEN) {
352         for (uint32_t i = 0; i < g_i2s_tx_length; i++) {
353             hal_sio_write_data(bus, g_write_left_data[i], SIO_LEFT);
354             hal_sio_write_data(bus, g_write_right_data[i], SIO_RIGHT);
355         }
356         g_i2s_index = g_i2s_tx_length;
357     } else {
358         for (uint32_t i = 0; i < SIO_FIRST_TRANSFER_LEN; i++) {
359             hal_sio_write_data(bus, g_write_left_data[i], SIO_LEFT);
360             hal_sio_write_data(bus, g_write_right_data[i], SIO_RIGHT);
361         }
362         g_i2s_index += SIO_FIRST_TRANSFER_LEN;
363     }
364     hal_sio_v151_txrx_enable(bus);
365 
366     if (osal_sem_down(&(g_tx_trans[bus].trans_sem)) != OSAL_SUCCESS) {
367         return;
368     }
369     if (!g_tx_trans[bus].trans_succ) {
370         return;
371     }
372     uapi_tcxo_delay_us(SIO_LAST_DELAY_US);
373     hal_sio_v151_txrx_disable(bus);
374     g_tx_trans[bus].trans_succ = false;
375 }
376 #endif
377 
hal_sio_v151_txrx_disable(sio_bus_t bus)378 void hal_sio_v151_txrx_disable(sio_bus_t bus)
379 {
380     sio_v151_ct_clr_data_t clr_set;
381     clr_set.d32 = sios_v151_regs(bus)->ct_clr;
382     clr_set.b.tx_enable = 1;
383     clr_set.b.rx_enable = 1;
384     clr_set.b.rst_n = 1;
385     sios_v151_regs(bus)->ct_clr = clr_set.d32;
386     hal_sio_v151_crg_clock_enable(bus, false);
387 }
388 
hal_sio_v151_txrx_enable(sio_bus_t bus)389 void hal_sio_v151_txrx_enable(sio_bus_t bus)
390 {
391     sio_v151_ct_set_data_t ct_set;
392     ct_set.d32 = sios_v151_regs(bus)->ct_set;
393     ct_set.b.tx_enable = 1;
394     ct_set.b.rx_enable = 1;
395     ct_set.b.rst_n = 1;
396     sios_v151_regs(bus)->ct_set = ct_set.d32;
397     hal_sio_v151_crg_clock_enable(bus, true);
398 }
399 
400 #if defined(CONFIG_I2S_SUPPORT_DMA)
401 #define SIO_INTMASK_TX_DISABLED 0x32
402 #define SIO_INTMASK_RX_DISABLED 0xd
hal_sio_v151_dma_cfg(sio_bus_t bus,const uintptr_t attr)403 static void hal_sio_v151_dma_cfg(sio_bus_t bus, const uintptr_t attr)
404 {
405     hal_i2s_dma_attr_t *dma_attr = (hal_i2s_dma_attr_t *)attr;
406     hal_i2s_config(bus, I2S_MODE);
407     hal_sio_v151_pos_merge_set_en(bus, 1);
408     if (dma_attr->tx_dma_enable) {
409         hal_sio_fifo_threshold_set_tx_fifo_threshold(bus, dma_attr->tx_int_threshold);
410         uint32_t mask = sios_v151_regs(bus)->intmask;
411         mask = (mask | SIO_INTMASK_TX_DISABLED);
412         hal_sio_set_intmask(bus, mask);
413     }
414     if (dma_attr->rx_dma_enable) {
415         hal_sio_fifo_threshold_set_rx_fifo_threshold(bus, dma_attr->rx_int_threshold);
416         uint32_t mask = sios_v151_regs(bus)->intmask;
417         mask = (mask | SIO_INTMASK_RX_DISABLED);
418         hal_sio_set_intmask(bus, mask);
419     }
420 }
421 #endif
422 
423 static hal_sio_funcs_t g_hal_sio_v151_funcs = {
424     .init = hal_sio_v151_init,
425     .deinit = hal_sio_v151_deinit,
426     .set_config = hal_sio_v151_set_config,
427     .get_config = hal_sio_v151_get_config,
428     .rx_enable = hal_sio_v151_rx_enable,
429     .write = hal_sio_v151_write,
430     .get_data = hal_sio_v151_get_data,
431     .registerfunc = hal_sio_v151_register,
432     .unregisterfunc = hal_sio_v151_unregister,
433 #if defined(CONFIG_I2S_SUPPORT_LOOPBACK)
434     .loop = hal_sio_v151_loop,
435     .loop_trans = hal_sio_v151_loop_trans,
436 #endif
437 #if defined(CONFIG_I2S_SUPPORT_DMA)
438     .dma_cfg = hal_sio_v151_dma_cfg,
439 #endif
440 };
441 
hal_sio_v151_funcs_get(void)442 hal_sio_funcs_t *hal_sio_v151_funcs_get(void)
443 {
444     return &g_hal_sio_v151_funcs;
445 }