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

📄 wmxscaleaclink.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 4 页
字号:
         * Clear command done bit to be safe.
         */
        pDeviceContext->v_pAC97Regs->GSR = AC97GSR_CDONE;

        /*
         * Write the data.
         */
        *regAddr = (unsigned int) value;

        /*
         * Wait for command done.
         */
        status = private_WaitForCommandDone( hDevice );
        if ( WMS_DEVICE_BUSY == status )
        {
            WM_TRACE( hDevice, (
                      "WMPlatformACLinkWrite: CDONE didn't get set"
                    ));
            goto error;
        }

        /*
         * Clear command done bit again.
         */
        pDeviceContext->v_pAC97Regs->GSR = AC97GSR_CDONE;
    }

    /*
     * It worked.
     */
done:
#endif /* WM_USE_XLLP_AC97 */
    return WMS_SUCCESS;

    /*
     * Error cleanup.
     */
error:
    /*
     * Clear command done bit.
     */
    pDeviceContext->v_pAC97Regs->GSR = AC97GSR_CDONE;

    return status;
}

#if WM_GPIO_CONTROL
/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkClearGPIOInput
 *
 * Writes the given value to the GPIO status register on the codec, using
 * slots 1 and 2 of the AC-link frame.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      regval      the new value to write to the register.  0 clears sticky bits.
 *                  Note: to preserve the values of output GPIOs, you must write
 *                  the correct value to them (i.e. you cannot just write all
 *                  zeroes if you have GPIO outputs).
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkClearGPIOInput( WM_DEVICE_HANDLE hDevice,
                                         WM_REGVAL regval
                                       )
{
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext = 
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status = WMS_SUCCESS;

#if WM_USE_XLLP_AC97
    {
        XLLP_ACODEC_CONTEXT_T   ACodecCtxStruct;
        XLLP_ACODEC_ERROR_T     xllpStatus;
        
        ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
        
        xllpStatus = XllpAc97ACodecClearGPIO( &ACodecCtxStruct, regval );
        if ( XLLP_ACODEC_SUCCESS != xllpStatus )
        {
            WM_TRACE( hDevice, ( "XllpAc97ACodecClearGPIO failed: 0x%X", xllpStatus ));
            status = XllpStatusToWMStatus( xllpStatus );
        }
    }
    
#else   /* WM_USE_XLLP_AC97 */

    if ( !IS_WM9712_FAMILY( hDevice ) )
    {
        /*
         * Do a normal R54 write - this will write to both slots 1 and 2
         * and slot 12, so clearing the sticky bit as well as setting outputs.
         */
        status = WMPlatformACLinkWrite( hDevice, WM97_GPIO_PIN_STATUS, regval );
    }
    else
    {
        unsigned int                pCodecAddr;
        volatile unsigned int        *regAddr;

        /*
         * For the WM9711/12 we need to write via codec space to clear sticky bits.
         */
        pCodecAddr = PRIMARY_CODEC_REGS( pDeviceContext );

        /*
         * Work out the virtual address corresponding to the register.
         * The registers are based at v_pAC97Regs->CodecRegsPrimaryAud
         * and are each 16-bits wide, i.e. at offset reg*2 from the base.
         */
        regAddr = (volatile unsigned int *) (pCodecAddr + (WM97_GPIO_PIN_STATUS << 1));

        /*
         * Write the data.
         */
        *regAddr = (unsigned int) regval;

        /*
         * Wait for 2 frames (50uSecs) for IO completion to occur.
         */
        MicroSleep( hDevice, 50 );
    }
#endif /* WM_USE_XLLP_AC97 */

    return status;
}
#endif /* WM_GPIO_CONTROL */

#if WM_STREAM_AUXADC
/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkReadCTCAuxADC
 *
 * Reads the next ADC value from the stream in continuous conversion mode (CTC).
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *      pValue              variable to receive value
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkReadCTCAuxADC( WM_DEVICE_HANDLE hDevice,
                                        WM_REGVAL *pValue
                                      )
{
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext =
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status = WMS_SUCCESS;

#if AC97_RXFIFO_SERVICE_REQUEST
    /* Check whether there's data available. */
    if ( !pDeviceContext->v_pAC97Regs->MISR & AC97_RXFIFO_SERVICE_REQUEST )
    {
        status = WMS_NO_DATA;
        goto done;
    }
#endif /* AC97_RXFIFO_SERVICE_REQUEST */

    /* Check for overrun */
    if ( pDeviceContext->v_pAC97Regs->MISR & AC97_RXFIFO_ERROR )
    {
        /*
         * Now clear the error condition (by writing the bit).
         * Note: we don't do anything about flushing the FIFO because experiments
         * have shown that this actually makes things worse.
         */
        pDeviceContext->v_pAC97Regs->MISR = AC97_RXFIFO_ERROR;
    }

    /* Read the value */
    *pValue = (WM_REGVAL) pDeviceContext->v_pAC97Regs->MODR;

    /* Check for underrun */
    if ( pDeviceContext->v_pAC97Regs->MISR & AC97_RXFIFO_ERROR )
    {
        status = WMS_NO_DATA;

        /* Now clear the error condition (by writing the bit). */
        pDeviceContext->v_pAC97Regs->MISR = AC97_RXFIFO_ERROR;
    }

#if AC97_RXFIFO_SERVICE_REQUEST
done:
#endif /* AC97_RXFIFO_SERVICE_REQUEST */
    return status;
}
#endif /* WM_STREAM_AUXADC */

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkSetController
 *
 * Enables or disables the AC Link on the controller.
 * After enabling a cold/warm reset must be performed for the link to come up.
 * Before disabling the codec must be powered down.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *      enable              Whether to enable the link.
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void WMPlatformACLinkSetController( WM_DEVICE_HANDLE hDevice, WM_BOOL enable )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    
    if ( enable )
    {
        pDeviceContext->v_pAC97Regs->GCR &= ~AC97GCR_AclinkOff;
    }
