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

📄 wmxscaledma.c

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

    pChannelDetails = WMDMAGetChannelDetails( hDevice, APIChannel );
	if ( NULL == pChannelDetails )
	{
		return FALSE;
	}

	if ( WM_WIDE & pChannelDetails->flags )
		return TRUE;
	else 
		return FALSE;
}

#if WM_USE_DYNAMIC_DMA_CHANNEL
/*-----------------------------------------------------------------------------
 * Function:    WMDMAGetEventHandle
 *
 * This function returns the DMA interrupt event handle for the given channel
 * (if relevant for this platform).
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *		channel     the channel ID.
 *
 * Returns:     WMEvent_t
 *      the DMA event interrupt handle, or NULL if this is not relevant.
 *---------------------------------------------------------------------------*/
WMEvent_t WMDMAGetEventHandle( WM_DEVICE_HANDLE hDevice,
                                WMDMA_CHAN_HANDLE channel
                              )
{
    ChannelDef  *pChannelDef	= (ChannelDef *)channel;
	char						EventName[WM_DMA_EVENT_STRING];
	
	WMFormatString( EventName, "%s%d", DMA_CHANNEL_PREFIX, pChannelDef->DMAChannel );

	return WMGetNamedEvent( hDevice, EventName );
}
#endif /* WM_USE_DYNAMIC_DMA_CHANNEL */

/*-----------------------------------------------------------------------------
 * Function:    WMDMAEnableInterrupts
 *
 * This function enables DMA interrupts.
 * NOTE: This function is intended for use only by the Wolfson test
 *       code and should not be used by standard library code.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void WMDMAEnableInterrupts( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT  *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;

	volatile XLLP_INTC_T  *v_pIntRegs = pDeviceContext->v_pIntRegs;

    v_pIntRegs->icmr |= XLLP_INTC_DMAC;
}

/*-----------------------------------------------------------------------------
 * Function:    WMDMADisableInterrupts
 *
 * This function disables DMA interrupts.
 * NOTE: This function is intended for use only by the Wolfson test
 *       code and should not be used by standard library code.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void WMDMADisableInterrupts( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT  *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;

	volatile XLLP_INTC_T  *v_pIntRegs = pDeviceContext->v_pIntRegs;

    v_pIntRegs->icmr &= ~XLLP_INTC_DMAC;
}

/*-----------------------------------------------------------------------------
 * Function:    private_GetNextBuffer
 *
 * Returns a pointer to the next DMA buffer for the channel.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      channel     the channel to return the buffer for.
 *
 * Returns:     void *
 *      A pointer to the DMA buffer (of size as configured in WMDMAInit).
 *---------------------------------------------------------------------------*/
void *private_GetNextBuffer( WM_DEVICE_HANDLE hDevice,
                             WMDMA_CHAN_HANDLE channel
                           )
{
    void						*pBuffer;
    ChannelDef					*pChannelDef	= (ChannelDef *)channel;
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext = 
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;

    /*
     * Default to the first buffer.
     */
    pBuffer = pChannelDef->buffer1;

    /*
     * If it's an active channel, we pick the buffer that's not currently
     * being transmitted.  If it's inactive we stick with the first buffer.
     */
    if ( pChannelDef->flags & WMCHAN_ACTIVE )
    {
        const void *pNextDescriptor = (const void *)
             pDeviceContext->v_pDmaReg->DDG[pChannelDef->DMAChannel].DDADR;
             
        if ( pNextDescriptor == pChannelDef->desc2Physical )
        {
            pBuffer = pChannelDef->buffer2;
        }
        
        /* else we've defaulted to buffer1 */
    }
                        
    return pBuffer;
}

