drv_i2s.c 8.6 KB

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