/* 
 * Don't disable the PXA27X AC-Controller once it's been enabled as it causes
 * undesirable effects to the FIFOs after a suspend/resume cycle.
 */
#if !WM_CPU_PXA27X
    else
    {
        pDeviceContext->v_pAC97Regs->GCR |= AC97GCR_AclinkOff;
    }
#endif
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkIsCodecReady
 *
 * Returns whether the AC link is enabled and available for reading and writing.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WM_BOOL
 *      TRUE if it's enabled.
 *---------------------------------------------------------------------------*/
WM_BOOL WMPlatformACLinkIsCodecReady( WM_DEVICE_HANDLE hDevice )
{
    return private_IsCodecReady( hDevice );
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkColdReset
 *
 * Forces a cold reset of the WM97xx device, restoring everything to its
 * default startup condition.
 *
 * Note: this function assumes the workaround is in place for the
 * XScale bug in the AC Link controller - using a GPIO for the reset instead
 * of the AC link reset.  See WMPlatformConfig.h for more details.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkColdReset( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext = 
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status;

#if WM_USE_XLLP_AC97
    {
        XLLP_ACODEC_CONTEXT_T   ACodecCtxStruct;
        XLLP_ACODEC_ERROR_T     xllpStatus;
        
        ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
        

		/* 
		 * We _should_ know what we are, at this point,  
		 * so convert to an XLLP codec ID (most codecs are 
		 * treated the same as the 9712). 
		 */
		if ( IS_WM9705_FAMILY( hDevice ) )
		{
			ACodecCtxStruct.ACodecId = WM_9712_ID;
		}
		if ( IS_WM9707_FAMILY( hDevice ) )
		{
			ACodecCtxStruct.ACodecId = WM_9712_ID;
		}
		if ( IS_WM9712_FAMILY( hDevice ) )
		{
			ACodecCtxStruct.ACodecId = WM_9712_ID;
		}
		if ( IS_WM9713_FAMILY( hDevice ) )
		{
			ACodecCtxStruct.ACodecId = WM_9713_ID;
		}
		else
		{
			goto error;
		}

		/*
		 *  Then call through to XLLP to do the work for us.
		 */        
		xllpStatus = XllpACodecInit( &ACodecCtxStruct );
		if ( XLLP_ACODEC_SUCCESS != xllpStatus )
		{
			WM_TRACE( hDevice, ( "XllpACodecInit failed: 0x%X", xllpStatus ));
			status = XllpStatusToWMStatus( xllpStatus );
			goto error;
		}
	}
#else /* WM_USE_XLLP_AC97 */

    /*
     * Initiate a cold reset by dragging the reset line low.
     */
    pDeviceContext->v_pGPIORegs->RESET_GPIO_REG(GPCR) |= RESET_GPIO_MASK;
    pDeviceContext->v_pAC97Regs->GCR &= ~AC97GCR_ColdReset;

    /*
     * After SDATA_IN goes high, SYNC must be held for a minimum of 1 microsecond.
     * Just to be sure everything's OK there is a delay of 10 microseconds.
     */
    MicroSleep( hDevice, 10 );                 

    /*
     * Take the reset line high again to bring us out of cold reset.
     */
    pDeviceContext->v_pGPIORegs->RESET_GPIO_REG(GPSR) |= RESET_GPIO_MASK;
    pDeviceContext->v_pAC97Regs->GCR |= AC97GCR_ColdReset;

    /*
     * We need to be sure the clocks have started before we do a warm reset.
     * 10ms ought to be enough for even the slowest clock to react.
     */
    MilliSleep( hDevice, 10 );

    /*
     * Do a warm reset in case the codec defaults to powered down.
     */
    if ( !private_IsCodecReady( hDevice ) )
    {
        status = WMPlatformACLinkWarmReset( hDevice );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }
    }
    
    /* Check for codec ready. */

⌨️ 快捷键说明

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