📄 ac97.c
字号:
#ifndef DEBUG_AC97
#define DEBUG_AC97
#endif
#include "stdio.h"
#include "stdlib.h"
#include "XsAc97CtrlApi.h"
#include "XsAc97Ctrl.h"
#include "dma.h"
#include "pcm.h"
#include "CS4201.h"
#include "UtilFunc.h"
#include "XsUartDrv.h"
#define PCM_OUT 0
#define PCM_IN 1
static UINT32 channel = 3;
static UINT32 channelin = 4;
void StopDMAALL(void);
extern unsigned char ppcm[]; // PCM data
void * Make16BytesAlign(void * ptr)
{
unsigned p = (UINT32)ptr;
void *ptr2;
if (p & 0x0F)
ptr2 = (void *)((p & 0xFFFFFFF0) + 16);
else
ptr2 = (void *)(p & 0xFFFFFFF0);
return ptr2;
}
#ifndef DEBUG_AC97
#define LENGTH_OF_TRANS 0x00001000
#define PCMLength 470016
#define n8k 115 //(PCMLength/LENGTH_OF_TRANS)
XsDmaDescriptorGroupT PCMDesGrp[n8k+1];
#else
#define LENGTH_OF_TRANS 0x00001000
#define PCMLength 0x2000
#define n8k 2
char DesArea[256]; //leave space for DMA descriptor
char DesAreain[256]; //leave space for DMA descriptor
XsDmaDescriptorGroupT *PCMDesGrp;
#endif
XsDmaDescriptorGroupT * initdesc(INT32 dir)
{
#ifndef DEBUG_AC97
INT32 i;
XsDmaDescriptorGroupT * pdesc;
unsigned char * ppcmout = (unsigned char *)Make16BytesAlign(ppcm); // 16 byte align
print_string("In initdesc\r\n");
pdesc = (XsDmaDescriptorGroupT *)Make16BytesAlign(&PCMDesGrp);
for (i=0; i<n8k; i++)
{
pdesc->DDADR = (UINT32)(pdesc + 1);
pdesc->DSADR = (UINT32)ppcmout;
pdesc->DTADR = (UINT32)&(XsAc97CtrlRegsP->PCDR); // audio transmit FIFO (0x40500040)
// [31] increment Src Addr
// [28] FLOWTRG
// [17:16] 11b - 32 bytes Maxim Burst Size of each transfer
// [15:14] 11b - Word Width
// [12,0] Length of transfer in bytes
pdesc->DCMD = 0x9003C000 | LENGTH_OF_TRANS;
pdesc ++;
ppcmout += LENGTH_OF_TRANS; // skip 8k bytes
}
pdesc --;
pdesc->DDADR = (UINT32)pdesc;
print_string("Dumping descriptor in initdesc\r\n");
Dump_Bin((unsigned)pdesc,n8k*4);
return (XsDmaDescriptorGroupT *)Make16BytesAlign(&PCMDesGrp);
#else
INT32 i,j;
XsDmaDescriptorGroupT * pdesc;
unsigned short * ppcmout = (unsigned short *)Make16BytesAlign(ppcm); // 16 byte align
/* for (i=0,j=0;i<0x2000/sizeof(unsigned short);i++,j=(j+10)%1000)
{
ppcmout[i] = SampleTable[j]; //16K 480KHz sine data
}
*/
if(dir==PCM_OUT)
{
PCMDesGrp = (XsDmaDescriptorGroupT *)Make16BytesAlign(DesArea);
pdesc = PCMDesGrp;
for (i=0; i<n8k; i++)
{
pdesc->DDADR = (UINT32)(pdesc);
pdesc->DSADR = (UINT32)ppcmout;
pdesc->DTADR = (UINT32)&(XsAc97CtrlRegsP->PCDR); // audio transmit FIFO (0x40500040)
// [31] increment Src Addr
// [28] FLOWTRG
// [17:16] 11b - 32 bytes Maxim Burst Size of each transfer
// [15:14] 11b - Word Width
// [12,0] Length of transfer in bytes
pdesc->DCMD = 0x9003C000 | LENGTH_OF_TRANS;
pdesc++;
ppcmout += LENGTH_OF_TRANS/sizeof(unsigned short); // skip 8k bytes
}
pdesc--;
pdesc->DDADR = (UINT32)PCMDesGrp;
}
else
{
PCMDesGrp = (XsDmaDescriptorGroupT *)Make16BytesAlign(DesAreain);
pdesc = PCMDesGrp;
for (i=0; i<n8k; i++)
{
pdesc->DDADR = (UINT32)(pdesc);
pdesc->DSADR = (UINT32)&(XsAc97CtrlRegsP->PCDR);
pdesc->DTADR = (UINT32)ppcmout; // audio transmit FIFO (0x40500040)
// [31] increment Src Addr
// [28] FLOWTRG
// [17:16] 11b - 32 bytes Maxim Burst Size of each transfer
// [15:14] 11b - Word Width
// [12,0] Length of transfer in bytes
pdesc->DCMD = 0x6003C000 | LENGTH_OF_TRANS;
pdesc++;
ppcmout += LENGTH_OF_TRANS/sizeof(unsigned short); // skip 8k bytes
}
pdesc--;
pdesc->DDADR = (UINT32)PCMDesGrp;
}
return PCMDesGrp;
#endif
}
void startdma(UINT32 channel)
{
XsDmaControlRegsP->DCSR[channel] |= 0x80000000; // RUN = 1
}
void stopdma(UINT32 channel)
{
XsDmaControlRegsP->DCSR[channel] &= ~0x80000000; // RUN = 0
}
//Mic In Loopback
UINT32 initac97audiocodec_micinloopback()
{
UINT32 status;
// disable loopback mode
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_GPR, 0);
if (status) return status;
// SL[10:8] 000=Mic In L; SR[2:0] 000=Mic In R
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_RSR, UCB_RSR_SR_MIC | UCB_RSR_SL_MIC);
if (status) return status;
//set record gain
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_RGR, 0x0707);
if (status) return status;
//enable Variable Rate Audio mode
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_EASCR, UCB_EAIDR_VRA);
if (status) return status;
//48 kHz
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_ADR, UCB_DR_48000);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_AAR, UCB_DR_48000);
if (status) return status;
//set volume: bit13~8 - ML; bit5~0 - MR
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MVR, 0x303);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_HVR, 0x303);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MNVR, 0x303);
if (status) return status;
//Mute PCM out
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_POUTVR, 0x8303);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MICVR, 0x003 | MICVR_20DB);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MCCR, MCCR_10DB);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_ACMCR, ACMCR_DDM);
if (status) return status;
// enable loopback mode
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_GPR, GPR_LPBK);
if (status) return status;
return status;
}
void MicInLoopback(void)
{
UINT32 DDADR, DSADR, DTADR, DCMD, tmp;
XsDmaDescriptorGroupT * pdesc;
StopDMAALL();
PrintfUartDef("Mic In Loopback!\r\n");
PrintfUartDef(" To init AC97 codec\r\n");
initac97audiocodec_micinloopback();
return;
while (1);
// The below code is for debug
restart:
XsAc97CtrlRegsP->POSR |= 0x00000010;
tmp = XsDmaControlRegsP->DCSR[channel];
tmp = XsDmaControlRegsP->DCSR[channel] & 0x08;
if (tmp)
{
startdma(channel);
while (XsDmaControlRegsP->DCSR[channel] & 0x08)
{
DDADR = XsDmaControlRegsP->DDG[channel].DDADR;
DSADR = XsDmaControlRegsP->DDG[channel].DSADR;
DTADR = XsDmaControlRegsP->DDG[channel].DTADR;
DCMD = XsDmaControlRegsP->DDG[channel].DCMD;
PrintfUartDef("dma not run\n\t[DDADR]0x%x\n\t[DSADR]0x%x\n\t[DTADR]0x%x\n\t[DCMD]0x%x\n", DDADR, DSADR, DTADR, DCMD);
}
}
Util_DelayUs(1);
if (XsDmaControlRegsP->DCSR[channel] & 0x08)
{
DDADR = XsDmaControlRegsP->DDG[channel].DDADR;
PrintfUartDef("dma stops: [DDADR]0x%x\n", DDADR);
}
if (XsAc97CtrlRegsP->POSR & 0x00000010)
{
//XsDmaControlRegsP->DCSR[channel] &= 0x7FFFFFFF; // RUN = 0
//while (!(XsDmaControlRegsP->DCSR[channel] & 0x08)) DM_WaitUs(1);
DDADR = XsDmaControlRegsP->DDG[channel].DDADR;
DSADR = XsDmaControlRegsP->DDG[channel].DSADR;
DTADR = XsDmaControlRegsP->DDG[channel].DTADR;
DCMD = XsDmaControlRegsP->DDG[channel].DCMD;
tmp = XsDmaControlRegsP->DCSR[channel];
PrintfUartDef("fifo error:\n\t[DDADR]0x%x\n\t[DSADR]0x%x\n\t[DTADR]0x%x\n\t[DCMD]0x%x\n", DDADR, DSADR, DTADR, DCMD);
}
goto restart;
}
//Mic In DMA Loopback
UINT32 initac97audiocodec_micindmaloopback()
{
UINT32 status;
// disable loopback mode
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_GPR, 0);
if (status) return status;
// SL[10:8] 000=Mic In L; SR[2:0] 000=Mic In R
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_RSR, 0);
if (status) return status;
//set record gain
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_RGR, 0x0707);
if (status) return status;
//enable Variable Rate Audio mode
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_EASCR, UCB_EAIDR_VRA);
if (status) return status;
//48 kHz
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_ADR, UCB_DR_48000);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_AAR, UCB_DR_48000);
if (status) return status;
//set volume: bit13~8 - ML; bit5~0 - MR
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MVR, 0x303);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_HVR, 0x303);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MNVR, 0x303);
if (status) return status;
//Mute PCM out
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_POUTVR, 0x8303);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MICVR, 0x003 | MICVR_20DB);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_GPR, 0x0000);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_MCCR, MCCR_10DB);
if (status) return status;
status = XsAc97CtrlWriteCodecReg(XS_AC97CTRL_CM_ID_PRI_CODEC,
UCB_ACMCR, ACMCR_DDM);
if (status) return status;
// enable loopback mode
return status;
}
void MicInDMALoopback(void)
{
UINT32 DDADR, DSADR, DTADR, DCMD, tmp;
XsDmaDescriptorGroupT * pdesc;
XsDmaDescriptorGroupT * pdescin;
StopDMAALL();
PrintfUartDef("Mic In DMA Loopback!\r\n");
pdesc = initdesc(PCM_OUT);
if (!pdesc)
return;
pdescin = initdesc(PCM_IN);
if (!pdescin)
return;
PrintfUartDef(" To init AC97 codec\r\n");
initac97audiocodec_micindmaloopback();
PrintfUartDef(" To init AC97 dma\r\n");
//Waiting for current DMA End
tmp = XsDmaControlRegsP->DCSR[channel];
XsDmaControlRegsP->DCSR[channel] &= 0x7FFFFFFF; // RUN = 0
tmp = 0;
PrintfUartDef(" Waiting channel to be not busy (channel %d)\r\n",channel);
while (!tmp)
{
tmp = XsDmaControlRegsP->DCSR[channel] & 0x08;
Util_DelayUs(1);
}
PrintfUartDef(" Channel vacant\r\n");
XsDmaControlRegsP->DCSR[channel] = 0x00000008;
XsDmaControlRegsP->DDG[channel].DDADR = ((UINT32)pdesc);// | 0xA0000001;
XsDmaControlRegsP->DRCMR[XSDMA_DRCMR_ID_AC97_AUDIO_TX] = channel | 0x080u;
//Waiting for current DMA End
tmp = XsDmaControlRegsP->DCSR[channelin];
XsDmaControlRegsP->DCSR[channelin] &= 0x7FFFFFFF; // RUN = 0
tmp = 0;
PrintfUartDef(" Waiting channel to be not busy (channelin %d)\r\n",channelin);
while (!tmp)
{
tmp = XsDmaControlRegsP->DCSR[channelin] & 0x08;
Util_DelayUs(1);
}
PrintfUartDef(" Channel vacant\r\n");
XsDmaControlRegsP->DCSR[channelin] = 0x00000008;
XsDmaControlRegsP->DDG[channelin].DDADR = ((UINT32)(pdescin));// | 0xA0000001;
XsDmaControlRegsP->DRCMR[XSDMA_DRCMR_ID_AC97_AUDIO_RX] = channelin | 0x080u;
XsAc97CtrlRegsP->POSR |= 0x00000010;
PrintfUartDef(" To start dma\r\n");
startdma(channelin);
startdma(channel);
PrintfUartDef("Exit playpcm\r\n");
return;
while (1);
// The below code is for debug
restart:
XsAc97CtrlRegsP->POSR |= 0x00000010;
tmp = XsDmaControlRegsP->DCSR[channel];
tmp = XsDmaControlRegsP->DCSR[channel] & 0x08;
if (tmp)
{
startdma(channel);
while (XsDmaControlRegsP->DCSR[channel] & 0x08)
{
DDADR = XsDmaControlRegsP->DDG[channel].DDADR;
DSADR = XsDmaControlRegsP->DDG[channel].DSADR;
DTADR = XsDmaControlRegsP->DDG[channel].DTADR;
DCMD = XsDmaControlRegsP->DDG[channel].DCMD;
PrintfUartDef("dma not run\n\t[DDADR]0x%x\n\t[DSADR]0x%x\n\t[DTADR]0x%x\n\t[DCMD]0x%x\n", DDADR, DSADR, DTADR, DCMD);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -