1 
2 #include <platform_stdlib.h>
3 #include <math.h>
4 #include "rl6548.h"
5 #include "audio_internel.h"
6 #include "osdep_service.h"
7 
8 //#define ENABLE_PA
9 
10 static u8 sp_rx_buf[SP_DMA_PAGE_SIZE * SP_DMA_PAGE_NUM]__attribute__((aligned(32)));
11 static u8 sp_tx_buf[SP_DMA_PAGE_SIZE * SP_DMA_PAGE_NUM]__attribute__((aligned(32)));
12 static u8 sp_zero_buf[SP_ZERO_BUF_SIZE]__attribute__((aligned(32)));
13 static u8 sp_full_buf[SP_FULL_BUF_SIZE]__attribute__((aligned(32)));
14 
15 static u8 rx_data_cache[SP_DMA_PAGE_SIZE];
16 static uint32_t rx_data_cache_len = 0;
17 
18 
19 static SP_InitTypeDef SP_InitStruct;
20 static SP_GDMA_STRUCT SPGdmaStruct;
21 static SP_OBJ sp_obj;
22 static SP_RX_INFO sp_rx_info;
23 static SP_TX_INFO sp_tx_info;
24 static int RX_GDMA_flag = 0; //0, start, 1, stop, 2, close
25 static int TX_GDMA_flag = 0;
26 static SP_OBJ sp_obj;
27 static SP_InitTypeDef SP_InitStruct;
28 
29 extern void PLL_Div(u32 div);
30 extern BOOL AUDIO_SP_TXGDMA_Restart(u8 GDMA_Index, u8 GDMA_ChNum, u32 tx_addr, u32 tx_length);
31 extern BOOL AUDIO_SP_RXGDMA_Restart(u8 GDMA_Index, u8 GDMA_ChNum, u32 rx_addr, u32 rx_length);
32 
sp_get_free_tx_page(void)33 static u8 *sp_get_free_tx_page(void)
34 {
35     pTX_BLOCK ptx_block = &(sp_tx_info.tx_block[sp_tx_info.tx_usr_cnt]);
36 
37     if (ptx_block->tx_gdma_own)
38         return NULL;
39     else{
40         return (u8*)ptx_block->tx_addr;
41     }
42 }
43 
sp_write_tx_page(u8 * src,u32 length)44 static void sp_write_tx_page(u8 *src, u32 length)
45 {
46     pTX_BLOCK ptx_block = &(sp_tx_info.tx_block[sp_tx_info.tx_usr_cnt]);
47 
48     memcpy((void*)ptx_block->tx_addr, src, length);
49     ptx_block-> tx_gdma_own = 1;
50     ptx_block -> tx_length = length;
51     sp_tx_info.tx_usr_cnt++;
52     if (sp_tx_info.tx_usr_cnt == SP_DMA_PAGE_NUM){
53         sp_tx_info.tx_usr_cnt = 0;
54     }
55 }
56 
sp_release_tx_page(void)57 static void sp_release_tx_page(void)
58 {
59     pTX_BLOCK ptx_block = &(sp_tx_info.tx_block[sp_tx_info.tx_gdma_cnt]);
60 
61     if (sp_tx_info.tx_empty_flag){
62     }
63     else{
64         ptx_block->tx_gdma_own = 0;
65         sp_tx_info.tx_gdma_cnt++;
66         if (sp_tx_info.tx_gdma_cnt == SP_DMA_PAGE_NUM){
67             sp_tx_info.tx_gdma_cnt = 0;
68         }
69     }
70 }
71 
sp_get_ready_tx_page(void)72 static u8 *sp_get_ready_tx_page(void)
73 {
74     pTX_BLOCK ptx_block = &(sp_tx_info.tx_block[sp_tx_info.tx_gdma_cnt]);
75 
76     if (ptx_block->tx_gdma_own){
77         sp_tx_info.tx_empty_flag = 0;
78         return (u8*)ptx_block->tx_addr;
79     }
80     else{
81         sp_tx_info.tx_empty_flag = 1;
82         return (u8*)sp_tx_info.tx_zero_block.tx_addr;	//for audio buffer empty case
83     }
84 }
85 
sp_get_ready_tx_length(void)86 static u32 sp_get_ready_tx_length(void)
87 {
88     pTX_BLOCK ptx_block = &(sp_tx_info.tx_block[sp_tx_info.tx_gdma_cnt]);
89 
90     if (sp_tx_info.tx_empty_flag){
91         return sp_tx_info.tx_zero_block.tx_length;
92     }
93     else{
94         return ptx_block->tx_length;
95     }
96 }
97 
sp_tx_complete(void * Data)98 static void sp_tx_complete(void *Data)
99 {
100     SP_GDMA_STRUCT *gs = (SP_GDMA_STRUCT *) Data;
101     PGDMA_InitTypeDef GDMA_InitStruct;
102     u32 tx_addr;
103     u32 tx_length;
104 
105     GDMA_InitStruct = &(gs->SpTxGdmaInitStruct);
106 
107     /* Clear Pending ISR */
108     GDMA_ClearINT(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum);
109     sp_release_tx_page();
110     tx_addr = (u32)sp_get_ready_tx_page();
111     tx_length = sp_get_ready_tx_length();
112     if(TX_GDMA_flag == 0) {
113         AUDIO_SP_TXGDMA_Restart(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, tx_addr, tx_length);
114     } else {
115         GDMA_ChnlFree(SPGdmaStruct.SpTxGdmaInitStruct.GDMA_Index, SPGdmaStruct.SpTxGdmaInitStruct.GDMA_ChNum);
116         AUDIO_SP_TdmaCmd(AUDIO_SPORT_DEV, DISABLE);
117         // AUDIO_SP_TxStart(AUDIO_SPORT_DEV, DISABLE);
118 
119         if(TX_GDMA_flag == 2){
120             RCC_PeriphClockCmd(APBPeriph_AUDIOC, APBPeriph_AUDIOC_CLOCK, DISABLE);
121             RCC_PeriphClockCmd(APBPeriph_SPORT, APBPeriph_SPORT_CLOCK, DISABLE);
122             CODEC_DeInit(APP_LINE_OUT);
123             PLL_PCM_Set(DISABLE);
124         }
125     }
126 }
127 
sp_get_ready_rx_page(void)128 static u8 *sp_get_ready_rx_page(void)
129 {
130     pRX_BLOCK prx_block = &(sp_rx_info.rx_block[sp_rx_info.rx_usr_cnt]);
131 
132     if (prx_block->rx_gdma_own)
133         return NULL;
134     else{
135         return (u8 *)prx_block->rx_addr;
136     }
137 }
138 
sp_read_rx_page(u8 * dst,u32 length)139 static void sp_read_rx_page(u8 *dst, u32 length)
140 {
141     pRX_BLOCK prx_block = &(sp_rx_info.rx_block[sp_rx_info.rx_usr_cnt]);
142 
143     memcpy(dst, (u8 *)prx_block->rx_addr, length);
144     prx_block->rx_gdma_own = 1;
145     sp_rx_info.rx_usr_cnt++;
146     if (sp_rx_info.rx_usr_cnt == SP_DMA_PAGE_NUM){
147         sp_rx_info.rx_usr_cnt = 0;
148     }
149 }
150 
151 
sp_release_rx_page(void)152 static void sp_release_rx_page(void)
153 {
154     pRX_BLOCK prx_block = &(sp_rx_info.rx_block[sp_rx_info.rx_gdma_cnt]);
155 
156     if (sp_rx_info.rx_full_flag){
157     }
158     else{
159         prx_block->rx_gdma_own = 0;
160         sp_rx_info.rx_gdma_cnt++;
161         if (sp_rx_info.rx_gdma_cnt == SP_DMA_PAGE_NUM){
162             sp_rx_info.rx_gdma_cnt = 0;
163         }
164     }
165 }
166 
167 
sp_get_free_rx_page(void)168 static u8 *sp_get_free_rx_page(void)
169 {
170     pRX_BLOCK prx_block = &(sp_rx_info.rx_block[sp_rx_info.rx_gdma_cnt]);
171 
172     if (prx_block->rx_gdma_own){
173         sp_rx_info.rx_full_flag = 0;
174         return (u8 *)prx_block->rx_addr;
175     }
176     else{
177         sp_rx_info.rx_full_flag = 1;
178         return (u8 *)sp_rx_info.rx_full_block.rx_addr;	//for audio buffer full case
179     }
180 }
181 
sp_get_free_rx_length(void)182 static u32 sp_get_free_rx_length(void)
183 {
184     pRX_BLOCK prx_block = &(sp_rx_info.rx_block[sp_rx_info.rx_gdma_cnt]);
185 
186     if (sp_rx_info.rx_full_flag){
187         return sp_rx_info.rx_full_block.rx_length;
188     }
189     else{
190         return prx_block->rx_length;
191     }
192 }
193 
sp_init_tx_variables(void)194 static void sp_init_tx_variables(void)
195 {
196     int i;
197 
198     for(i=0; i<SP_ZERO_BUF_SIZE; i++){
199         sp_zero_buf[i] = 0;
200     }
201     sp_tx_info.tx_zero_block.tx_addr = (u32)sp_zero_buf;
202     sp_tx_info.tx_zero_block.tx_length = (u32)SP_ZERO_BUF_SIZE;
203 
204     sp_tx_info.tx_gdma_cnt = 0;
205     sp_tx_info.tx_usr_cnt = 0;
206     sp_tx_info.tx_empty_flag = 0;
207 
208     for(i=0; i<SP_DMA_PAGE_NUM; i++){
209         sp_tx_info.tx_block[i].tx_gdma_own = 0;
210         sp_tx_info.tx_block[i].tx_addr = (u32)sp_tx_buf+i*SP_DMA_PAGE_SIZE;
211         sp_tx_info.tx_block[i].tx_length = SP_DMA_PAGE_SIZE;
212     }
213 }
214 
sp_init_rx_variables(void)215 static void sp_init_rx_variables(void)
216 {
217     int i;
218     sp_rx_info.rx_full_block.rx_addr = (u32)sp_full_buf;
219     sp_rx_info.rx_full_block.rx_length = (u32)SP_FULL_BUF_SIZE;
220 
221     sp_rx_info.rx_gdma_cnt = 0;
222     sp_rx_info.rx_usr_cnt = 0;
223     sp_rx_info.rx_full_flag = 0;
224 
225     for(i=0; i<SP_DMA_PAGE_NUM; i++){
226         sp_rx_info.rx_block[i].rx_gdma_own = 1;
227         sp_rx_info.rx_block[i].rx_addr = (u32)(sp_rx_buf + i*SP_DMA_PAGE_SIZE);
228         sp_rx_info.rx_block[i].rx_length = SP_DMA_PAGE_SIZE;
229     }
230 }
231 
sp_rx_complete(void * data)232 static void sp_rx_complete(void *data)
233 {
234     SP_GDMA_STRUCT *gs = (SP_GDMA_STRUCT *) data;
235     PGDMA_InitTypeDef GDMA_InitStruct;
236     u32 rx_addr;
237     u32 rx_length;
238     char *pbuf;
239 
240     GDMA_InitStruct = &(gs->SpRxGdmaInitStruct);
241     DCache_Invalidate(GDMA_InitStruct->GDMA_DstAddr, GDMA_InitStruct->GDMA_BlockSize<<2);
242     /* Clear Pending ISR */
243     GDMA_ClearINT(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum);
244     sp_release_rx_page();
245     rx_addr = (u32)sp_get_free_rx_page();
246     rx_length = sp_get_free_rx_length();
247 
248     if(RX_GDMA_flag == 0) {
249         AUDIO_SP_RXGDMA_Restart(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, rx_addr, rx_length);
250     } else {
251         GDMA_ChnlFree(SPGdmaStruct.SpRxGdmaInitStruct.GDMA_Index, SPGdmaStruct.SpRxGdmaInitStruct.GDMA_ChNum);
252         AUDIO_SP_RdmaCmd(AUDIO_SPORT_DEV, DISABLE);
253         // AUDIO_SP_RxStart(AUDIO_SPORT_DEV, DISABLE);
254 
255         if(RX_GDMA_flag == 2) {
256             RCC_PeriphClockCmd(APBPeriph_AUDIOC, APBPeriph_AUDIOC_CLOCK, DISABLE);
257             RCC_PeriphClockCmd(APBPeriph_SPORT, APBPeriph_SPORT_CLOCK, DISABLE);
258             CODEC_DeInit(APP_AMIC_IN);
259             PLL_PCM_Set(DISABLE);
260         }
261     }
262 }
263 
sp_init_hal(pSP_OBJ psp_obj)264 static void sp_init_hal(pSP_OBJ psp_obj)
265 {
266     u32 div;
267     PLL_I2S_Set(ENABLE);		//enable 98.304MHz PLL. needed if fs=8k/16k/32k/48k/96k
268     //PLL_PCM_Set(ENABLE);		//enable 45.1584MHz PLL. needed if fs=44.1k/8.2k
269 
270     RCC_PeriphClockCmd(APBPeriph_AUDIOC, APBPeriph_AUDIOC_CLOCK, ENABLE);
271     RCC_PeriphClockCmd(APBPeriph_SPORT, APBPeriph_SPORT_CLOCK, ENABLE);
272 
273     //set clock divider to gen clock sample_rate*256 from 98.304M.
274     switch(psp_obj->sample_rate){
275         case SR_48K:
276             div = 8;
277             break;
278         case SR_96K:
279             div = 4;
280             break;
281         case SR_32K:
282             div = 12;
283             break;
284         case SR_16K:
285             div = 24;
286             break;
287         case SR_8K:
288             div = 48;
289             break;
290         default:
291             DBG_8195A("sample rate not supported!!\n");
292             break;
293     }
294     PLL_Div(div);
295 
296     PAD_CMD(_PA_0, DISABLE);
297     PAD_CMD(_PA_1, DISABLE);
298     PAD_CMD(_PA_2, DISABLE);
299     PAD_CMD(_PA_3, DISABLE);
300     PAD_CMD(_PA_4, DISABLE);
301 
302     PAD_CMD(_PB_28, DISABLE);
303     PAD_CMD(_PB_29, DISABLE);
304     PAD_CMD(_PB_30, DISABLE);
305     PAD_CMD(_PB_31, DISABLE);
306 
307     /*codec init*/
308     CODEC_Init(psp_obj->sample_rate, psp_obj->word_len, psp_obj->mono_stereo, psp_obj->direction);
309 
310 
311 #ifdef ENABLE_PA
312     CODEC_SetAmicBst(0x3, 0x1);  //right loopback
313     CODEC_SetVolume(0x82, 0x82);
314 
315     u32 reg_value = 0;
316     reg_value = AUDIO_SI_ReadReg(0x2);
317     //reg_value &= ~(15<<BIT_MICBST_GSELL);
318     reg_value |= (1<<14);
319     AUDIO_SI_WriteReg(0x2, reg_value);
320 #else
321     CODEC_SetAmicBst(0x3, 0x3);
322     CODEC_SetVolume(0x92, 0x92);
323 #endif
324 }
325 
326 // static
rl6548_capture_start()327 void rl6548_capture_start()
328 {
329     u32 rx_addr;
330     u32 rx_length;
331     RX_GDMA_flag = 0;
332     memset(rx_data_cache, 0x00, SP_DMA_PAGE_SIZE);
333     rx_data_cache_len = 0;
334 
335     sp_init_rx_variables();
336     // AUDIO_SP_Init(AUDIO_SPORT_DEV, &SP_InitStruct);
337     AUDIO_SP_RdmaCmd(AUDIO_SPORT_DEV, ENABLE);
338     AUDIO_SP_RxStart(AUDIO_SPORT_DEV, ENABLE);
339 
340     rx_addr = (u32)sp_get_free_rx_page();
341     rx_length = sp_get_free_rx_length();
342     AUDIO_SP_RXGDMA_Init(0, &SPGdmaStruct.SpRxGdmaInitStruct, &SPGdmaStruct, (IRQ_FUN)sp_rx_complete, (u8 *)rx_addr, rx_length);
343 }
344 
345 // static
rl6548_capture_stop()346 void rl6548_capture_stop()
347 {
348     RX_GDMA_flag = 1;
349 }
350 
351 // static
rl6548_playback_start()352 void rl6548_playback_start()
353 {
354     u32 tx_addr;
355     u32 tx_length;
356 
357     TX_GDMA_flag = 0;
358 
359     sp_init_tx_variables();
360     // AUDIO_SP_Init(AUDIO_SPORT_DEV, &SP_InitStruct);
361     AUDIO_SP_TdmaCmd(AUDIO_SPORT_DEV, ENABLE);
362     AUDIO_SP_TxStart(AUDIO_SPORT_DEV, ENABLE);
363 
364     tx_addr = (u32)sp_get_ready_tx_page();
365     tx_length = sp_get_ready_tx_length();
366     AUDIO_SP_TXGDMA_Init(0, &SPGdmaStruct.SpTxGdmaInitStruct, &SPGdmaStruct, (IRQ_FUN)sp_tx_complete, (u8 *)tx_addr, tx_length);
367 }
368 
369 // static
rl6548_playback_stop()370 void rl6548_playback_stop()
371 {
372     TX_GDMA_flag = 1;
373 }
374 
375 
rl6548_audio_init(int sampleRate,int channels,int wordLen)376 void *rl6548_audio_init(int sampleRate, int channels, int wordLen)
377 {
378     // printf("enter rl6548_audio_init\n");
379     pSP_OBJ psp_obj = &sp_obj;
380 
381     if(channels == 1)
382         psp_obj->mono_stereo= CH_MONO;
383     else if(channels == 2)
384         psp_obj->mono_stereo= CH_STEREO;
385 
386     psp_obj->word_len = wordLen;
387 
388     switch(sampleRate) {
389         case 48000:
390             psp_obj->sample_rate = SR_48K;
391             break;
392         case 96000:
393             psp_obj->sample_rate = SR_96K;
394             break;
395         case 32000:
396             psp_obj->sample_rate = SR_32K;
397             break;
398         case 16000:
399             psp_obj->sample_rate = SR_16K;
400             break;
401         case 8000:
402             psp_obj->sample_rate = SR_8K;
403             break;
404         case 44100:
405             psp_obj->sample_rate = SR_44P1K;
406             break;
407         case 88200:
408             psp_obj->sample_rate = SR_88P2K;
409             break;
410         default:
411             printf("not support sr %d\n", sampleRate);
412     }
413 
414     psp_obj->direction = APP_AMIC_IN | APP_LINE_OUT; //default
415 
416     sp_init_hal(psp_obj);
417     sp_init_rx_variables();
418     sp_init_tx_variables();
419 
420     /*configure Sport according to the parameters*/
421     AUDIO_SP_StructInit(&SP_InitStruct);
422     SP_InitStruct.SP_MonoStereo= psp_obj->mono_stereo;
423     SP_InitStruct.SP_WordLen = psp_obj->word_len;
424 
425     AUDIO_SP_Init(AUDIO_SPORT_DEV, &SP_InitStruct);
426     return psp_obj;
427 }
428 
429 
rl6548_audio_deinit()430 void rl6548_audio_deinit()
431 {
432     // printf("enter rl6548_audio_deinit\n");
433     RCC_PeriphClockCmd(APBPeriph_AUDIOC, APBPeriph_AUDIOC_CLOCK, DISABLE);
434     RCC_PeriphClockCmd(APBPeriph_SPORT, APBPeriph_SPORT_CLOCK, DISABLE);
435     CODEC_DeInit(APP_AMIC_IN | APP_LINE_OUT);
436     PLL_PCM_Set(DISABLE);
437 }
438 
439 
rl6548_audio_write(void * h,uint8_t * buf,uint32_t size)440 int rl6548_audio_write(void *h, uint8_t *buf, uint32_t size)
441 {
442     uint32_t offset = 0;
443     uint32_t tx_len;
444 
445     while(size) {
446         if (sp_get_free_tx_page()){
447             tx_len = (size >= SP_DMA_PAGE_SIZE) ? SP_DMA_PAGE_SIZE : size;
448             sp_write_tx_page((buf+offset), tx_len);
449             offset += tx_len;
450             size -= tx_len;
451         } else {
452             // rtw_msleep_os(1);
453             aos_msleep(1);
454         }
455     }
456 }
457 
458 
rl6548_data_read(void * handle,void * buf,unsigned int size)459 int rl6548_data_read(void *handle, void *buf, unsigned int size)
460 {
461     int sz = size;
462     char *dst = (char*)buf;
463 
464     if(sz >= rx_data_cache_len && rx_data_cache_len > 0) {
465         memcpy(dst, rx_data_cache, rx_data_cache_len);
466         sz -= rx_data_cache_len;
467         dst += rx_data_cache_len;
468         rx_data_cache_len = 0;
469     } else if(sz < rx_data_cache_len) {
470         memcpy(dst, rx_data_cache, sz);
471         rx_data_cache_len -= sz;
472         memmove(rx_data_cache, rx_data_cache + sz, rx_data_cache_len);
473         sz = 0;
474     }
475 
476     while(sz > 0) {
477         if (sp_get_ready_rx_page()) {
478             sp_read_rx_page((u8 *)rx_data_cache, SP_DMA_PAGE_SIZE);
479             rx_data_cache_len = SP_DMA_PAGE_SIZE;
480             if(sz >= rx_data_cache_len) {
481                 memcpy(dst, rx_data_cache, rx_data_cache_len);
482                 sz -= rx_data_cache_len;
483                 dst += rx_data_cache_len;
484                 rx_data_cache_len = 0;
485             } else {
486                 memcpy(dst, rx_data_cache, sz);
487                 rx_data_cache_len -= sz;
488                 memmove(rx_data_cache, rx_data_cache + sz, rx_data_cache_len);
489                 sz = 0;
490             }
491         } else {
492             // rtw_msleep_os(1);
493             aos_msleep(1);
494         }
495     }
496     return size - sz;
497 }
498 
499 
rl6548_volume_set(int index)500 void rl6548_volume_set(int index)
501 {
502     int vol = (int)(VOLUME_MAX / 100.0 * index) ;
503     SET_VOLUME(vol, vol);
504     // printf("Volume Set, index %d, value %d\r\n", index, vol);
505 }
506 
507 
rl6548_volume_get()508 int rl6548_volume_get()
509 {
510     int vol = 0;
511     int volume_index = 0;
512     u16 volume_16 = 0;
513 
514     GET_VOLUME(&volume_16);
515     // printf("Volume Register Data %x", volume_16);
516 
517     vol = volume_16 & 0x00FF;
518     volume_index = round(vol * 100.0 / VOLUME_MAX);
519     return volume_index;
520 }
521 
522 
rl6548_set_mute(int mute)523 void rl6548_set_mute(int mute)
524 {
525     if(mute)
526         rl6548_volume_set(0);
527 }
528 
529 
rl6548_get_mute()530 int rl6548_get_mute()
531 {
532     return rl6548_volume_get() == 0;
533 }
534