📄 dma.cpp
字号:
// number of frames per block
OUTREG32(&pDMAReg->DMA4_CFN, 1);
// source frame index and element index
OUTREG32(&pDMAReg->DMA4_CSFI, 0);
OUTREG32(&pDMAReg->DMA4_CSEI, 0);
// destination frame index and element index
OUTREG32(&pDMAReg->DMA4_CDFI, 0);
OUTREG32(&pDMAReg->DMA4_CDEI, 0);
#if defined(DEBUG)
DumpDMA_LC(L"Init Output", pDMAReg);
#endif
DEBUGMSG(ZONE_FUNCTION, (L"-OMAP2420DMAContext::WInitOutputDMA()\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: HWStartInputDMA ()
//
// Start the output DMA.
//
void
OMAP2420DMAContext::HWStartInputDMA()
{
OMAP2420_DMA_REGS *pDMAReg;
DEBUGMSG(ZONE_FUNCTION, (L"OMAP2420DMAContext::HWStartInputDMA()\r\n"));
pDMAReg = m_pInDMAReg;
#ifdef PROFILE_MIXER
GetInputDeviceContext(0)->StartMixerProfiler();
#endif
// enable the channel
SETREG32(&pDMAReg->DMA4_CLNK_CTRL, DMA_CLNK_CTRL_ENABLE_LINK);
SETREG32(&pDMAReg->DMA4_CCR, DMA_CCR_ENABLE);
#if defined(DEBUG)
DumpDMA_LC(L"Start Input", pDMAReg);
CheckDMAStatus(pDMAReg, TRUE);
#endif
HWEnableInputChannel(TRUE);
DEBUGMSG(ZONE_FUNCTION, (L"-OMAP2420DMAContext::HWStartInputDMA()\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: HWStopInputDMA ()
//
// Stop the input DMA.
//
void
OMAP2420DMAContext::HWStopInputDMA()
{
OMAP2420_DMA_REGS *pDMAReg;
DWORD i, dwVal;
DEBUGMSG(ZONE_FUNCTION, (L"+OMAP2420DMAContext::HWStopInputDMA()\r\n"));
pDMAReg = m_pInDMAReg;
// disable the DMA channel link and wait for reading to finish
CLRREG32(&pDMAReg->DMA4_CLNK_CTRL, DMA_CLNK_CTRL_ENABLE_LINK);
dwVal = INREG32(&pDMAReg->DMA4_CCR);
for (i = 0; (i < DMA_SAFETY_LOOP_NUM) && (dwVal & DMA_CCR_RD_ACTIVE); i++)
{
Sleep(1);
dwVal = INREG32(&pDMAReg->DMA4_CCR);
}
// disable DMA on the channel
CLRREG32(&pDMAReg->DMA4_CCR, DMA_CCR_ENABLE);
// clear pending interrupts
OUTREG32(&pDMAReg->DMA4_CSR, INREG32(&pDMAReg->DMA4_CSR));
DMA_ControllerSet(m_hCont, DMACP_L3IntAck, 1 << AUDIO_INPUT_DMA_CHANNEL);
// disable the rest of the channel
HWEnableInputChannel(FALSE);
#if defined(DEBUG)
DumpDMA_LC(L"Stop Input", pDMAReg);
CheckDMAStatus(pDMAReg, FALSE);
#endif
#ifdef PROFILE_MIXER
LARGE_INTEGER liTotalTime;
LARGE_INTEGER liMixerTime;
GetInputDeviceContext(0)->StopMixerProfiler(&liTotalTime,&liMixerTime);
DEBUGMSG(ZONE_DMA, (L"OMAP2420DMAContext::HWStopInputDMA: "
L"Total capture time: %dms, %dms while mixing\r\n", (DWORD) (liTotalTime.QuadPart), (DWORD) (liMixerTime.QuadPart)
));
#endif
DEBUGMSG(ZONE_FUNCTION, (L"-OMAP2420DMAContext::HWStopInputDMA()\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: HWStartOutputDMA ()
//
// Stop the output DMA.
//
void
OMAP2420DMAContext::HWStartOutputDMA()
{
OMAP2420_DMA_REGS *pDMAReg;
DEBUGMSG(ZONE_FUNCTION, (L"+OMAP2420DMAContext::HWStartOutputDMA()\r\n"));
#ifdef PROFILE_MIXER
GetOutputDeviceContext(0)->StartMixerProfiler();
#endif
pDMAReg = m_pOutDMAReg;
// enable the channel
SETREG32(&pDMAReg->DMA4_CLNK_CTRL, DMA_CLNK_CTRL_ENABLE_LINK);
SETREG32(&pDMAReg->DMA4_CCR, DMA_CCR_ENABLE);
#if defined(DEBUG)
DumpDMA_LC(L"Start Output", pDMAReg);
CheckDMAStatus(pDMAReg, TRUE);
#endif
HWEnableOutputChannel(TRUE);
DEBUGMSG(ZONE_FUNCTION, (L"-OMAP2420DMAContext::HWStartOutputDMA()\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: HWStopOutputDMA ()
//
// Stop the output DMA.
//
void
OMAP2420DMAContext::HWStopOutputDMA()
{
OMAP2420_DMA_REGS *pDMAReg;
DWORD i, dwVal;
DEBUGMSG(ZONE_FUNCTION, (L"+OMAP2420DMAContext::HWStopOutputDMA()\r\n"));
pDMAReg = m_pOutDMAReg;
// disable the DMA channel link and wait for writing to finish
CLRREG32(&pDMAReg->DMA4_CLNK_CTRL, DMA_CLNK_CTRL_ENABLE_LINK);
dwVal = INREG32(&pDMAReg->DMA4_CCR);
for (i = 0; (i < DMA_SAFETY_LOOP_NUM) && (dwVal & DMA_CCR_WR_ACTIVE); i++)
{
Sleep(1);
dwVal = INREG32(&pDMAReg->DMA4_CCR);
}
// disable DMA on the channel
CLRREG32(&pDMAReg->DMA4_CCR, DMA_CCR_ENABLE);
// clear pending interrupts
OUTREG32(&pDMAReg->DMA4_CSR, INREG32(&pDMAReg->DMA4_CSR));
DMA_ControllerSet(m_hCont, DMACP_L2IntAck, 1 << AUDIO_OUTPUT_DMA_CHANNEL);
// disable the rest of the channel
HWEnableOutputChannel(FALSE);
#if defined(DEBUG)
DumpDMA_LC(L"Stop Output", pDMAReg);
CheckDMAStatus(pDMAReg, FALSE);
#endif
#ifdef PROFILE_MIXER
LARGE_INTEGER liTotalTime;
LARGE_INTEGER liMixerTime;
GetOutputDeviceContext(0)->StopMixerProfiler(&liTotalTime,&liMixerTime);
DEBUGMSG(ZONE_DMA,(L"OMAP2420DMAContext::HWStopOutputDMA: "
L"Total play time: %dms, %dms while mixing\r\n", (DWORD) (liTotalTime.QuadPart), (DWORD) (liMixerTime.QuadPart)
));
#endif
DEBUGMSG(ZONE_FUNCTION, (L"-OMAP2420DMAContext::HWStopOutputDMA()\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: HWTransferInputBuffers ()
//
// Transfer capture buffers.
//
ULONG
OMAP2420DMAContext::HWTransferInputBuffers()
{
ULONG BytesTransferred=0;
OMAP2420_DMA_REGS *pDMAReg;
DWORD dwVal, dwOffset;
pDMAReg = m_pInDMAReg;
// read the CSR register, clear interrupt bits
dwVal = INREG32(&pDMAReg->DMA4_CSR);
OUTREG32(&pDMAReg->DMA4_CSR, dwVal);
DMA_ControllerSet(m_hCont, DMACP_L3IntAck, 1 << AUDIO_INPUT_DMA_CHANNEL);
DEBUGMSG(ZONE_FUNCTION, (L"+OMAP2420DMAContext::HWTransferInputBuffers() %08X\n", dwVal));
// an error occured
if (dwVal & DMA_CSR_DROP)
{
DEBUGMSG(ZONE_ERROR|ZONE_DMA, (L"OMAP2420DMAContext::HWTransferInputBuffers: "
L"RX DMA CSR error = 0x%x\r\n", dwVal
));
}
// make sure this is a HALF or FRAME interrupt
if (!(dwVal & (DMA_CSR_HALF|DMA_CSR_FRAME)))
{
DEBUGMSG(ZONE_DMA, (L"OMAP2420DMAContext::HWTransferInputBuffers: "
L"NOT input interrupt %08X\n", dwVal
));
return BytesTransferred;
}
// if both HALF and FRAME are on, then we lost one of them
if ((dwVal & (DMA_CSR_HALF|DMA_CSR_FRAME)) == (DMA_CSR_HALF|DMA_CSR_FRAME))
{
DEBUGMSG(ZONE_ERROR, (L"OMAP2420DMAContext::HWTransferInputBuffers: "
L"Input buffer interrupt lost\r\n"
));
// pick HALF or FRAME based on which half of the frame the read pointer is in
dwOffset = INREG32(&pDMAReg->DMA4_CSAC) - INREG32(&pDMAReg->DMA4_CSSA);
dwVal = (dwOffset >= AUDIO_DMA_PAGE_SIZE) ? DMA_CSR_HALF : DMA_CSR_FRAME;
}
// HALF interrupt, reload page 0
if (dwVal & DMA_CSR_HALF)
{
BytesTransferred += TransferInputBuffer(0);
}
// FRAME interrupt, reload page 1
if (dwVal & DMA_CSR_FRAME)
{
BytesTransferred += TransferInputBuffer(1);
}
// stop DMA when there's no more data
if (BytesTransferred == 0)
{
StopInputDMA();
}
return BytesTransferred;
}
//------------------------------------------------------------------------------
//
// Function: HWTransferOutputBuffers ()
//
// Transfer playback buffers.
//
ULONG
OMAP2420DMAContext::HWTransferOutputBuffers()
{
ULONG BytesTransferred=0;
OMAP2420_DMA_REGS *pDMAReg;
DWORD dwVal, dwOffset;
pDMAReg = m_pOutDMAReg;
// read the DMA CSR register, clear interrupt bits.
dwVal = INREG32(&pDMAReg->DMA4_CSR);
OUTREG32(&pDMAReg->DMA4_CSR, dwVal);
DMA_ControllerSet(m_hCont, DMACP_L2IntAck, 1 << AUDIO_OUTPUT_DMA_CHANNEL);
DEBUGMSG(ZONE_FUNCTION, (L"OMAP2420DMAContext::HWTransferOutputBuffers() %08X\n", dwVal));
// an error occured
if (dwVal & DMA_CSR_DROP)
{
DEBUGMSG(ZONE_ERROR|ZONE_DMA, (L"OMAP2420DMAContext::HWTransferOutputBuffers: "
L"TX DMA CSR error = 0x%x\r\n", dwVal
));
}
// make sure this is a HALF or FRAME interrupt
if (!(dwVal & (DMA_CSR_HALF|DMA_CSR_FRAME)))
{
DEBUGMSG(ZONE_DMA, (L"OMAP2420DMAContext::HWTransferOutputBuffers: "
L"NOT output interrupt %08X\n", dwVal
));
return BytesTransferred;
}
// if both HALF and FRAME are on, then we lost an interrupt
if ((dwVal & (DMA_CSR_HALF|DMA_CSR_FRAME)) == (DMA_CSR_HALF|DMA_CSR_FRAME))
{
DEBUGMSG(ZONE_ERROR|ZONE_DMA, (L"OMAP2420DMAContext::HWTransferOutputBuffers: "
L"Ooutput buffer interrupt lost\r\n"
));
// pick HALF or FRAME based on which half of the frame the write pointer is in
dwOffset = INREG32(&pDMAReg->DMA4_CSAC) - INREG32(&pDMAReg->DMA4_CSSA);
dwVal = (dwOffset >= AUDIO_DMA_PAGE_SIZE) ? DMA_CSR_HALF : DMA_CSR_FRAME;
}
// HALF interrupt, reload page 0
if (dwVal & DMA_CSR_HALF)
{
BytesTransferred += TransferOutputBuffer(0);
}
// FRAME interrupt, reload page 1
if (dwVal & DMA_CSR_FRAME)
{
BytesTransferred += TransferOutputBuffer(1);
}
// stop DMA when there's no more data
if (BytesTransferred == 0)
{
StopOutputDMA();
}
DEBUGMSG(ZONE_FUNCTION, (L"-OMAP2420DMAContext::HWTransferOutputBuffers() %08X %d\r\n", dwVal, BytesTransferred));
return BytesTransferred;
}
//------------------------------------------------------------------------------
//
// Function: DumpDMA_LC ()
//
// dump DMA logical channel registers
//
#if defined(DEBUG)
static void
DumpDMA_LC(PTSTR szChannel, OMAP2420_DMA_REGS *pCh)
{
DEBUGMSG(ZONE_DMA,(L"AC: %s Channel\r\n", szChannel, GetTickCount()));
DEBUGMSG(ZONE_DMA,(L"AC: CSDP: %08X\r\n", INREG32(&pCh->DMA4_CSDP)));
DEBUGMSG(ZONE_DMA,(L"AC: CCR: %08X\r\n", INREG32(&pCh->DMA4_CCR)));
DEBUGMSG(ZONE_DMA,(L"AC: CICR: %08X\r\n", INREG32(&pCh->DMA4_CICR)));
DEBUGMSG(ZONE_DMA,(L"AC: CSR: %08X\r\n", INREG32(&pCh->DMA4_CSR)));
DEBUGMSG(ZONE_DMA,(L"AC: CSSA: %08X\r\n", INREG32(&pCh->DMA4_CSSA)));
DEBUGMSG(ZONE_DMA,(L"AC: CDSA: %08X\r\n", INREG32(&pCh->DMA4_CDSA)));
DEBUGMSG(ZONE_DMA,(L"AC: CEN: %08X\r\n", INREG32(&pCh->DMA4_CEN)));
DEBUGMSG(ZONE_DMA,(L"AC: CFN: %08X\r\n", INREG32(&pCh->DMA4_CFN)));
DEBUGMSG(ZONE_DMA,(L"AC: CSFI: %08X\r\n", INREG32(&pCh->DMA4_CSFI)));
DEBUGMSG(ZONE_DMA,(L"AC: CSEI: %08X\r\n", INREG32(&pCh->DMA4_CSEI)));
DEBUGMSG(ZONE_DMA,(L"AC: CSAC: %08X\r\n", INREG32(&pCh->DMA4_CSAC)));
DEBUGMSG(ZONE_DMA,(L"AC: CDAC: %08X\r\n", INREG32(&pCh->DMA4_CDAC)));
DEBUGMSG(ZONE_DMA,(L"AC: CDEI: %08X\r\n", INREG32(&pCh->DMA4_CDEI)));
DEBUGMSG(ZONE_DMA,(L"AC: CDFI: %08X\r\n", INREG32(&pCh->DMA4_CDFI)));
DEBUGMSG(ZONE_DMA,(L"AC: COLOR: %08X\r\n", INREG32(&pCh->DMA4_COLOR)));
DEBUGMSG(ZONE_DMA,(L"AC: CLNK_CTRL: %08X\r\n", INREG32(&pCh->DMA4_CLNK_CTRL)));
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -