📄 wmxscaledma.c
字号:
/*-----------------------------------------------------------------------------
* Function: WMDMAMarkBufferEmpty
*
* Marks the given DMA buffer as empty and ready to receive more data.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel the channel ID.
* pBuffer the buffer to mark as empty (from WMDMAGetChannelBuffer).
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMDMAMarkBufferEmpty( WM_DEVICE_HANDLE hDevice,
WMDMA_CHAN_HANDLE channel,
void *pBuffer
)
{
ChannelDef *pChannelDef = (ChannelDef *)channel;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
if ( pChannelDef->buffer1 == pBuffer )
{
pChannelDef->flags &= ~WMCHAN_BUF1_FULL;
}
else if ( pChannelDef->buffer2 == pBuffer )
{
pChannelDef->flags &= ~WMCHAN_BUF2_FULL;
}
else
{
WM_ASSERT( hDevice,
pChannelDef->buffer1 == pBuffer || pChannelDef->buffer2 == pBuffer
);
}
}
/*-----------------------------------------------------------------------------
* Function: WMDMAStartChannel
*
* Sets the channel running.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel the channel to start.
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMDMAStartChannel( WM_DEVICE_HANDLE hDevice, WMDMA_CHAN_HANDLE channel )
{
unsigned int pDesc;
XLLP_DMAC_DRCMR_T device;
ChannelDef *pChannelDef = (ChannelDef *)channel;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
/*
* If the channel is active there's nothing to do.
*/
if ( pChannelDef->flags & WMCHAN_ACTIVE )
{
return;
}
/*
* Enable the Voice DAC Interface if it's required.
*/
if ( WM_IS_VOICE_SUPPORTED( hDevice ) &&
WM_IS_VOICE_CHANNEL( pChannelDef->pDetails->APIChannel )
)
{
WMVoiceEnable( hDevice );
WMVoiceStart( hDevice );
}
/*
* Set up and start the DMA.
*/
/*
* Set the physical address of the descriptor.
*/
pDesc = (unsigned int) pChannelDef->desc1Physical;
WM_ASSERT( hDevice, (pDesc & DESC_ADDRESS_MASK) == pDesc );
pDeviceContext->v_pDmaReg->DDG[pChannelDef->DMAChannel].DDADR = pDesc;
/*
* setup the request channel map register (with channel and valid).
*/
device = pChannelDef->pDetails->DMADevice;
pDeviceContext->v_pDmaReg->DRCMR1[device] = DMA_MAP_VALID_MASK | pChannelDef->DMAChannel;
switch ( device )
{
#if WM_AC97
case DMA_CHAN_AC97_STEREO_OUT:
/* Clear output FIFO errors */
pDeviceContext->v_pAC97Regs->POSR = 0x10;
break;
case DMA_CHAN_AC97_STEREO_IN:
/* Clear input FIFO errors */
pDeviceContext->v_pAC97Regs->PISR = 0x10;
/* Flush input FIFO */
private_Flush_InputFIFO( hDevice,
&(pDeviceContext->v_pAC97Regs->PCDR),
AC97_FIFO_DEPTH);
break;
case DMA_CHAN_AC97_MIC:
/* Clear input FIFO errors */
pDeviceContext->v_pAC97Regs->MCSR = 0x10;
/* Flush input FIFO */
private_Flush_InputFIFO( hDevice,
&(pDeviceContext->v_pAC97Regs->MCDR),
AC97_FIFO_DEPTH);
break;
#endif /* WM_AC97 */
#if WM_I2S
case DMA_CHAN_I2S_STEREO_OUT:
/* Clear output FIFO errors */
pDeviceContext->v_pI2SRegs->SAICR = XLLP_SAICR_TUR;
break;
case DMA_CHAN_I2S_STEREO_IN:
/* Clear input FIFO errors */
pDeviceContext->v_pI2SRegs->SAICR = XLLP_SAICR_ROR;
/* Flush input FIFO */
private_Flush_InputFIFO( hDevice,
&(pDeviceContext->v_pI2SRegs->SADR),
I2S_INPUT_FIFO_DEPTH);
break;
#endif /* WM_I2S */
#if WM_VOICE
case DMA_CHAN_VOICE_OUT:
/* Clear output FIFO errors */
pDeviceContext->v_pSSP2Regs->ssr = XLLP_SSSP_TUR;
break;
case DMA_CHAN_VOICE_IN:
/* Clear input FIFO errors */
pDeviceContext->v_pSSP2Regs->ssr = XLLP_SSSP_ROR;
break;
#endif /* WM_VOICE */
}
/*
* Clear all the DMA interrupts.
*/
pDeviceContext->v_pDmaReg->DCSR[pChannelDef->DMAChannel] |= DCSR_DMA_INT_MASK;
/*
* Set the channel to be active.
*/
pChannelDef->flags |= WMCHAN_ACTIVE;
/*
* The rest of the registers are loaded when the RUN bit is set in
* the DCSR.
*/
pDeviceContext->v_pDmaReg->DCSR[pChannelDef->DMAChannel] |= DCSR_RUN;
}
/*-----------------------------------------------------------------------------
* Function: WMDMAStopChannel
*
* Stops the channel. Any outstanding data in the DMA buffers is lost.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel the channel to stop.
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMDMAStopChannel( WM_DEVICE_HANDLE hDevice, WMDMA_CHAN_HANDLE channel )
{
ChannelDef *pChannelDef = (ChannelDef *)channel;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
/*
* Stop the DMA.
*/
pDeviceContext->v_pDmaReg->DCSR[pChannelDef->DMAChannel] &= ~DCSR_RUN;
/*
* Stop the Voice DAC Interface if we started it.
* Note: this assumes there is only one Voice DAC channel.
*/
if ( WM_IS_VOICE_SUPPORTED( hDevice ) &&
WM_IS_VOICE_CHANNEL( pChannelDef->pDetails->APIChannel )
)
{
WMVoiceStop( hDevice );
}
/*
* Clean out our buffers.
*/
private_CleanChannelBuffers( hDevice, pChannelDef );
/*
* We're no longer active.
*/
pChannelDef->flags &= ~WMCHAN_ACTIVE;
/*
* Assume this means both buffers are transmitted or neither is filled.
*/
pChannelDef->flags &= ~( WMCHAN_BUF1_FULL | WMCHAN_BUF2_FULL );
}
/*-----------------------------------------------------------------------------
* Function: WMDMACheckChannelInterrupts
*
* This function checks what interrupts have happened and clears them.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel the channel to check. This must have been initialised
* using WMAudioChannel.
*
* Returns: WMAUDIO_INTSTATE
* bitmask listing the interrupts
*---------------------------------------------------------------------------*/
WMAUDIO_INTSTATE WMDMACheckChannelInterrupts( WM_DEVICE_HANDLE hDevice,
WMDMA_CHAN_HANDLE channel
)
{
unsigned int dcsr;
WMAUDIO_INTSTATE intState = 0;
ChannelDef *pChannelDef = (ChannelDef *)channel;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
WM_ASSERT( hDevice, ( NULL != pChannelDef) );
WM_ASSERT( hDevice, ( NULL != pDeviceContext) );
/*
* Current descriptor finished succesfully.
*/
dcsr = pDeviceContext->v_pDmaReg->DCSR[pChannelDef->DMAChannel];
if ( dcsr & DCSR_ENDINTR )
{
intState |= WMAUDIO_INT_END;
}
/*
* Bus error - descriptor loaded but not ready for use.
*/
if ( dcsr & DCSR_BUSERRINTR )
{
intState |= WMAUDIO_INT_ERROR;
WM_TRACE( hDevice, ("WMDMACheckChannelInterrupts: Bus error - descriptor loaded but not ready for use"));
WM_ASSERT( hDevice, !(dcsr & DCSR_BUSERRINTR) );
}
/*
* Clear all the DMA interrupts.
*/
pDeviceContext->v_pDmaReg->DCSR[pChannelDef->DMAChannel] |=
(dcsr & DCSR_DMA_INT_MASK);
return intState;
}
/*-----------------------------------------------------------------------------
* Function: WMDMAHandleInterrupt
*
* This function allows the library to do any processing required when an
* interrupt is received on an audio channel. This _must_ be called
* when an interrupt is received to allow the library to keep its internal
* state correct.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel the channel ID.
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMDMAHandleInterrupt( WM_DEVICE_HANDLE hDevice, WMDMA_CHAN_HANDLE channel )
{
ChannelDef *pChannelDef = (ChannelDef *)channel;
void *pBuffer;
unsigned int flag;
/*
* Work out which buffer. If we've just had the interrupt, the
* DMA controller will already have switched buffers. This means the
* buffer which has just been finished is the one which is _not_ in
* the DMA - i.e. the one which private_GetNextBuffer returns.
*
* This assumes we only have two buffers, of course...
*/
pBuffer = private_GetNextBuffer( hDevice, channel );
if ( pChannelDef->buffer1 == pBuffer )
{
flag = WMCHAN_BUF1_FULL;
}
else
{
flag = WMCHAN_BUF2_FULL;
}
/*
* Now mark it as available. An output buffer is available if empty.
* An input buffer is available if full.
*/
if ( pChannelDef->pDetails->flags & WM_INPUT )
{
pChannelDef->flags |= flag;
}
else
{
pChannelDef->flags &= ~flag;
}
}
/*-----------------------------------------------------------------------------
* Function: WMDMAGetMaxBufferSize
*
* This function returns the maximum size for a DMA buffer in bytes.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: unsigned int
* the number of bytes in an audio sample for the given channel
*---------------------------------------------------------------------------*/
unsigned int WMDMAGetMaxBufferSize( WM_DEVICE_HANDLE hDevice )
{
return WMAUDIO_MAX_BUFFER_SIZE;
}
/*-----------------------------------------------------------------------------
* Function: WMDMAGetBytesPerSample
*
* This function returns the number of bytes per sample on the given channel.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel the channel to check.
*
* Returns: unsigned int
* the number of bytes in an audio sample for the given channel.
* 0 indicates that the channel cannot be found.
*---------------------------------------------------------------------------*/
unsigned int WMDMAGetBytesPerSample( WM_DEVICE_HANDLE hDevice,
WMAUDIO_CHANNEL APIChannel
)
{
const DMA_CHANNEL_DETAILS *pChannelDetails;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
DMAContext *pDMAContext = pDeviceContext->pDMAContext;
WM_ASSERT( hDevice, pDMAContext->initialised );
pChannelDetails = WMDMAGetChannelDetails( hDevice, APIChannel );
if ( NULL == pChannelDetails )
{
return 0;
}
return (pChannelDetails->nBytesPerSample);
}
/*-----------------------------------------------------------------------------
* Function: WMDMAIsStereo
*
* This function returns whether or not the given channel is stereo.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* APIChannel the channel to check.
*
* Returns: WM_BOOL
* TRUE if the given channel is stereo
* FALSE for all other situations (including error conditions)
*---------------------------------------------------------------------------*/
WM_BOOL WMDMAIsStereo( WM_DEVICE_HANDLE hDevice,
WMAUDIO_CHANNEL APIChannel
)
{
const DMA_CHANNEL_DETAILS *pChannelDetails;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
DMAContext *pDMAContext = pDeviceContext->pDMAContext;
WM_ASSERT( hDevice, pDMAContext->initialised );
pChannelDetails = WMDMAGetChannelDetails( hDevice, APIChannel );
if ( NULL == pChannelDetails )
{
return FALSE;
}
if ( WM_STEREO & pChannelDetails->flags )
return TRUE;
else
return FALSE;
}
/*-----------------------------------------------------------------------------
* Function: WMDMAIsInput
*
* This function returns whether or not the given channel is an input.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* APIChannel the channel to check.
*
* Returns: WM_BOOL
* TRUE if the given channel is an input
* FALSE for all other situations (including error conditions)
*---------------------------------------------------------------------------*/
WM_BOOL WMDMAIsInput( WM_DEVICE_HANDLE hDevice,
WMAUDIO_CHANNEL APIChannel
)
{
const DMA_CHANNEL_DETAILS *pChannelDetails;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
DMAContext *pDMAContext = pDeviceContext->pDMAContext;
WM_ASSERT( hDevice, pDMAContext->initialised );
pChannelDetails = WMDMAGetChannelDetails( hDevice, APIChannel );
if ( NULL == pChannelDetails )
{
return FALSE;
}
if ( WM_INPUT & pChannelDetails->flags )
return TRUE;
else
return FALSE;
}
/*-----------------------------------------------------------------------------
* Function: WMDMAIsWide
*
* This function returns whether or not the given channel is 32 bits wide.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* APIChannel the channel to check.
*
* Returns: WM_BOOL
* TRUE if the given channel is wide
* FALSE for all other situations (including error conditions)
*---------------------------------------------------------------------------*/
WM_BOOL WMDMAIsWide( WM_DEVICE_HANDLE hDevice,
WMAUDIO_CHANNEL APIChannel
)
{
const DMA_CHANNEL_DETAILS *pChannelDetails;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
DMAContext *pDMAContext = pDeviceContext->pDMAContext;
WM_ASSERT( hDevice, pDMAContext->initialised );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -