⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmxscaledma.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 4 页
字号:

/*-----------------------------------------------------------------------------
 * 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 + -