1 /**
2 ******************************************************************************
3 * @file rtl8721dhp_audio.c
4 * @author
5 * @version V1.0.0
6 * @date 2017-12-13
7 * @brief This file provides firmware functions to manage the following
8 * functionalities of the Audio codec peripheral:
9 * - SPORT Initialization
10 * - SPORT parameters management
11 * - Data transfers configuration
12 * - GDMA configuration
13 *
14 ******************************************************************************
15 * @attention
16 *
17 * This module is a confidential and proprietary property of RealTek and
18 * possession or use of this module requires written permission of RealTek.
19 *
20 * Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
21 ******************************************************************************
22 */
23 #include "ameba_soc.h"
24
25 const AUDIO_DevTable AUDIO_DEV_TABLE[1] = {
26 {AUDIO_SPORT_DEV, GDMA_HANDSHAKE_INTERFACE_AUDIO_TX, GDMA_HANDSHAKE_INTERFACE_AUDIO_RX}, /*audio sport */
27 };
28
29 /**
30 * @brief Fills each SP_StructInit member with its default value.
31 * @param SP_StructInit: pointer to an SP_StructInit structure which will be
32 * initialized.
33 * @retval None
34 */
AUDIO_SP_StructInit(SP_InitTypeDef * SP_InitStruct)35 void AUDIO_SP_StructInit(SP_InitTypeDef* SP_InitStruct)
36 {
37 SP_InitStruct->SP_WordLen = SP_WL_16;
38 SP_InitStruct->SP_DataFormat = SP_DF_I2S;
39 SP_InitStruct->SP_MonoStereo = SP_CH_STEREO;
40 SP_InitStruct->SP_SelRxCh = SP_RX_CH_LR;
41 }
42
43 /**
44 * @brief Initializes the AUDIO SPORT registers according to the specified parameters
45 * in SP_InitStruct.
46 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
47 * @param SP_InitStruct: pointer to an SP_InitTypeDef structure that contains
48 * the configuration information for the specified AUDIO SPORT peripheral
49 * @note AUDIO SPORT has two clock sources, one is 98.304MHz, the other is 45.1584MHz.
50 * BIT_CTRL_CTLX_I2S_CLK_SRC can used to select the clock source.
51 * @retval None
52 */
AUDIO_SP_Init(AUDIO_SPORT_TypeDef * SPORTx,SP_InitTypeDef * SP_InitStruct)53 void AUDIO_SP_Init(AUDIO_SPORT_TypeDef* SPORTx, SP_InitTypeDef* SP_InitStruct)
54 {
55 u32 Tmp;
56
57 /* Check the parameters */
58 assert_param(IS_SP_WORD_LEN(SP_InitStruct->SP_WordLen));
59 assert_param(IS_SP_DATA_FMT(SP_InitStruct->SP_DataFormat));
60 assert_param(IS_SP_CHN_NUM(SP_InitStruct->SP_MonoStereo));
61 assert_param(IS_SP_SEL_RX_CH(SP_InitStruct->SP_SelRxCh));
62
63 /* Reset SPORT module */
64 SPORTx->SP_CTRLR0 |= SP_CTRLR0_RST;
65 SPORTx->SP_CTRLR0 &= ~ SP_CTRLR0_RST;
66
67 /* Configure parameters: BCLK = 16*16K */
68 SPORTx->SP_CLK_DIV = 0x271 | (0x10 << 16) | SP_CLK_MI_NI_UPDATE;
69
70 /* Configure parameters: disable RX, disable TX, AUDIO SPORT mode */
71 AUDIO_SP_TxStart(SPORTx, DISABLE);
72 AUDIO_SP_RxStart(SPORTx, DISABLE);
73
74 /* Configure parameters: data format, word length, channel number, etc */
75 Tmp = SPORTx->SP_CTRLR0;
76 Tmp &= ~(SP_CTRLR0_DATA_LEN_SEL |SP_CTRLR0_DATA_FORMAT_SEL | SP_CTRLR0_EN_I2S_MONO | SP_CTRLR0_SEL_I2S_RX_CH);
77 Tmp |= ((SP_InitStruct->SP_WordLen << 12) |
78 (SP_InitStruct->SP_DataFormat << 8) |
79 (SP_InitStruct->SP_MonoStereo << 11) |
80 (SP_InitStruct->SP_SelRxCh << 28));
81 SPORTx->SP_CTRLR0 = Tmp;
82 }
83
84 /**
85 * @brief Start or stop SPORT Tx.
86 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
87 * @param NewState: new state of the SPORT Tx.
88 * This parameter can be: ENABLE or DISABLE.
89 * @retval None
90 */
AUDIO_SP_TxStart(AUDIO_SPORT_TypeDef * SPORTx,u32 NewState)91 void AUDIO_SP_TxStart(AUDIO_SPORT_TypeDef* SPORTx, u32 NewState)
92 {
93 if (NewState == ENABLE) {
94 SPORTx->SP_CTRLR0 &= ~ SP_CTRLR0_TX_DISABLE;
95 SPORTx->SP_CTRLR0 |= SP_CTRLR0_START_TX;
96 } else {
97 SPORTx->SP_CTRLR0 |= SP_CTRLR0_TX_DISABLE;
98 SPORTx->SP_CTRLR0 &= ~ SP_CTRLR0_START_TX;
99 }
100 }
101
102 /**
103 * @brief Start or stop SPORT Rx.
104 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
105 * @param NewState: new state of the SPORT Rx.
106 * This parameter can be: ENABLE or DISABLE.
107 * @retval None
108 */
AUDIO_SP_RxStart(AUDIO_SPORT_TypeDef * SPORTx,u32 NewState)109 void AUDIO_SP_RxStart(AUDIO_SPORT_TypeDef* SPORTx, u32 NewState)
110 {
111 if (NewState == ENABLE) {
112 SPORTx->SP_CTRLR0 &= ~ SP_CTRLR0_RX_DISABLE;
113 SPORTx->SP_CTRLR0 |= SP_CTRLR0_START_RX;
114 } else {
115 SPORTx->SP_CTRLR0 |= SP_CTRLR0_RX_DISABLE;
116 SPORTx->SP_CTRLR0 &= ~ SP_CTRLR0_START_RX;
117 }
118 }
119
120 /**
121 * @brief SPORT Tx DMA request on or off.
122 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
123 * @param NewState: new state of the SPORT Tx DMA request.
124 * This parameter can be: ENABLE or DISABLE.
125 * @note If Tx DMA request is not enable, then should start Tx when GDMA complete every time.
126 * @retval None
127 */
AUDIO_SP_TdmaCmd(AUDIO_SPORT_TypeDef * SPORTx,u32 NewState)128 void AUDIO_SP_TdmaCmd(AUDIO_SPORT_TypeDef* SPORTx, u32 NewState)
129 {
130 if (NewState == ENABLE) {
131 SPORTx->SP_CTRLR1 |= SP_CTRLR1_TDMA_REQ;
132 SPORTx->SP_DSP_INT_CR &= ~ SP_TX_DMA_SINGLE_NO_REQ;
133 } else {
134 SPORTx->SP_CTRLR1 &= ~ SP_CTRLR1_TDMA_REQ;
135 SPORTx->SP_DSP_INT_CR |= SP_TX_DMA_SINGLE_NO_REQ;
136 }
137 }
138
139 /**
140 * @brief SPORT Rx DMA request on or off.
141 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
142 * @param NewState: new state of the SPORT Rx DMA request.
143 * This parameter can be: ENABLE or DISABLE.
144 * @note If Rx DMA request is not enable, then should start Rx when GDMA complete every time.
145 * @retval None
146 */
AUDIO_SP_RdmaCmd(AUDIO_SPORT_TypeDef * SPORTx,u32 NewState)147 void AUDIO_SP_RdmaCmd(AUDIO_SPORT_TypeDef* SPORTx, u32 NewState)
148 {
149 if (NewState == ENABLE) {
150 SPORTx->SP_CTRLR1 |= SP_CTRLR1_RDMA_REQ;
151 SPORTx->SP_DSP_INT_CR &= ~ SP_RX_DMA_SINGLE_NO_REQ;
152 } else {
153 SPORTx->SP_CTRLR1 &= ~ SP_CTRLR1_RDMA_REQ;
154 SPORTx->SP_DSP_INT_CR |= SP_RX_DMA_SINGLE_NO_REQ;
155 }
156 }
157
158 /**
159 * @brief Set the AUDIO SPORT word length.
160 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
161 * @param SP_WordLen: the value of word length.
162 * This parameter can be one of the following values:
163 * @arg SP_WL_16: sample bit is 16 bit
164 * @arg SP_WL_24: sample bit is 24 bit
165 * @arg SP_WL_8: sample bit is 8 bit
166 * @retval None
167 */
AUDIO_SP_SetWordLen(AUDIO_SPORT_TypeDef * SPORTx,u32 SP_WordLen)168 void AUDIO_SP_SetWordLen(AUDIO_SPORT_TypeDef* SPORTx, u32 SP_WordLen)
169 {
170 u32 reg_value;
171 assert_param(IS_SP_WORD_LEN(SP_WordLen));
172
173 reg_value = SPORTx->SP_CTRLR0;
174 reg_value &= ~(SP_CTRLR0_DATA_LEN_SEL);
175 reg_value |= (SP_WordLen << 12);
176 SPORTx->SP_CTRLR0 = reg_value;
177 }
178
179 /**
180 * @brief Get AUDIO SPORT word length.
181 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
182 * @retval the value of word length.
183 * @arg 0: sample bit is 16 bit
184 * @arg 2: sample bit is 24 bit
185 * @arg 3: sample bit is 8 bit
186 */
187
AUDIO_SP_GetWordLen(AUDIO_SPORT_TypeDef * SPORTx)188 u32 AUDIO_SP_GetWordLen(AUDIO_SPORT_TypeDef* SPORTx)
189 {
190 u32 len = ((SPORTx->SP_CTRLR0) & SP_CTRLR0_DATA_LEN_SEL) >> 12;
191 return len;
192 }
193
194 /**
195 * @brief Set the AUDIO SPORT channel number.
196 * @param SPORTx: pointer to the base addr of AUDIO SPORT peripheral.
197 * @param SP_MonoStereo: mono or stereo.
198 * This parameter can be one of the following values:
199 * @arg SP_CH_STEREO: stereo channel, channel number is 2
200 * @arg SP_CH_MONO: mono channel, channel number is 1
201 * @retval None
202 */
AUDIO_SP_SetMonoStereo(AUDIO_SPORT_TypeDef * SPORTx,u32 SP_MonoStereo)203 void AUDIO_SP_SetMonoStereo(AUDIO_SPORT_TypeDef* SPORTx, u32 SP_MonoStereo)
204 {
205 u32 reg_value;
206 assert_param(IS_SP_CHN_NUM(SP_MonoStereo));
207
208 reg_value = SPORTx->SP_CTRLR0;
209 reg_value &= ~(SP_CTRLR0_EN_I2S_MONO);
210 reg_value |= (SP_MonoStereo << 11);
211 SPORTx->SP_CTRLR0 = reg_value;
212 }
213
214 /**
215 * @brief Initialize GDMA peripheral for sending data.
216 * @param Index: 0.
217 * @param GDMA_InitStruct: pointer to a GDMA_InitTypeDef structure that contains
218 * the configuration information for the GDMA peripheral.
219 * @param CallbackData: GDMA callback data.
220 * @param CallbackFunc: GDMA callback function.
221 * @param pTxData: Tx Buffer.
222 * @param Length: Tx Count.
223 * @retval TRUE/FLASE
224 */
AUDIO_SP_TXGDMA_Init(u32 Index,GDMA_InitTypeDef * GDMA_InitStruct,void * CallbackData,IRQ_FUN CallbackFunc,u8 * pTxData,u32 Length)225 BOOL AUDIO_SP_TXGDMA_Init(
226 u32 Index,
227 GDMA_InitTypeDef *GDMA_InitStruct,
228 void *CallbackData,
229 IRQ_FUN CallbackFunc,
230 u8 *pTxData,
231 u32 Length
232 )
233 {
234 u8 GdmaChnl;
235 AUDIO_SPORT_TypeDef *SPORTx = AUDIO_DEV_TABLE[Index].SPORTx;
236 u32 WordLen = AUDIO_SP_GetWordLen(SPORTx);
237
238 assert_param(GDMA_InitStruct != NULL);
239 /*obtain a DMA channel and register DMA interrupt handler*/
240 GdmaChnl = GDMA_ChnlAlloc(0, CallbackFunc, (u32)CallbackData, 12);
241 if (GdmaChnl == 0xFF) {
242 // No Available DMA channel
243 return _FALSE;
244 }
245
246 _memset((void *)GDMA_InitStruct, 0, sizeof(GDMA_InitTypeDef));
247
248 /*set GDMA initial structure member value*/
249 GDMA_InitStruct->MuliBlockCunt = 0;
250 GDMA_InitStruct->GDMA_ReloadSrc = 0;
251 GDMA_InitStruct->MaxMuliBlock = 1;
252 GDMA_InitStruct->GDMA_DIR = TTFCMemToPeri;
253 GDMA_InitStruct->GDMA_DstHandshakeInterface = AUDIO_DEV_TABLE[Index].Tx_HandshakeInterface;
254 GDMA_InitStruct->GDMA_DstAddr = (u32)&AUDIO_DEV_TABLE[Index].SPORTx->SP_TX_DR;
255 GDMA_InitStruct->GDMA_Index = 0;
256 GDMA_InitStruct->GDMA_ChNum = GdmaChnl;
257 GDMA_InitStruct->GDMA_IsrType = (BlockType|TransferType|ErrType);
258 GDMA_InitStruct->GDMA_DstInc = NoChange;
259 GDMA_InitStruct->GDMA_SrcInc = IncType;
260
261 /* Cofigure GDMA transfer */
262 if (WordLen == SP_WL_8) {
263 /* 8bits mode */
264 if (((Length & 0x03)==0) && (((u32)(pTxData) & 0x03)==0)) {
265 /* 4-bytes aligned, move 4 bytes each transfer */
266 GDMA_InitStruct->GDMA_SrcMsize = MsizeOne;
267 GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthFourBytes;
268 GDMA_InitStruct->GDMA_BlockSize = Length >> 2;
269 } else {
270 GDMA_InitStruct->GDMA_SrcMsize = MsizeFour;
271 GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthOneByte;
272 GDMA_InitStruct->GDMA_BlockSize = Length;
273 }
274 GDMA_InitStruct->GDMA_DstMsize = MsizeFour;
275 GDMA_InitStruct->GDMA_DstDataWidth = TrWidthOneByte;
276 } else {
277 /* 24bits or 16bits mode */
278 if (((Length & 0x03)==0) && (((u32)(pTxData) & 0x03)==0)) {
279 /* 4-bytes aligned, move 4 bytes each transfer */
280 GDMA_InitStruct->GDMA_SrcMsize = MsizeFour;
281 GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthFourBytes;
282 GDMA_InitStruct->GDMA_BlockSize = Length >> 2;
283 } else if (((Length & 0x01)==0) && (((u32)(pTxData) & 0x01)==0)) {
284 /* 2-bytes aligned, move 2 bytes each transfer */
285 GDMA_InitStruct->GDMA_SrcMsize = MsizeEight;
286 GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthTwoBytes;
287 GDMA_InitStruct->GDMA_BlockSize = Length >> 1;
288 } else {
289 DBG_8195A("AUDIO_SP_TXGDMA_Init: Aligment Err: pTxData=0x%x, Length=%d\n", pTxData, Length);
290 return _FALSE;
291 }
292 GDMA_InitStruct->GDMA_DstMsize = MsizeFour;
293 GDMA_InitStruct->GDMA_DstDataWidth = TrWidthFourBytes;
294 }
295
296 /*check GDMA block size*/
297 assert_param(GDMA_InitStruct->GDMA_BlockSize <= 4096);
298
299 /*configure GDMA source address */
300 GDMA_InitStruct->GDMA_SrcAddr = (u32)pTxData;
301
302 /* Enable GDMA for TX */
303 GDMA_Init(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, GDMA_InitStruct);
304 DCache_CleanInvalidate((u32)pTxData, Length);
305 GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, ENABLE);
306
307 return _TRUE;
308 }
309
310 /**
311 * @brief Initialize GDMA peripheral for receiving data.
312 * @param Index: 0.
313 * @param GDMA_InitStruct: pointer to a GDMA_InitTypeDef structure that contains
314 * the configuration information for the GDMA peripheral.
315 * @param CallbackData: GDMA callback data.
316 * @param CallbackFunc: GDMA callback function.
317 * @param pRxData: Rx Buffer.
318 * @param Length: Rx Count.
319 * @retval TRUE/FLASE
320 */
AUDIO_SP_RXGDMA_Init(u32 Index,GDMA_InitTypeDef * GDMA_InitStruct,void * CallbackData,IRQ_FUN CallbackFunc,u8 * pRxData,u32 Length)321 BOOL AUDIO_SP_RXGDMA_Init(
322 u32 Index,
323 GDMA_InitTypeDef *GDMA_InitStruct,
324 void *CallbackData,
325 IRQ_FUN CallbackFunc,
326 u8 *pRxData,
327 u32 Length
328 )
329 {
330 u8 GdmaChnl;
331 AUDIO_SPORT_TypeDef *SPORTx = AUDIO_DEV_TABLE[Index].SPORTx;
332 u32 WordLen = AUDIO_SP_GetWordLen(SPORTx);
333
334 assert_param(GDMA_InitStruct != NULL);
335 /*obtain a DMA channel and register DMA interrupt handler*/
336 GdmaChnl = GDMA_ChnlAlloc(0, CallbackFunc, (u32)CallbackData, 12);
337 if (GdmaChnl == 0xFF) {
338 // No Available DMA channel
339 return _FALSE;
340 }
341
342 _memset((void *)GDMA_InitStruct, 0, sizeof(GDMA_InitTypeDef));
343
344 /*set GDMA initial structure member value*/
345 GDMA_InitStruct->MuliBlockCunt = 0;
346 GDMA_InitStruct->GDMA_ReloadSrc = 0;
347 GDMA_InitStruct->MaxMuliBlock = 1;
348 GDMA_InitStruct->GDMA_DIR = TTFCPeriToMem;
349 GDMA_InitStruct->GDMA_SrcHandshakeInterface = AUDIO_DEV_TABLE[Index].Rx_HandshakeInterface;
350 GDMA_InitStruct->GDMA_SrcAddr = (u32)&AUDIO_DEV_TABLE[Index].SPORTx->SP_RX_DR;
351 GDMA_InitStruct->GDMA_Index = 0;
352 GDMA_InitStruct->GDMA_ChNum = GdmaChnl;
353 GDMA_InitStruct->GDMA_IsrType = (BlockType|TransferType|ErrType);
354 GDMA_InitStruct->GDMA_DstInc = IncType;
355 GDMA_InitStruct->GDMA_SrcInc = NoChange;
356
357 /* Cofigure GDMA transfer */
358 if (WordLen == SP_WL_8) {
359 GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthOneByte;
360 GDMA_InitStruct->GDMA_SrcMsize = MsizeFour;
361
362 GDMA_InitStruct->GDMA_DstMsize = MsizeOne;
363 GDMA_InitStruct->GDMA_DstDataWidth = TrWidthFourBytes;
364 GDMA_InitStruct->GDMA_BlockSize = Length;
365 } else {
366 GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthFourBytes;
367 GDMA_InitStruct->GDMA_SrcMsize = MsizeEight;
368
369 GDMA_InitStruct->GDMA_DstMsize = MsizeEight;
370 GDMA_InitStruct->GDMA_DstDataWidth = TrWidthFourBytes;
371 GDMA_InitStruct->GDMA_BlockSize = Length >> 2;
372 }
373
374 /*check GDMA block size*/
375 assert_param(GDMA_InitStruct->GDMA_BlockSize <= 4096);
376
377 /*configure GDMA destination address */
378 GDMA_InitStruct->GDMA_DstAddr = (u32)pRxData;
379
380 /* Enable GDMA for RX */
381 GDMA_Init(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, GDMA_InitStruct);
382 DCache_CleanInvalidate((u32)pRxData, Length);
383 GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, ENABLE);
384
385 return _TRUE;
386 }
387
388 /**
389 * @brief Audio GDMA Tx restart in isr
390 * @param GDMA_Index: GDMA index used in this routine.
391 * @param GDMA_ChNum: GDMA channel number used in this routine.
392 * @param tx_addr: Address of data to be sent.
393 * @param tx_length: Length of data to be sent.
394 * @retval TRUE
395 */
AUDIO_SP_TXGDMA_Restart(u8 GDMA_Index,u8 GDMA_ChNum,u32 tx_addr,u32 tx_length)396 BOOL AUDIO_SP_TXGDMA_Restart(
397 u8 GDMA_Index,
398 u8 GDMA_ChNum,
399 u32 tx_addr,
400 u32 tx_length
401 )
402 {
403 GDMA_SetSrcAddr(GDMA_Index, GDMA_ChNum, tx_addr);
404 GDMA_SetBlkSize(GDMA_Index, GDMA_ChNum, tx_length>>2);
405 DCache_CleanInvalidate(tx_addr, tx_length);
406 GDMA_Cmd(GDMA_Index, GDMA_ChNum, ENABLE);
407
408 return _TRUE;
409 }
410
411 /**
412 * @brief Audio GDMA Rx restart in isr
413 * @param GDMA_Index: GDMA index used in this routine.
414 * @param GDMA_ChNum: GDMA channel number used in this routine.
415 * @param tx_addr: Address of data to be received.
416 * @param tx_length: Length of data to be received.
417 * @retval TRUE
418 */
AUDIO_SP_RXGDMA_Restart(u8 GDMA_Index,u8 GDMA_ChNum,u32 rx_addr,u32 rx_length)419 BOOL AUDIO_SP_RXGDMA_Restart(
420 u8 GDMA_Index,
421 u8 GDMA_ChNum,
422 u32 rx_addr,
423 u32 rx_length
424 )
425 {
426 GDMA_SetDstAddr(GDMA_Index, GDMA_ChNum, rx_addr);
427 GDMA_SetBlkSize(GDMA_Index, GDMA_ChNum, rx_length>>2);
428 DCache_CleanInvalidate(rx_addr, rx_length);
429 GDMA_Cmd(GDMA_Index, GDMA_ChNum, ENABLE);
430
431 return _TRUE;
432 }
433 /******************* (C) COPYRIGHT 2017 Realtek Semiconductor *****END OF FILE****/
434