/*-----------------------------------------------------------------------------
 * Function:    private_PrepareDescriptors
 *
 * Sets up the DMA descriptors for the given channel (non-XLLP version).
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      pChannelDef DMA Channel definition structure.
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_PrepareDescriptors( WM_DEVICE_HANDLE hDevice,
                                            ChannelDef       *pChannelDef
                                          )
{
    WM_BOOL						isInput;
    void						*channelAddr;
    unsigned int				width, size;
	WMSTATUS					result;
    union DmaCmdReg				CmdBuff			= {0};
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext =
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    DMAContext					*pDMAContext	= pDeviceContext->pDMAContext;

	/*
     * Parameter validation.
     */
    WM_ASSERT( hDevice, NULL != pChannelDef );

    /*
     * Variation for different channels.
     */
    channelAddr = pChannelDef->pDetails->channelAddr;
    isInput = pChannelDef->pDetails->flags & WM_INPUT;

	/*
	 * Allocate DMA channel
	 */
	result =  private_AllocateChannel( hDevice, pChannelDef, pChannelDef->APIChannel );
	if ( WM_ERROR( result ) )
	{
		goto error;
	}

    switch ( pChannelDef->pDetails->nBytesPerSample )
    {
        case 1:
            width = 0x01;
            break;
            
        case 2:
            width = 0x02;
            break;
            
        case 4:
            width = 0x03;
            break;
        
        default:
            WM_TRACE( hDevice,
                      ( "WMDMA PrepareDescriptors: invalid number of bytes per sample: %d\n",
                        pChannelDef->pDetails->nBytesPerSample
                      ));
            WM_ASSERT( hDevice, FALSE );
    }

    /*
     * Maximum burst size of each data transfer.
     */
    size = pChannelDef->pDetails->nBurstSize;

    /*
     * Construct the DCMD register.
     */
    CmdBuff.DcmdReg.len = 0;        // length of the memory buffer
    CmdBuff.DcmdReg.width = width;  // as above
    CmdBuff.DcmdReg.size = size;    // as above 
    CmdBuff.DcmdReg.endian = 0;     // little endian
    CmdBuff.DcmdReg.flybyt = 0;     // Flowthrough
    CmdBuff.DcmdReg.flybys = 0;     // Flowthrough
    CmdBuff.DcmdReg.endirqen = 1;   // 1 means Interrupt when decrement length = 0;
    CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded

    /*
     * Now the stuff which varies depending on whether it's input or output.
     */
    if ( isInput )
    {
        CmdBuff.DcmdReg.flowtrg = 0;    // 1 means the target is an external peripheral
        CmdBuff.DcmdReg.flowsrc = 1;    // 1 means the source is an external peripheral (and needs flow control)
        CmdBuff.DcmdReg.inctrgadd = 1;  // 1 means increment the target address (since it's memory) 
        CmdBuff.DcmdReg.incsrcadd = 0;  // 1 means increment the source address (since it's a peripheral)
    }
    else
    {
        CmdBuff.DcmdReg.flowtrg = 1;    // 1 means the target is an external peripheral
        CmdBuff.DcmdReg.flowsrc = 0;    // 1 means the source is an external peripheral (and needs flow con
        CmdBuff.DcmdReg.inctrgadd = 0;  // 1 means increment the target address (since it's memory) 
        CmdBuff.DcmdReg.incsrcadd = 1;  // 1 means increment the source address (since it's a peripheral)
    }

    /*
     * Now set up the descriptors.
     */
	WM_ASSERT( hDevice,
    		   ((unsigned long) pChannelDef->desc2Physical & DESC_ADDRESS_MASK) ==
               (unsigned long) pChannelDef->desc2Physical
             );
    pChannelDef->desc1->DDADR = (unsigned long) pChannelDef->desc2Physical;     /* Next descriptor */
    pChannelDef->desc1->DCMD  = CmdBuff.DcmdDword;              /* Command */

	WM_ASSERT( hDevice,
    		   ((unsigned long) pChannelDef->desc1Physical & DESC_ADDRESS_MASK) == 
			   (unsigned long) pChannelDef->desc1Physical
			 );
    pChannelDef->desc2->DDADR = (unsigned long) pChannelDef->desc1Physical;     /* Next descriptor */
    pChannelDef->desc2->DCMD  = CmdBuff.DcmdDword;				/* Command */

    if ( isInput )
    {
		WM_ASSERT( hDevice,
				   ((unsigned long) pChannelDef->buffer1Physical & FORCE_64BIT_ALIGNMENT) == 
				   (unsigned long) pChannelDef->buffer1Physical
				 );
        pChannelDef->desc1->DTADR = (unsigned long) pChannelDef->buffer1Physical;   /* Source address */
		WM_ASSERT( hDevice,
    	    	   ((unsigned long) channelAddr & FORCE_128BIT_ALIGNMENT) == 
				   (unsigned long) channelAddr
				 );
        pChannelDef->desc1->DSADR = (unsigned long) channelAddr;                   /* Target address */

		WM_ASSERT( hDevice,
	   	    	   ((unsigned long) pChannelDef->buffer2Physical & FORCE_64BIT_ALIGNMENT) == 
				   (unsigned long) pChannelDef->buffer2Physical
				 );
        pChannelDef->desc2->DTADR = (unsigned long) pChannelDef->buffer2Physical;   /* Source address */
		WM_ASSERT( hDevice,
    	    	   ((unsigned long) channelAddr & FORCE_128BIT_ALIGNMENT) == 
				   (unsigned long) channelAddr
				 );
        pChannelDef->desc2->DSADR = (unsigned long) channelAddr;                   /* Target address */
    }
    else
    {
		WM_ASSERT( hDevice,
    	    	   ((unsigned long) channelAddr & FORCE_64BIT_ALIGNMENT) == 
				   (unsigned long) channelAddr
				 );
        pChannelDef->desc1->DTADR = (unsigned long) channelAddr;                    /* Source address */
		WM_ASSERT( hDevice,
    	    	   ((unsigned long) pChannelDef->buffer1Physical & FORCE_128BIT_ALIGNMENT) == 
				   (unsigned long) pChannelDef->buffer1Physical
				 );
        pChannelDef->desc1->DSADR = (unsigned long) pChannelDef->buffer1Physical;  /* Target address */

		WM_ASSERT( hDevice,
    	    	   ((unsigned long) channelAddr & FORCE_64BIT_ALIGNMENT) == 
				   (unsigned long) channelAddr
				 );
        pChannelDef->desc2->DTADR = (unsigned long) channelAddr;                    /* Source address */
		WM_ASSERT( hDevice,
    	    	   ((unsigned long) pChannelDef->buffer2Physical & FORCE_128BIT_ALIGNMENT) == 
				   (unsigned long) pChannelDef->buffer2Physical
				 );
        pChannelDef->desc2->DSADR = (unsigned long) pChannelDef->buffer2Physical;  /* Target address */
    }

	return ( WMS_SUCCESS );

