1 /*
2 * Copyright (c) 2022-2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <rtthread.h>
9 #include <rtdevice.h>
10
11 #define DBG_TAG "i2s"
12 #define DBG_LVL DBG_INFO
13 #include <rtdbg.h>
14
15 #ifdef BSP_USING_I2S
16 #include "hpm_i2s_drv.h"
17 #include "board.h"
18 #ifdef HPMSOC_HAS_HPMSDK_DMAV2
19 #include "hpm_dmav2_drv.h"
20 #else
21 #include "hpm_dma_drv.h"
22 #endif
23 #include "hpm_dmamux_drv.h"
24 #include "hpm_l1c_drv.h"
25 #include "hpm_clock_drv.h"
26 #include "hpm_dma_mgr.h"
27
28 #include "drv_i2s.h"
29 #include "drivers/dev_audio.h"
30
31 static rt_ssize_t hpm_i2s_transmit(struct rt_audio_device* audio, const void* writeBuf, void* readBuf, rt_size_t size);
32
33 /**
34 * I2S state
35 */
36 typedef enum {
37 hpm_i2s_state_stop,
38 hpm_i2s_state_read,
39 hpm_i2s_state_write,
40 } hpm_i2s_state_t;
41
42 struct hpm_i2s
43 {
44 struct rt_audio_device audio;
45 struct rt_audio_configure audio_config;
46 dma_resource_t rx_dma_resource;
47 dma_resource_t tx_dma_resource;
48 char *dev_name;
49 I2S_Type *base;
50 clock_name_t clk_name;
51 i2s_transfer_config_t transfer;
52 uint8_t rx_dma_req;
53 uint8_t tx_dma_req;
54 rt_uint8_t* tx_buff;
55 rt_uint8_t* rx_buff;
56 hpm_i2s_state_t i2s_state;
57 };
58
59 #if defined(BSP_USING_I2S0)
60 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s0_tx_buff[I2S_FIFO_SIZE];
61 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s0_rx_buff[I2S_FIFO_SIZE];
62 #endif
63 #if defined(BSP_USING_I2S1)
64 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s1_tx_buff[I2S_FIFO_SIZE];
65 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s1_rx_buff[I2S_FIFO_SIZE];
66 #endif
67 #if defined(BSP_USING_I2S2)
68 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s2_tx_buff[I2S_FIFO_SIZE];
69 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s2_rx_buff[I2S_FIFO_SIZE];
70 #endif
71 #if defined(BSP_USING_I2S3)
72 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s3_tx_buff[I2S_FIFO_SIZE];
73 ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t i2s3_rx_buff[I2S_FIFO_SIZE];
74 #endif
75
76 static struct hpm_i2s hpm_i2s_set[] =
77 {
78 #if defined(BSP_USING_I2S0) && defined(HPM_I2S0)
79 {
80 .dev_name = "i2s0",
81 .base = HPM_I2S0,
82 .clk_name = clock_i2s0,
83 .rx_dma_req = HPM_DMA_SRC_I2S0_RX,
84 .tx_dma_req = HPM_DMA_SRC_I2S0_TX,
85 .tx_buff = i2s0_tx_buff,
86 .rx_buff = i2s0_rx_buff,
87 },
88 #endif
89 #if defined(BSP_USING_I2S1) && defined(HPM_I2S1)
90 {
91 .dev_name = "i2s1",
92 .base = HPM_I2S1;
93 .clk_name = clock_i2s1,
94 .rx_dma_req = HPM_DMA_SRC_I2S1_RX,
95 .tx_dma_req = HPM_DMA_SRC_I2S1_TX,
96 .tx_buff = i2s1_tx_buff,
97 .rx_buff = i2s1_rx_buff,
98 },
99 #endif
100 #if defined(BSP_USING_I2S2) && defined(HPM_I2S2)
101 {
102 .dev_name = "i2s2",
103 .base = HPM_I2S2,
104 .clk_name = clock_i2s2,
105 .rx_dma_req = HPM_DMA_SRC_I2S2_RX,
106 .tx_dma_req = HPM_DMA_SRC_I2S2_TX,
107 .tx_buff = i2s2_tx_buff,
108 .rx_buff = i2s2_rx_buff,
109 },
110 #endif
111 #if defined(BSP_USING_I2S3) && defined(HPM_I2S3)
112 {
113 .dev_name = "i2s3",
114 .base = HPM_I2S3,
115 .clk_name = clock_i2s3,
116 .rx_dma_req = HPM_DMA_SRC_I2S3_RX,
117 .tx_dma_req = HPM_DMA_SRC_I2S3_TX,
118 .tx_buff = i2s3_tx_buff,
119 .rx_buff = i2s3_rx_buff,
120 },
121 #endif
122 };
123
124 /* I2S TX DMA callback function: trigger next transfer */
i2s_tx_dma_tc_callback(DMA_Type * ptr,uint32_t channel,void * user_data)125 void i2s_tx_dma_tc_callback(DMA_Type *ptr, uint32_t channel, void *user_data)
126 {
127 struct hpm_i2s* hpm_audio = (struct hpm_i2s*) user_data;
128 rt_audio_tx_complete(&hpm_audio->audio);
129 }
130
131 /* I2S RX DMA callback function: write data into record->pipe and trigger next transfer */
i2s_rx_dma_tc_callback(DMA_Type * ptr,uint32_t channel,void * user_data)132 void i2s_rx_dma_tc_callback(DMA_Type *ptr, uint32_t channel, void *user_data)
133 {
134 struct hpm_i2s* hpm_audio = (struct hpm_i2s*) user_data;
135 rt_audio_rx_done(&hpm_audio->audio, hpm_audio->rx_buff, I2S_FIFO_SIZE);
136 hpm_i2s_transmit(&hpm_audio->audio, NULL, hpm_audio->rx_buff, I2S_FIFO_SIZE);
137 }
138
139
hpm_i2s_init(struct rt_audio_device * audio)140 static rt_err_t hpm_i2s_init(struct rt_audio_device* audio)
141 {
142 RT_ASSERT(audio != RT_NULL);
143 rt_uint32_t mclk_hz;
144 i2s_config_t i2s_config;
145 i2s_transfer_config_t transfer;
146
147 struct hpm_i2s* hpm_audio = (struct hpm_i2s*)audio->parent.user_data;
148
149 init_i2s_pins(hpm_audio->base);
150 board_init_i2s_clock(hpm_audio->base);
151
152 /* enable dma request */
153 i2s_enable_rx_dma_request(hpm_audio->base);
154 i2s_enable_tx_dma_request(hpm_audio->base);
155
156 i2s_get_default_config(hpm_audio->base, &i2s_config);
157 i2s_config.enable_mclk_out = true;
158 i2s_init(hpm_audio->base, &i2s_config);
159
160 mclk_hz = clock_get_frequency(hpm_audio->clk_name);
161 i2s_get_default_transfer_config(&transfer);
162 /* init I2S parameter */
163 transfer.sample_rate = 48000U;
164 transfer.protocol = I2S_PROTOCOL_LEFT_JUSTIFIED;
165 transfer.channel_slot_mask = I2S_CHANNEL_SLOT_MASK(0); /* one channel */
166 transfer.audio_depth = i2s_audio_depth_16_bits;
167 transfer.master_mode = true;
168 hpm_audio->transfer = transfer;
169 /* record i2s parameter to audio_config */
170 hpm_audio->audio_config.samplerate = 48000U;
171 hpm_audio->audio_config.samplebits = 16;
172 hpm_audio->audio_config.channels = 1;
173 if (status_success != i2s_config_transfer(hpm_audio->base, mclk_hz, &transfer))
174 {
175 LOG_E("dao_i2s configure transfer failed\n");
176 return -RT_ERROR;
177 }
178
179 hpm_audio->i2s_state = hpm_i2s_state_stop;
180
181 return RT_EOK;
182 }
183
hpm_i2s_getcaps(struct rt_audio_device * audio,struct rt_audio_caps * caps)184 static rt_err_t hpm_i2s_getcaps(struct rt_audio_device* audio, struct rt_audio_caps* caps)
185 {
186 rt_err_t result = RT_EOK;
187
188 RT_ASSERT(audio != RT_NULL);
189 struct hpm_i2s* hpm_audio = (struct hpm_i2s*)audio->parent.user_data;
190
191 switch(caps->main_type)
192 {
193 case AUDIO_TYPE_INPUT:
194 {
195 switch(caps->sub_type)
196 {
197 case AUDIO_DSP_PARAM:
198 {
199 caps->udata.config.channels = hpm_audio->audio_config.channels;
200 caps->udata.config.samplebits = hpm_audio->audio_config.samplebits;
201 caps->udata.config.samplerate = hpm_audio->audio_config.samplerate;
202 break;
203 }
204
205 case AUDIO_DSP_SAMPLERATE:
206 {
207 caps->udata.config.samplerate = hpm_audio->audio_config.samplerate;
208 break;
209 }
210
211 case AUDIO_DSP_CHANNELS:
212 {
213 caps->udata.config.channels = hpm_audio->audio_config.channels;
214 break;
215 }
216
217 case AUDIO_DSP_SAMPLEBITS:
218 {
219 caps->udata.config.samplebits = hpm_audio->audio_config.samplebits;
220 break;
221 }
222
223 case AUDIO_PARM_I2S_DATA_LINE:
224 {
225 caps->udata.value = hpm_audio->transfer.data_line;
226 break;
227 }
228
229 default:
230 {
231 result = -RT_ERROR;
232 break;
233 }
234 }
235 break;
236 }
237 case AUDIO_TYPE_OUTPUT:
238 {
239 switch(caps->sub_type)
240 {
241 case AUDIO_DSP_PARAM:
242 {
243 caps->udata.config.samplerate = hpm_audio->audio_config.samplerate;
244 caps->udata.config.channels = hpm_audio->audio_config.channels;
245 caps->udata.config.samplebits = hpm_audio->audio_config.samplebits;
246 break;
247 }
248
249 case AUDIO_DSP_SAMPLERATE:
250 {
251 caps->udata.config.samplerate = hpm_audio->audio_config.samplerate;
252 break;
253 }
254
255 case AUDIO_DSP_CHANNELS:
256 {
257 caps->udata.config.channels = hpm_audio->audio_config.channels;
258 break;
259 }
260
261 case AUDIO_DSP_SAMPLEBITS:
262 {
263 caps->udata.config.samplebits = hpm_audio->audio_config.samplebits;
264 break;
265 }
266
267 case AUDIO_PARM_I2S_DATA_LINE:
268 {
269 caps->udata.value = hpm_audio->transfer.data_line;
270 break;
271 }
272
273 default:
274 {
275 result = -RT_ERROR;
276 break;
277 }
278 }
279
280 break;
281 }
282
283 default:
284 result = -RT_ERROR;
285 break;
286 }
287
288 return result;
289 }
290
i2s_is_enabled(I2S_Type * ptr)291 static bool i2s_is_enabled(I2S_Type *ptr)
292 {
293 return ((ptr->CTRL & I2S_CTRL_I2S_EN_MASK) != 0);
294 }
295
hpm_i2s_configure(struct rt_audio_device * audio,struct rt_audio_caps * caps)296 static rt_err_t hpm_i2s_configure(struct rt_audio_device* audio, struct rt_audio_caps* caps)
297 {
298 rt_err_t result = RT_EOK;
299 RT_ASSERT(audio != RT_NULL);
300 struct hpm_i2s* hpm_audio = (struct hpm_i2s*)audio->parent.user_data;
301
302 switch(caps->main_type)
303 {
304 case AUDIO_TYPE_OUTPUT:
305 {
306 switch(caps->sub_type)
307 {
308 case AUDIO_DSP_PARAM:
309 {
310 hpm_audio->audio_config.samplerate = caps->udata.config.samplerate;
311 hpm_audio->audio_config.samplebits = caps->udata.config.samplebits;
312 hpm_audio->audio_config.channels = caps->udata.config.channels;
313 break;
314 }
315
316 case AUDIO_DSP_SAMPLERATE:
317 {
318 hpm_audio->audio_config.samplerate = caps->udata.config.samplerate;
319 break;
320 }
321
322 case AUDIO_DSP_CHANNELS:
323 {
324 hpm_audio->audio_config.channels = caps->udata.config.channels;
325 break;
326 }
327
328 case AUDIO_DSP_SAMPLEBITS:
329 {
330 hpm_audio->audio_config.samplebits = caps->udata.config.samplebits;
331 break;
332 }
333
334 case AUDIO_PARM_I2S_DATA_LINE:
335 {
336 hpm_audio->transfer.data_line = caps->udata.value;
337 break;
338 }
339
340 default:
341 result = -RT_ERROR;
342 break;
343 }
344 break;
345 }
346 case AUDIO_TYPE_INPUT:
347 {
348 switch(caps->sub_type)
349 {
350
351 case AUDIO_DSP_PARAM:
352 {
353 hpm_audio->audio_config.samplerate = caps->udata.config.samplerate;
354 hpm_audio->audio_config.channels = caps->udata.config.channels;
355 hpm_audio->audio_config.samplebits = caps->udata.config.samplebits;
356 break;
357 }
358
359 case AUDIO_DSP_SAMPLERATE:
360 {
361 hpm_audio->audio_config.samplerate = caps->udata.config.samplerate;
362 break;
363 }
364 case AUDIO_DSP_CHANNELS:
365 {
366 hpm_audio->audio_config.channels = caps->udata.config.channels;
367 break;
368 }
369
370 case AUDIO_DSP_SAMPLEBITS:
371 {
372 hpm_audio->audio_config.samplebits = caps->udata.config.samplebits;
373 break;
374 }
375
376 case AUDIO_PARM_I2S_DATA_LINE:
377 {
378 hpm_audio->transfer.data_line = caps->udata.value;
379 break;
380 }
381
382 default:
383 result = -RT_ERROR;
384 break;
385 }
386 break;
387 }
388
389 default:
390 break;
391 }
392
393 /* configure I2S transfer */
394 if (hpm_audio->audio_config.channels == i2s_mono_left) {
395 hpm_audio->transfer.channel_slot_mask = I2S_CHANNEL_SLOT_MASK(0);
396 } else if (hpm_audio->audio_config.channels == i2s_mono_right) {
397 hpm_audio->transfer.channel_slot_mask = I2S_CHANNEL_SLOT_MASK(1);
398 } else if(hpm_audio->audio_config.channels == 2) {
399 hpm_audio->transfer.channel_slot_mask = I2S_CHANNEL_SLOT_MASK(0) | I2S_CHANNEL_SLOT_MASK(1);
400 } else {
401 LOG_E("I2S not support channels number %d.\n", hpm_audio->audio_config.channels);
402 return -RT_ERROR;
403 }
404
405 hpm_audio->transfer.sample_rate = hpm_audio->audio_config.samplerate;
406
407 /* i2s dma only support sample bit: 16 and 32 bits */
408 assert(hpm_audio->audio_config.samplebits == 16 || hpm_audio->audio_config.samplebits == 32);
409 hpm_audio->transfer.audio_depth = hpm_audio->audio_config.samplebits;
410
411 /* Stop I2S transfer if the I2S needs to be re-configured */
412 bool is_enabled = i2s_is_enabled(hpm_audio->base);
413 if (is_enabled)
414 {
415 if (hpm_audio->i2s_state == hpm_i2s_state_read)
416 {
417 dma_abort_channel(hpm_audio->rx_dma_resource.base, hpm_audio->rx_dma_resource.channel);
418 }
419 if (hpm_audio->i2s_state == hpm_i2s_state_write)
420 {
421 dma_abort_channel(hpm_audio->tx_dma_resource.base, hpm_audio->tx_dma_resource.channel);
422 }
423 }
424 if (status_success != i2s_config_transfer(hpm_audio->base, clock_get_frequency(hpm_audio->clk_name), &hpm_audio->transfer))
425 {
426 LOG_E("%s configure transfer failed.\n", hpm_audio->dev_name);
427 return -RT_ERROR;
428 }
429 /* Restore I2S to previous state */
430 if (is_enabled)
431 {
432 i2s_enable(hpm_audio->base);
433 }
434
435 return result;
436 }
437
hpm_i2s_start(struct rt_audio_device * audio,int stream)438 static rt_err_t hpm_i2s_start(struct rt_audio_device* audio, int stream)
439 {
440 RT_ASSERT(audio != RT_NULL);
441
442 struct hpm_i2s* hpm_audio = (struct hpm_i2s*)audio->parent.user_data;
443
444 /* request DMA resource for audio data transfer */
445 if (stream == AUDIO_STREAM_REPLAY) {
446 i2s_disable(hpm_audio->base);
447 i2s_disable_tx_dma_request(hpm_audio->base);
448 dma_resource_t *dma_resource = &hpm_audio->tx_dma_resource;
449 if (dma_mgr_request_resource(dma_resource) == status_success) {
450 uint8_t dmamux_ch;
451 dma_mgr_install_chn_tc_callback(dma_resource, i2s_tx_dma_tc_callback, hpm_audio);
452 dma_mgr_enable_dma_irq_with_priority(dma_resource, 1);
453 dmamux_ch = DMA_SOC_CHN_TO_DMAMUX_CHN(dma_resource->base, dma_resource->channel);
454 dmamux_config(HPM_DMAMUX, dmamux_ch, hpm_audio->tx_dma_req, true);
455 } else {
456 LOG_E("no dma resource available for I2S TX transfer.\n");
457 return -RT_ERROR;
458 }
459 i2s_reset_tx(hpm_audio->base); /* disable and reset tx */
460 /* fill 2 dummy data, it is suitable for 1/2 channel of audio */
461 if (i2s_fill_tx_dummy_data(hpm_audio->base, hpm_audio->transfer.data_line , 2) != status_success) {
462 return -RT_ERROR;
463 }
464 rt_audio_tx_complete(audio);
465 i2s_enable(hpm_audio->base);
466 i2s_enable_tx_dma_request(hpm_audio->base);
467 } else if (stream == AUDIO_STREAM_RECORD) {
468 i2s_disable(hpm_audio->base);
469 i2s_disable_rx_dma_request(hpm_audio->base);
470 dma_resource_t *dma_resource = &hpm_audio->rx_dma_resource;
471 if (dma_mgr_request_resource(dma_resource) == status_success) {
472 uint8_t dmamux_ch;
473 dma_mgr_install_chn_tc_callback(dma_resource, i2s_rx_dma_tc_callback, hpm_audio);
474 dma_mgr_enable_dma_irq_with_priority(dma_resource, 1);
475 dmamux_ch = DMA_SOC_CHN_TO_DMAMUX_CHN(dma_resource->base, dma_resource->channel);
476 dmamux_config(HPM_DMAMUX, dmamux_ch, hpm_audio->rx_dma_req, true);
477 } else {
478 LOG_E("no dma resource available for I2S RX transfer.\n");
479 return -RT_ERROR;
480 }
481 i2s_reset_rx(hpm_audio->base); /* disable and reset rx */
482 if (I2S_FIFO_SIZE != hpm_i2s_transmit(&hpm_audio->audio, NULL, hpm_audio->rx_buff, I2S_FIFO_SIZE)) {
483 return -RT_ERROR;
484 }
485 i2s_enable(hpm_audio->base);
486 i2s_enable_rx_dma_request(hpm_audio->base);
487 } else {
488 return -RT_ERROR;
489 }
490
491 return RT_EOK;
492 }
493
hpm_i2s_stop(struct rt_audio_device * audio,int stream)494 static rt_err_t hpm_i2s_stop(struct rt_audio_device* audio, int stream)
495 {
496 RT_ASSERT(audio != RT_NULL);
497 struct hpm_i2s* hpm_audio = (struct hpm_i2s*)audio->parent.user_data;
498
499 i2s_disable(hpm_audio->base);
500
501 if (stream == AUDIO_STREAM_REPLAY) {
502 dma_resource_t *dma_resource = &hpm_audio->tx_dma_resource;
503 dma_abort_channel(dma_resource->base, dma_resource->channel);
504 dma_mgr_release_resource(dma_resource);
505 } else if (stream == AUDIO_STREAM_RECORD)
506 {
507 dma_resource_t *dma_resource = &hpm_audio->rx_dma_resource;
508 dma_abort_channel(dma_resource->base, dma_resource->channel);
509 dma_mgr_release_resource(dma_resource);
510 } else {
511 return -RT_ERROR;
512 }
513
514 hpm_audio->i2s_state = hpm_i2s_state_stop;
515
516 return RT_EOK;
517 }
518
hpm_i2s_transmit(struct rt_audio_device * audio,const void * writeBuf,void * readBuf,rt_size_t size)519 static rt_ssize_t hpm_i2s_transmit(struct rt_audio_device* audio, const void* writeBuf, void* readBuf, rt_size_t size)
520 {
521 RT_ASSERT(audio != RT_NULL);
522 struct hpm_i2s* hpm_audio = (struct hpm_i2s*)audio->parent.user_data;
523
524 /* i2s dma only support sample bit: 16 and 32 bits */
525 uint8_t data_width;
526 uint8_t data_shift_byte;
527 if (hpm_audio->transfer.audio_depth == i2s_audio_depth_16_bits) {
528 data_width = DMA_TRANSFER_WIDTH_HALF_WORD;
529 data_shift_byte = 2U ; /* put 16bit data on high bit of register */
530 } else {
531 data_width = DMA_TRANSFER_WIDTH_WORD;
532 data_shift_byte = 0U;
533 }
534
535 if(writeBuf != RT_NULL)
536 {
537 dma_resource_t *dma_resource = &hpm_audio->tx_dma_resource;
538 dma_channel_config_t ch_config = {0};
539 dma_default_channel_config(dma_resource->base, &ch_config);
540 ch_config.src_addr = core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)writeBuf);
541 ch_config.dst_addr = (uint32_t)&hpm_audio->base->TXD[hpm_audio->transfer.data_line] + data_shift_byte;
542 ch_config.src_width = data_width;
543 ch_config.dst_width = data_width;
544 ch_config.src_addr_ctrl = DMA_ADDRESS_CONTROL_INCREMENT;
545 ch_config.dst_addr_ctrl = DMA_ADDRESS_CONTROL_FIXED;
546 ch_config.size_in_byte = size;
547 ch_config.dst_mode = DMA_HANDSHAKE_MODE_HANDSHAKE;
548 ch_config.src_burst_size = DMA_NUM_TRANSFER_PER_BURST_1T;
549
550 if (l1c_dc_is_enabled()) {
551 /* cache writeback for sent buff */
552 l1c_dc_writeback((uint32_t)writeBuf, size);
553 }
554
555 hpm_audio->i2s_state = hpm_i2s_state_write;
556 if (status_success != dma_setup_channel(dma_resource->base, dma_resource->channel, &ch_config, true)) {
557 LOG_E("dma setup channel failed\n");
558 return -RT_ERROR;
559 }
560 } else if (readBuf != RT_NULL){
561 dma_resource_t *dma_resource = &hpm_audio->rx_dma_resource;
562 dma_channel_config_t ch_config = {0};
563 dma_default_channel_config(dma_resource->base, &ch_config);
564 ch_config.src_addr = (uint32_t)&hpm_audio->base->RXD[hpm_audio->transfer.data_line] + data_shift_byte;
565 ch_config.dst_addr = core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)readBuf);
566 ch_config.src_width = data_width;
567 ch_config.dst_width = data_width;
568 ch_config.src_addr_ctrl = DMA_ADDRESS_CONTROL_FIXED;
569 ch_config.dst_addr_ctrl = DMA_ADDRESS_CONTROL_INCREMENT;
570 ch_config.size_in_byte = size;
571 ch_config.src_mode = DMA_HANDSHAKE_MODE_HANDSHAKE;
572 ch_config.src_burst_size = DMA_NUM_TRANSFER_PER_BURST_1T;
573
574 hpm_audio->i2s_state = hpm_i2s_state_read;
575 if (status_success != dma_setup_channel(dma_resource->base, dma_resource->channel, &ch_config, true)) {
576 LOG_E("dma setup channel failed\n");
577 return -RT_ERROR;
578 }
579
580 if (l1c_dc_is_enabled()) {
581 /* cache invalidate for receive buff */
582 l1c_dc_invalidate((uint32_t)readBuf, size);
583 }
584 }
585
586 return size;
587 }
588
hpm_i2s_buffer_info(struct rt_audio_device * audio,struct rt_audio_buf_info * info)589 static void hpm_i2s_buffer_info(struct rt_audio_device* audio, struct rt_audio_buf_info* info)
590 {
591 RT_ASSERT(audio != RT_NULL);
592 struct hpm_i2s* hpm_audio = (struct hpm_i2s*)audio->parent.user_data;
593 /**
594 * AUD_FIFO
595 * +----------------+----------------+
596 * | block1 | block2 |
597 * +----------------+----------------+
598 * \ block_size /
599 */
600 info->buffer = hpm_audio->tx_buff;
601 info->total_size = I2S_FIFO_SIZE;
602 info->block_size = I2S_FIFO_SIZE / 2;
603 info->block_count = 2;
604 }
605
606
607 static struct rt_audio_ops hpm_i2s_ops =
608 {
609 .getcaps = hpm_i2s_getcaps,
610 .configure = hpm_i2s_configure,
611 .init = hpm_i2s_init,
612 .start = hpm_i2s_start,
613 .stop = hpm_i2s_stop,
614 .transmit = hpm_i2s_transmit,
615 .buffer_info = hpm_i2s_buffer_info,
616 };
617
rt_hw_i2s_init(void)618 int rt_hw_i2s_init(void)
619 {
620 rt_err_t ret = RT_EOK;
621
622 for (uint32_t i = 0; i < sizeof(hpm_i2s_set) / sizeof(hpm_i2s_set[0]); i++) {
623 hpm_i2s_set[i].audio.ops = &hpm_i2s_ops;
624
625 ret = rt_audio_register(&hpm_i2s_set[i].audio, hpm_i2s_set[i].dev_name, RT_DEVICE_FLAG_RDWR, &hpm_i2s_set[i]);
626
627 if (ret != RT_EOK)
628 {
629 LOG_E("rt audio %s register failed, status=%d\n", hpm_i2s_set[i].dev_name, ret);
630 }
631
632 }
633
634 return RT_EOK;
635 }
636 INIT_DEVICE_EXPORT(rt_hw_i2s_init);
637
638
639 #endif /* BSP_USING_I2S */
640