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

📄 wmxscaleaclink.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 4 页
字号:
void WMPlatformACLinkShutdown( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    
    /* Return the GPIO to general use */
    private_UnconfigureACLinkGPIO( hDevice );
    
    pDeviceContext->flags &= ~DEVICE_INITIALISED;
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkRead
 *
 * Reads the value from the given register.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *      reg                 register to read from
 *      pValue              variable to receive value
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkRead( WM_DEVICE_HANDLE hDevice,
                               WM_REGTYPE reg,
                               WM_REGVAL *pValue
                             )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status;

    /*
     * Parameter validation.
     */
    if ( reg > WM97_MAX_REGISTER )
    {
        status = WMS_REG_NOT_PRESENT;
        goto error;
    }
    
#if WM_USE_XLLP_AC97
    {
        XLLP_ACODEC_CONTEXT_T   ACodecCtxStruct;
        XLLP_ACODEC_ERROR_T     xllpStatus;
        
        ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
        
        xllpStatus = XllpAc97ACodecRead( &ACodecCtxStruct, reg, pValue );
        if ( XLLP_ACODEC_SUCCESS != xllpStatus )
        {
            WM_TRACE( hDevice, ( "XllpAc97ACodecRead failed: 0x%X", xllpStatus ));
            status = XllpStatusToWMStatus( xllpStatus );
            goto error;
        }
    }
    
#else   /* WM_USE_XLLP_AC97 */
    
    {
        unsigned int                pCodecAddr;
        volatile unsigned int       *regAddr;
    
        /*
         * Just to make things complicated, the WM97_GPIO_PIN_STATUS is better
         * supported through the modem codec registers than the audio codec
         * registers, and is cached on the controller, so we don't need to
         * wait for a read to conplete.
         *
         * Due to an issue with PXA27x silicon after A1, reads to register 54h
         * in the modem IO space will cause all subsequent reads and writes
         * to either the codec and/or modem IO space to fail, so on Bulverde we
         * do an ordinary codec-space read instead.
         */
#if !WM_CPU_PXA27X
        if ( WM97_GPIO_PIN_STATUS == reg )
        {
            unsigned int pModemAddr;

            /*
             * Find the right bank of registers.
             */
            if ( WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID )
                pModemAddr = PRIMARY_MODEM_REGS( pDeviceContext );
            else
                pModemAddr = SECONDARY_MODEM_REGS( pDeviceContext );

            regAddr = (volatile unsigned int *) (pModemAddr + (reg << 1));

            /*
             * Read the data.
             */
            *pValue = (WM_REGVAL) *regAddr;

            /*
             * And we don't need to wait for the read to complete.
             */
            goto done;
        }
#endif /* !WM_CPU_PXA27X */

        /*
         * Find the right bank of registers.
         */
        if ( WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID )
            pCodecAddr = PRIMARY_CODEC_REGS( pDeviceContext );
        else
            pCodecAddr = SECONDARY_CODEC_REGS( pDeviceContext );

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

        /*
         * Clear SDONE and CDONE to be safe.
         */
        pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE;
        
        /*
         * Do a dummy read to start the data off.
         */
        *pValue = (WM_REGVAL) *regAddr;

        /*
         * Check for SDONE, and do the real read if it's set.
         */
        status = private_WaitForStatusDone( hDevice );
        if ( WM_ERROR( status ) )
        {
            WM_TRACE( hDevice, (
                      "WMPlatformACLinkRead: SDONE didn't get set after dummy read"
                    ));
            goto error;
        }

        /*
         * Check there was no read error.
         */
        if ( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_READ_COMPLETION_STATUS )
        {
            /* 
             * There was.
             */
            status = WMS_DATA_TIMED_OUT;
            WM_TRACE( hDevice, (
                      "WMPlatformACLinkRead: didn't receive data (timeout on dummy read)"
                    ));
            goto error;
        }

        /*
         * Clear SDONE and CDONE and do the real read.
         */
        pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE;
        *pValue = (WM_REGVAL) *regAddr;

        /*
         * Check for SDONE again.  Once set, we're done.
         */
        status = private_WaitForStatusDone( hDevice );
        if ( WM_ERROR( status ) )
        {
            WM_TRACE( hDevice, (
                      "WMPlatformACLinkRead: SDONE didn't get set after real read"
                    ));
            goto error;
        }

        /*
         * Check there was no read error.
         */
        if ( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_READ_COMPLETION_STATUS )
        {
            /* 
             * There was.
             */
            status = WMS_DATA_TIMED_OUT;
            WM_TRACE( hDevice, (
                      "WM97PlatformRead: didn't receive data (timeout)"
                    ));
            goto error;
        }
    }

    /*
     * Clear SDONE and CDONE again.
     */
    pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE;
    
    /*
     * It worked.
     */
#if !WM_CPU_PXA27X
done:
#endif /* !WM_CPU_PXA27X */
#endif /* WM_USE_XLLP_AC97 */

    return WMS_SUCCESS;

    /*
     * Error cleanup.
     */
error:
    /*
     * Clear the various flags by writing 1 to them.
     */
    pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE |
                                       AC97GSR_READ_COMPLETION_STATUS;

    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkWrite
 *
 * Writes the value to the given register.
 * 
 * Note: to clear GPIOs configured as interrupt sources (i.e. inputs held high
 * by the sticky bit), use WM97PlatformClearGPIOs instead.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *      reg                 register to write to
 *      value               value to write
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkWrite( WM_DEVICE_HANDLE hDevice,
                                WM_REGTYPE reg,
                                WM_REGVAL value
                              )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status;

    /*
     * Parameter validation.
     */
    if ( reg > WM97_MAX_REGISTER )
    {
        status = WMS_REG_NOT_PRESENT;
        goto error;
    }

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

    {
        unsigned int                pCodecAddr;
        volatile unsigned int       *regAddr;

        /*
         * Just to make things complicated, the WM97_GPIO_PIN_STATUS is better
         * supported through the modem codec registers than the audio codec
         * registers, and is cached on the controller, so we don't need to
         * wait for a write to complete.
         */
        if ( WM97_GPIO_PIN_STATUS == reg )
        {
            WM_REGVAL slotValue;
            unsigned int pModemAddr;

            /*
             * Find the right bank of registers.
             */
            if ( (WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID)
                 && !IS_WM9712_FAMILY( hDevice )
               )
            {
                pModemAddr = PRIMARY_MODEM_REGS( pDeviceContext );
            }
            else
            {
                pModemAddr = SECONDARY_MODEM_REGS( pDeviceContext );
            }
            regAddr = (volatile unsigned int *) (pModemAddr + (reg << 1));

            /*
             * We need to write to the modem space to set the appropriate bits
             * in slot 12.
             */
            if ( IS_WM9712_FAMILY( hDevice ) )
                slotValue = value << 1;
            else
                slotValue = value;

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

#if WM_CPU_PXA27X
            /*
             * On PXA27x silicon after A1 we now need to wait at least 2 frames
             * otherwise the controller will hang.  2 frames = approx 42us.  Round
             * this up to 50us.
             */
            MicroSleep( hDevice, 50 );
#endif /* WM_CPU_PXA27X */
            
            /*
             * We're done.  NB: This will not clear sticky bits on the WM9712!
             * Use WM97PlatformClearGPIOs instead.
             */
            goto done;
        }

        /*
         * Find the right bank of registers.
         */
        if ( WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID )
            pCodecAddr = PRIMARY_CODEC_REGS( pDeviceContext );
        else
            pCodecAddr = SECONDARY_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 + (reg << 1));

        /*

⌨️ 快捷键说明

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