error:
	return ( result );
}

/*-----------------------------------------------------------------------------
 * Function:    private_AllocateChannel
 *
 * Allocates a DMA channel for the given API channel.
 * Channels are currently preallocated (static model).
 *
 * Parameters:
 * 
 *      hDevice			handle to the device (from WMOpenDevice)
 *		pChannelDef		pointer to DMA channel structure.
 *		APIChannel		The API channel.
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_AllocateChannel( WM_DEVICE_HANDLE  hDevice,
										 ChannelDef        *pChannelDef,
										 WMAUDIO_CHANNEL   APIChannel
									   )
{
	WMSTATUS					status = WMS_INVALID_CHANNEL;

#if WM_USE_DYNAMIC_DMA_CHANNEL
    {
        XLLP_STATUS_T xllpStatus;

        xllpStatus = XllpDmacAllocChannel( &pChannelDef->DMAChannel, 
								           XLLP_DMAC_CHANNEL_PRIORITY_HIGH
                                         );

        status = XllpStatusToWMStatus( xllpStatus );
    }
#else /* WM_USE_DYNAMIC_DMA_CHANNEL */
    {
        int i;
	    /* 
	     * Static mapping - look up channel.
	     */
	    for ( i = 0; i <= WM_ARRAY_COUNT(s_DMAChannelsAvailable); i++ )
	    {
		    if ( APIChannel == s_DMAChannelsAvailable[i].APIChannel )
		    {
			    /* Set up DMA Channel Number in ChannelDef. */
			    pChannelDef->DMAChannel = s_DMAChannelsAvailable[i].DMAChannel;
			    status = WMS_SUCCESS;
				break;
		    }
	    }

	    /* As this is a static allocation this should NOT fail */
	    WM_ASSERT( hDevice, WM_SUCCESS( status ) );
    }
#endif /* WM_USE_DYNAMIC_DMA_CHANNEL */
	return ( status );
}

/*-----------------------------------------------------------------------------
 * Function:    private_SetDMABufferLength
 *
 * Sets the DMA buffer length of transfer in bytes. (non-XLLP version).
 *
 * Parameters:
 *      hDevice     	handle to the device (from WMOpenDevice)
 *      pChannelDef     the channel to prepare.
 *      bufsize     	the size of the DMA buffer(s).
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static void private_SetDMABufferLength( WM_DEVICE_HANDLE hDevice,
                                        ChannelDef       *pChannelDef,
                                        unsigned int     bufsize
                                      )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;

    /*
     * Parameter validation.
     */
    WM_ASSERT( hDevice, NULL != pChannelDef );
    WM_ASSERT( hDevice, bufsize <= WMDMAGetMaxBufferSize( hDevice ) );

    /*
     * Now set the transfer length for each descriptor.
     */
    pChannelDef->desc1->DCMD = 
		(pChannelDef->desc1->DCMD & ~WMAUDIO_DCMD_LEN_MASK) | bufsize;
    pChannelDef->desc2->DCMD = 
		(pChannelDef->desc2->DCMD & ~WMAUDIO_DCMD_LEN_MASK) | bufsize;
}

/*-----------------------------------------------------------------------------
 * Function:    private_CleanChannelBuffers
 *
 * Cleans the channel buffers so they only contain silence.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      pChannelDef the channel to clean.
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void private_CleanChannelBuffers( WM_DEVICE_HANDLE hDevice, ChannelDef *pChannelDef )
{
    /*
     * Set both buffers to zero (silence).
     */
    memset( pChannelDef->buffer1, 0, WMDMAGetMaxBufferSize( hDevice ) );
    memset( pChannelDef->buffer2, 0, WMDMAGetMaxBufferSize( hDevice ) );
}

/*-----------------------------------------------------------------------------
 * Function:    private_Flush_InputFIFO
 *
 * Flushes the given input FIFO.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      pFIFO       the FIFO to flush
 *      depth       depth of FIFO to flush
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void private_Flush_InputFIFO( WM_DEVICE_HANDLE hDevice, 
							  XLLP_VUINT32_T *pFIFO, 
							  unsigned int depth)
{
    unsigned int		i;
    XLLP_VUINT32_T		read_flush;

	/*
     * Reading flushes the FIFO.
     */
    for ( i=0; i<depth; i++)
	{
        read_flush = pFIFO[i];
	}
}

#ifdef DEBUG
/*-----------------------------------------------------------------------------
 * Function: private_DumpDmacChannel
 * 
 * Purpose: Output the value of channel-specific DMAC registers
 * (for debugging purposes only).
 *  
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      pChannelDef pointer to ChannelDef for the channel
 *
 * Returns:      void.
 *
 ----------------------------------------------------------------------------*/
static void private_DumpDmacChannel( WM_DEVICE_HANDLE hDevice,
                                     ChannelDef       *pChannelDef
                                     )
{
    int                         dmaChannel;
    XLLP_DMAC_DRCMR_T           device;
    volatile XLLP_DMAC_T        *v_pDmaReg		= NULL;
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext =
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;

    if ( NULL == pDeviceContext || NULL == pDeviceContext->v_pDmaReg )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -