• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
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 
16 #ifndef __WM_I2S_H
17 #define __WM_I2S_H
18 
19 #include <stdbool.h>
20 #include "wm_regs.h"
21 #include "wm_debug.h"
22 #include "wm_dma.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 typedef void (*tls_i2s_callback)(uint32_t *data, uint16_t *len);
29 
30 typedef struct {
31     __IO uint32_t CTRL;
32     __IO uint32_t INT_MASK;
33     __IO uint32_t INT_SRC;
34     __I  uint32_t INT_STATUS;
35     __O  uint32_t TX;
36     __I uint32_t RX;
37 } I2S_T;
38 
39 typedef struct {
40     uint32_t I2S_Mode_MS; // master or slave mode
41     uint32_t I2S_Mode_SS; // stereo or single channel
42     uint32_t I2S_Mode_LR; // left or right channel
43     uint32_t I2S_Trans_STD;
44     uint32_t I2S_DataFormat;
45     uint32_t I2S_AudioFreq;
46     uint32_t I2S_MclkFreq;
47 } I2S_InitDef;
48 
49 typedef struct _wm_dma_desc {
50     unsigned int valid;
51     unsigned int dma_ctrl;
52     unsigned int src_addr;
53     unsigned int dest_addr;
54     struct _wm_dma_desc *next;
55 }wm_dma_desc;
56 
57 typedef struct _dma_handler_type {
58     uint8_t channel;
59     void    (* XferCpltCallback)(struct _dma_handler_type *hdma);     /* !< DMA transfer complete callback */
60     void    (* XferHalfCpltCallback)(struct _dma_handler_type *hdma); /* !< DMA Half transfer complete callback    */
61 }wm_dma_handler_type;
62 
63 #define I2S			            ((I2S_T *)HR_I2S_REG_BASE)
64 
65 #define I2S_MODE_MASTER		    ((bool)0x0)
66 #define I2S_MODE_SLAVE		    ((bool)0x1)
67 
68 #define I2S_RIGHT_CHANNEL		((bool)0x0)
69 #define I2S_LEFT_CHANNEL		((bool)0x1)
70 
71 #define I2S_Standard			(0x0UL)
72 #define I2S_Standard_MSB		(0x1000000UL)
73 #define I2S_Standard_PCMA		(0x2000000UL)
74 #define I2S_Standard_PCMB		(0x3000000UL)
75 
76 #define I2S_DataFormat_8		(8)
77 #define I2S_DataFormat_16		(16)
78 #define I2S_DataFormat_24		(24)
79 #define I2S_DataFormat_32		(32)
80 
81 #define I2S_CTRL_CHSEL_MASK		(1UL<<23)
82 #define I2S_CTRL_CHSEL_LEFT		(1UL<<23)
83 #define I2S_CTRL_MONO			(1UL<<22)
84 #define I2S_CTRL_STEREO			(0UL<<22)
85 #define I2S_CTRL_RXDMA_EN		(1UL<<21)
86 #define I2S_CTRL_TXDMA_EN		(1UL<<20)
87 #define I2S_CTRL_RX_CLR			(1UL<<19)
88 #define I2S_CTRL_TX_CLR			(1UL<<18)
89 #define I2S_CTRL_LZCEN			(1UL<<17)
90 #define I2S_CTRL_RZCEN			(1UL<<16)
91 #define I2S_CTRL_RXTH(n)		(((n)-1)<<12)
92 #define I2S_CTRL_TXTH(n)		((n)<<9)
93 #define I2S_CTRL_SLAVE_SEL		(1UL<<8)
94 #define I2S_CTRL_MUTE			(1UL<<3)
95 #define I2S_CTRL_RXE			(1UL<<2)
96 #define I2S_CTRL_TXE			(1UL<<1)
97 #define I2S_CTRL_EN				(1UL<<0)
98 
99 #define I2S_INT_MASK_LZC		((uint16_t)0x200)
100 #define I2S_INT_MASK_RZC		((uint16_t)0x100)
101 #define I2S_INT_MASK_TXDONE		((uint16_t)0x080)
102 #define I2S_INT_MASK_TXTH		((uint16_t)0x040)
103 #define I2S_INT_MASK_TXOV		((uint16_t)0x020)
104 #define I2S_INT_MASK_TXUD		((uint16_t)0x010)
105 #define I2S_INT_MASK_RXDONE		((uint16_t)0x008)
106 #define I2S_INT_MASK_RXTH		((uint16_t)0x004)
107 #define I2S_INT_MASK_RXOV		((uint16_t)0x002)
108 #define I2S_INT_MASK_RXUD		((uint16_t)0x002)
109 
110 #define I2S_FLAG_TX					((uint16_t)0x1000)
111 #define I2S_FLAG_RX					((uint16_t)0x0800)
112 #define I2S_FLAG_I2S				((uint16_t)0x0400)
113 #define I2S_FLAG_LZC				((uint16_t)0x0200)
114 #define I2S_FLAG_RZC				((uint16_t)0x0100)
115 #define I2S_FLAG_TXDONE				((uint16_t)0x0080)
116 #define I2S_FLAG_TXTH				((uint16_t)0x0040)
117 #define I2S_FLAG_TXOV				((uint16_t)0x0020)
118 #define I2S_FLAG_TXUD				((uint16_t)0x0010)
119 #define I2S_FLAG_RXDONE				((uint16_t)0x0008)
120 #define I2S_FLAG_RXTH				((uint16_t)0x0004)
121 #define I2S_FLAG_RXOV				((uint16_t)0x0002)
122 #define I2S_FLAG_RXUD				((uint16_t)0x0001)
123 
124 #define WM_I2S_TX_DMA_CHANNEL       (1)
125 #define WM_I2S_RX_DMA_CHANNEL       (5)
126 
127 typedef struct wm_i2s_buf_s {
128     volatile uint32_t *txbuf;
129     volatile uint32_t txlen;
130     volatile uint32_t txtail;
131     volatile uint32_t *rxbuf;
132     volatile uint32_t rxlen;
133     volatile uint32_t int_txlen;
134     volatile uint32_t rxhead;
135     volatile uint8_t rxdata_ready;
136     volatile uint8_t txdata_done;
137 
138     /** function pointer for data receiver  */
139     void (*rx_callback)(void);
140     /** function pointer for data transmit  */
141     void (*tx_callback)(uint32_t *data, uint16_t *len);
142 } wm_i2s_buf_t;
143 /**
144  * @defgroup Driver_APIs Driver APIs
145  * @brief Driver APIs
146  */
147 
148 /**
149  * @addtogroup Driver_APIs
150  * @{
151  */
152 
153 /**
154  * @defgroup I2S_Driver_APIs I2S Driver APIs
155  * @brief I2S driver APIs
156  */
157 
158 /**
159  * @addtogroup I2S_Driver_APIs
160  * @{
161  */
162 
163 /**
164   * @brief Register a callback function
165   * @param  callback pointer to a callback function in which you can prepare the next buffer
166   * @param  callback->data  pointer to data buffer to be prepared
167   * @param  callback->len size of the data buffer to be prepared in 32-bit
168   * @note The registerred callback function will be called as long as the transmission begins
169   * @retval none
170   */
171 void wm_i2s_register_callback(tls_i2s_callback callback);
172 
173 /**
174   * @brief Initializes the I2S according to the specified parameters
175   *         in the I2S_InitDef.
176   * @param  opts pointer to a I2S_InitDef structure that contains
177   *         the configuration information for I2S module
178   * @retval status
179   */
180 int wm_i2s_port_init(I2S_InitDef *opts);
181 
182 /**
183   * @brief stop i2s module
184   * @retval none
185   */
186 void wm_i2s_tx_rx_stop(void);
187 
188 /**
189   * @brief Transmit an amount of data in blocking mode with Interrupt
190   * @param data a 16-bit pointer to data buffer.
191   * @param len number of data sample to be sent:
192   * @param next_data a 16-bit pointer to the next data buffer, same size with data; set to NULL if it's not needed
193   * @note  the len parameter means the number of 16-bit data length.
194   * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
195   *       between Master and Slave(example: audio streaming).
196   * @note This function will block its task until the transmission is over,so perpare the next data
197   *       buffer at another task during this interval.
198   * @note This function will call the registerred callback function as long as the transmission begins
199   * @retval status
200   */
201 int wm_i2s_tx_int(int16_t *data, uint16_t len, int16_t *next_data);
202 
203 /**
204   * @brief Transmit an amount of data in blocking mode with DMA's normal mode
205   * @param data a 16-bit pointer to data buffer.
206   * @param len number of data sample to be sent:
207   * @param next_data a 16-bit pointer to the next data buffer, same size with data; set to NULL if it's not needed
208   * @note  the len parameter means the number of 32-bit data length.
209   * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
210   *       between Master and Slave(example: audio streaming).
211   * @note This function will block its task until the transmission is over,so perpare the next data
212   *       buffer at another task during this interval.
213   * @note This function will call the registerred callback function as long as the transmission begins
214   * @retval status
215   */
216 int wm_i2s_tx_dma(int16_t *data, uint16_t len, int16_t *next_data);
217 
218 /**
219   * @brief Transmit an amount of data in blocking mode with DMA's link mode
220   * @param data a 16-bit pointer to data buffer.
221   * @param len number of data sample to be sent:
222   * @param next_data a 16-bit pointer to the next data buffer, same size with data:
223   * @note  the len parameter means the number of 32-bit data length.
224   * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
225   *       between Master and Slave(example: audio streaming).
226   * @note This function will block its task until the transmission is over,so perpare the next data
227   *       buffer at another task during this interval.Set len to 0xffff will exit this rountine.
228   * @note This function will call the registerred callback function as long as the data or next_data
229   *       is sent out.So prepare it in the callback.
230   * @note See the demo for detail use.
231   * @retval status
232   */
233 int wm_i2s_tx_dma_link(int16_t *data, uint16_t len, int16_t *next_data);
234 
235 /**
236   * @brief Receive an amount of data in blocking mode with Interrupt
237   * @param data a 16-bit pointer to the Receive data buffer.
238   * @param len number of data sample to be received:
239   * @note the len parameter means the number of 16-bit data length.
240   * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
241   *       between Master and Slave(example: audio streaming).
242   * @note This function will block its task until the transmission is over,so perpare the next data
243   *       buffer at another task during this interval.
244   * @retval status
245   */
246 int wm_i2s_rx_int(int16_t *data, uint16_t len);
247 
248 /**
249   * @brief Receive an amount of data in blocking mode with DMA
250   * @param data a 16-bit pointer to the Receive data buffer.
251   * @param len number of data sample to be received:
252   * @note the len parameter means the number of 16-bit data length.
253   * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
254   *       between Master and Slave(example: audio streaming).
255   * @note This function will block its task until the transmission is over,so perpare the next data
256   *       buffer at another task during this interval.
257   * @retval status
258   */
259 int wm_i2s_rx_dma(int16_t *data, uint16_t len);
260 
261 /**
262   * @brief Full-Duplex Transmit/Receive data in blocking mode using Interrupt
263   * @param  opts pointer to a I2S_InitDef structure that contains
264   *         the configuration information for I2S module
265   * @param data_tx a 16-bit pointer to the Transmit data buffer.
266   * @param data_rx a 16-bit pointer to the Receive data buffer.
267   * @param len number of data sample to be sent:
268   * @note  the len parameter means the number of 16-bit data length.
269   * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
270   *       between Master and Slave(example: audio streaming).
271   * @note This function will block its task until the transmission is over,so perpare the next data
272   *       buffer at another task during this interval.
273   * @retval status
274   */
275 int wm_i2s_tx_rx_int(I2S_InitDef *opts, int16_t *data_tx, int16_t *data_rx, uint16_t len);
276 
277 /**
278   * @brief Full-Duplex Transmit/Receive data in blocking mode using DMA
279   * @param  opts pointer to a I2S_InitDef structure that contains
280   *         the configuration information for I2S module
281   * @param data_tx a 16-bit pointer to the Transmit data buffer.
282   * @param data_rx a 16-bit pointer to the Receive data buffer.
283   * @param len number of data sample to be sent:
284   * @note  the len parameter means the number of 16-bit data length.
285   * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
286   *       between Master and Slave(example: audio streaming).
287   * @note This function will block its task until the transmission is over,so perpare the next data
288   *       buffer at another task during this interval.
289   * @retval status
290   */
291 int wm_i2s_tx_rx_dma(I2S_InitDef *opts, int16_t *data_tx, int16_t *data_rx, uint16_t len);
292 
293 int wm_i2s_transmit_dma(wm_dma_handler_type *hdma, uint16_t *data, uint16_t len);
294 int wm_i2s_receive_dma(wm_dma_handler_type *hdma, uint16_t *data, uint16_t len);
295 
296 /**
297  * @}
298  */
299 
300 /**
301  * @}
302  */
303 
304 #ifdef __cplusplus
305 }
306 #endif
307 
308 #endif
309