1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-03-12 Vandoul the first version
9 */
10
11 #include <rtthread.h>
12 #include "fsl_i2s.h"
13 #include "fsl_i2s_dma.h"
14 #include "drv_i2s.h"
15
16 #define DBG_TAG "DRVI2S"
17 #include "rtdbg.h"
18
19 #ifdef BSP_USING_I2S
20
21 #if !defined(BSP_USING_I2S0) && \
22 !defined(BSP_USING_I2S1) && \
23 !defined(BSP_USING_I2S2) && \
24 !defined(BSP_USING_I2S3) && \
25 !defined(BSP_USING_I2S4) && \
26 !defined(BSP_USING_I2S5) && \
27 !defined(BSP_USING_I2S6) && \
28 !defined(BSP_USING_I2S7)
29 #error "Please define at least one I2Sx"
30 #endif
31
32 #include <rtdevice.h>
33
34 enum {
35 #ifdef BSP_USING_I2S0
36 I2S0_INDEX,
37 #endif
38 #ifdef BSP_USING_I2S1
39 I2S1_INDEX,
40 #endif
41 #ifdef BSP_USING_I2S2
42 I2S2_INDEX,
43 #endif
44 #ifdef BSP_USING_I2S3
45 I2S3_INDEX,
46 #endif
47 #ifdef BSP_USING_I2S4
48 I2S4_INDEX,
49 #endif
50 #ifdef BSP_USING_I2S5
51 I2S5_INDEX,
52 #endif
53 #ifdef BSP_USING_I2S6
54 I2S6_INDEX,
55 #endif
56 #ifdef BSP_USING_I2S7
57 I2S7_INDEX,
58 #endif
59 };
60
61 struct lpc_i2s_clock_and_irq_param
62 {
63 clock_attach_id_t i2s_clock;
64 reset_ip_name_t i2s_reset_bit;
65 IRQn_Type irq_type;
66 };
67
68 struct lpc_i2s
69 {
70 struct rt_device device;
71 i2s_handle_t i2s_handle;
72 struct lpc_i2s_config config;
73 uint32_t index;
74 I2S_Type *i2s_base;
75 const char *device_name;
76 };
77
78 #define LPC_I2S_CONFIG_MODE_IS_SLAVE(dev) ((dev)->config.mode == LPC_I2S_CONFIG_MODE_SLAVE)
79 #define LPC_I2S_CONFIG_MODE_IS_MASTER(dev) ((dev)->config.mode == LPC_I2S_CONFIG_MODE_MASTER)
80
81 #define LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(index) {.i2s_clock = kPLL0_DIV_to_FLEXCOMM##index, .i2s_reset_bit = kFC##index##_RST_SHIFT_RSTn, .irq_type = FLEXCOMM##index##_IRQn,}
82 const static struct lpc_i2s_clock_and_irq_param lpc_i2s_clock_and_irq_param_table[] =
83 {
84 #ifdef BSP_USING_I2S0
85 // {.i2s_clock = kPLL0_DIV_to_FLEXCOMM0, .i2s_reset_bit = kFC0_RST_SHIFT_RSTn, .irq_type = FLEXCOMM0_IRQn,},
86 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(0),
87 #endif
88 #ifdef BSP_USING_I2S1
89 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(1),
90 #endif
91 #ifdef BSP_USING_I2S2
92 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(2),
93 #endif
94 #ifdef BSP_USING_I2S3
95 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(3),
96 #endif
97 #ifdef BSP_USING_I2S4
98 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(4),
99 #endif
100 #ifdef BSP_USING_I2S5
101 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(5),
102 #endif
103 #ifdef BSP_USING_I2S6
104 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(6),
105 #endif
106 #ifdef BSP_USING_I2S7
107 LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(7),
108 #endif
109 };
110
111 static struct lpc_i2s lpc_i2s_table[] =
112 {
113 #ifdef BSP_USING_I2S0
114 {.index = I2S0_INDEX,.i2s_base = I2S0,.device_name = "i2s0"},
115 #endif
116 #ifdef BSP_USING_I2S1
117 {.index = I2S1_INDEX,.i2s_base = I2S1,.device_name = "i2s1"},
118 #endif
119 #ifdef BSP_USING_I2S2
120 {.index = I2S2_INDEX,.i2s_base = I2S2,.device_name = "i2s2"},
121 #endif
122 #ifdef BSP_USING_I2S3
123 {.index = I2S3_INDEX,.i2s_base = I2S3,.device_name = "i2s3"},
124 #endif
125 #ifdef BSP_USING_I2S4
126 {.index = I2S4_INDEX,.i2s_base = I2S4,.device_name = "i2s4"},
127 #endif
128 #ifdef BSP_USING_I2S5
129 {.index = I2S5_INDEX,.i2s_base = I2S5,.device_name = "i2s5"},
130 #endif
131 #ifdef BSP_USING_I2S6
132 {.index = I2S6_INDEX,.i2s_base = I2S6,.device_name = "i2s6"},
133 #endif
134 #ifdef BSP_USING_I2S7
135 {.index = I2S7_INDEX,.i2s_base = I2S7,.device_name = "i2s7"},
136 #endif
137 };
138
transfer_callback(I2S_Type * base,i2s_handle_t * handle,status_t completionStatus,void * userData)139 static void transfer_callback(I2S_Type *base, i2s_handle_t *handle, status_t completionStatus, void *userData)
140 {
141 struct lpc_i2s *i2s_dev = rt_container_of(handle, struct lpc_i2s, i2s_handle);
142 if(LPC_I2S_CONFIG_MODE_IS_SLAVE(i2s_dev))
143 {
144 if(i2s_dev->device.rx_indicate != RT_NULL)
145 {
146 i2s_dev->device.rx_indicate(&i2s_dev->device, completionStatus);
147 }
148 }
149 else
150 {
151 if(i2s_dev->device.tx_complete != RT_NULL)
152 {
153 i2s_dev->device.tx_complete(&i2s_dev->device, RT_NULL);
154 }
155 }
156 }
157
i2s_clock_and_irq_config(struct lpc_i2s * dev)158 static void i2s_clock_and_irq_config(struct lpc_i2s *dev)
159 {
160 const struct lpc_i2s_clock_and_irq_param *clock_and_irq_param = &lpc_i2s_clock_and_irq_param_table[dev->index];
161 // CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 0U, true);
162 // CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 1U, false);
163 CLOCK_AttachClk(clock_and_irq_param->i2s_clock);
164 RESET_PeripheralReset(clock_and_irq_param->i2s_reset_bit);
165 NVIC_ClearPendingIRQ(clock_and_irq_param->irq_type);
166 /* Enable interrupts for I2S */
167 EnableIRQ(clock_and_irq_param->irq_type);
168 }
rt_i2s_init(rt_device_t dev)169 rt_err_t rt_i2s_init(rt_device_t dev)
170 {
171 struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
172 i2s_clock_and_irq_config(i2s_dev);
173 return RT_EOK;
174 }
rt_i2s_open(rt_device_t dev,rt_uint16_t oflag)175 rt_err_t rt_i2s_open(rt_device_t dev, rt_uint16_t oflag)
176 {
177 struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
178 i2s_config_t config;
179 if(i2s_dev->config.mode == LPC_I2S_CONFIG_MODE_SLAVE)
180 {
181 RT_ASSERT(i2s_dev->config.is_blocking == 0);
182 I2S_RxGetDefaultConfig(&config);
183 config.divider = CLOCK_GetPll0OutFreq()/i2s_dev->config.sampling_rate/i2s_dev->config.data_bits/i2s_dev->config.channels;
184 config.masterSlave = kI2S_MasterSlaveNormalSlave;
185 I2S_RxInit(i2s_dev->i2s_base, &config);
186 I2S_RxTransferCreateHandle(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer_callback, NULL);
187 }
188 else if(i2s_dev->config.mode == LPC_I2S_CONFIG_MODE_MASTER)
189 {
190 RT_ASSERT(i2s_dev->config.is_blocking == 0);
191 I2S_TxGetDefaultConfig(&config);
192 config.divider = CLOCK_GetPll0OutFreq()/i2s_dev->config.sampling_rate/i2s_dev->config.data_bits/i2s_dev->config.channels;
193 config.masterSlave = kI2S_MasterSlaveNormalMaster;
194 I2S_TxInit(i2s_dev->i2s_base, &config);
195 I2S_TxTransferCreateHandle(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer_callback, NULL);
196 }
197 return RT_EOK;
198 }
rt_i2s_close(rt_device_t dev)199 rt_err_t rt_i2s_close(rt_device_t dev)
200 {
201 struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
202 I2S_Deinit(i2s_dev->i2s_base);
203 return RT_EOK;
204 }
rt_i2s_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)205 rt_ssize_t rt_i2s_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
206 {
207 struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
208 if(!LPC_I2S_CONFIG_MODE_IS_SLAVE(i2s_dev))
209 {
210 return -RT_ERROR;
211 }
212 i2s_transfer_t transfer;
213 transfer.data = buffer;
214 transfer.dataSize = size;
215 if(kStatus_Success == I2S_RxTransferNonBlocking(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer))
216 return size;
217 else
218 return -RT_EBUSY;
219 }
rt_i2s_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)220 rt_ssize_t rt_i2s_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
221 {
222 struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
223 if(!LPC_I2S_CONFIG_MODE_IS_MASTER(i2s_dev))
224 {
225 return -RT_ERROR;
226 }
227 i2s_transfer_t transfer;
228 transfer.data = (uint8_t *)buffer;
229 transfer.dataSize = size;
230 if(kStatus_Success == I2S_TxTransferNonBlocking(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer))
231 return size;
232 else
233 return -RT_EBUSY;
234 }
rt_i2s_control(rt_device_t dev,int cmd,void * args)235 rt_err_t rt_i2s_control(rt_device_t dev, int cmd, void *args)
236 {
237 struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
238 rt_err_t ret = RT_EOK;
239 RT_ASSERT(dev != RT_NULL);
240 RT_ASSERT(args != RT_NULL);
241 switch(cmd)
242 {
243 case RT_I2S_CTRL_RESET:
244 i2s_clock_and_irq_config(i2s_dev);
245 break;
246 case RT_I2S_CTRL_SET_CONFIG:
247 {
248 struct lpc_i2s_config *config = (struct lpc_i2s_config *)args;
249 i2s_dev->config = *config;
250 }
251 break;
252 default:
253 ret = -RT_ERROR;
254 break;
255 }
256 return ret;
257 }
258
259 #ifdef RT_USING_DEVICE_OPS
260 const static struct rt_device_ops i2s_core_ops =
261 {
262 rt_i2s_init,
263 rt_i2s_open,
264 rt_i2s_close,
265 rt_i2s_read,
266 rt_i2s_write,
267 rt_i2s_control,
268 };
269 #endif /* RT_USING_DEVICE_OPS */
270
rt_hw_i2s_init(void)271 int rt_hw_i2s_init(void)
272 {
273 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
274 int i;
275
276 for (i = 0; i < sizeof(lpc_i2s_table) / sizeof(lpc_i2s_table[0]); i++)
277 {
278 #ifdef RT_USING_DEVICE_OPS
279 lpc_i2s_table[i].device.ops = &i2s_core_ops;
280 #else
281 lpc_i2s_table[i].device.init = rt_i2s_init;
282 lpc_i2s_table[i].device.open = rt_i2s_open;
283 lpc_i2s_table[i].device.close = rt_i2s_close;
284 lpc_i2s_table[i].device.read = rt_i2s_read;
285 lpc_i2s_table[i].device.write = rt_i2s_write;
286 lpc_i2s_table[i].device.control = rt_i2s_control;
287 #endif
288
289 /* register UART device */
290 rt_device_register(&lpc_i2s_table[i].device,
291 lpc_i2s_table[i].device_name,
292 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
293 }
294
295 return 0;
296 }
297
298 INIT_BOARD_EXPORT(rt_hw_i2s_init);
299
300 #endif
301
302