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 }