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

📄 wmxscale2wire.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
字号:
/*-----------------------------------------------------------------------------
 * Copyright (c) Wolfson Microelectronics plc.  All rights reserved.
 *
 * This software as well as any related documentation is furnished under 
 * license and may only be used or copied in accordance with the terms of the 
 * license. The information in this file is furnished for informational use 
 * only, is subject to change without notice, and should not be construed as 
 * a commitment by Wolfson Microelectronics plc. Wolfson Microelectronics plc
 * assumes no responsibility or liability for any errors or inaccuracies that
 * may appear in this document or any software that may be provided in
 * association with this document. 
 *
 * Except as permitted by such license, no part of this document may be 
 * reproduced, stored in a retrieval system, or transmitted in any form or by 
 * any means without the express written consent of Wolfson Microelectronics plc. 
 *
 * $Id: WMXScale2Wire.c 2326 2005-10-20 08:40:38Z ib $
 *
 * Functionality for configuring and using XScale I2C controller.
 *
 * Warning:
 *  This driver is specifically written for Wolfson Codecs. It is not a 
 *  general CODEC device driver.
 *
 *---------------------------------------------------------------------------*/

/*
 * Include files
 */
#include "WMCommon.h"
#include "WMDevice.h"
#include "WMControlLink.h"
#include "WMPlatformDeviceContext.h"
#include "WMPlatform2Wire.h"
#include "Test/WMTestCommon.h"
#include "Test/WMInternalTests.h"

#if XLLP_AVAILABLE
#include <xllp_clkmgr.h>
#endif /* XLLP_AVAILABLE */

#if WM_I2S

/*
 * Global definitions
 */
#define WRITE_TIMEOUT       65535

/*
 * Function prototypes
 */
static WMSTATUS private_2WireWriteByte( WM_DEVICE_HANDLE hDevice,
                                        unsigned char value,
                                        WM_BOOL isStart,
                                        WM_BOOL isEnd
                                      );

/*-----------------------------------------------------------------------------
 * Function:    WMPlatform2WireInit
 *
 * Initialise the XScale I2C controller.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatform2WireInit( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                     status;

    /*
     * Check our internals code.
     */
    WMTEST_RUN( WMTestPlatformInternals( hDevice ) );
    
    /*
     * Enable the I2C Clock.
     */
    pDeviceContext->v_pClkRegs->cken |= XLLP_CLKEN_I2C;

	if ( ! ( pDeviceContext->v_pClkRegs->cken & XLLP_CLKEN_I2C ) )
	{
        WM_TRACE( hDevice, ( "WMPlatform2WireInit: Could not enable I2C clock" ));
		status = WMS_CODEC_NOT_READY;
		goto error0;
	}

	/*
	 * Set up the I2C GPIOs.
	 */
	pDeviceContext->v_pGPIORegs->GPDR3 |= XLLP_GPIO_BIT_SCL;
	pDeviceContext->v_pGPIORegs->GPDR3 &= ~XLLP_GPIO_BIT_SDA;
	pDeviceContext->v_pGPIORegs->GAFR3_U |= XLLP_GPIO_AF_BIT_SCL | 
		                                    XLLP_GPIO_AF_BIT_SDA;

	/*
	 * Setup the I2C slave address with a dummy value to check that 
	 * it's working.
	 */
	pDeviceContext->v_pI2CRegs->ISAR = 0;
	if ( 0 != pDeviceContext->v_pI2CRegs->ISAR )
	{
        WM_TRACE( hDevice, ( "WMPlatform2WireInit: Could not enable I2C controller" ));
		status = WMS_CODEC_NOT_READY;
		goto error0;
	}

	/*
	 * Enable the I2C interface and make it master the clock.
	 */
	pDeviceContext->v_pI2CRegs->ICR = XLLP_ICR_UIE | XLLP_ICR_SCLEA;

    /*
     * Try to read the device ID to make sure we can talk to the codec.
     */
    status = WMInitDeviceId( hDevice );
    if ( WMS_UNSUPPORTED == status )
    {
        WM_REGVAL regVal = 0xFFFF;

        /*
         * If reading the device ID is unsupported, it's probably a write-only
         * codec. Try writing to a nonexistent register 
		 * (WM_I2S_INIT_TEST_REGISTER) to see if we get a response to that.
		 * Note - We are assuming that all our 2 wire devices do not have 
		 *        register WM_I2S_INIT_TEST_REGISTER.
         *
		 *      - For Write-only devices: All reads MUST use cached values, 
		 *        so we are allowed to do the read below.
         *
		 *      - WM_I2S_INIT_TEST_REGISTER is used because a write to set the 
		 *        device's register back to its original value would cause
		 *        a real register in the generic drivers to have non-default
		 *        value as the default values are unknown.
		 */

        /* 
		 * Attempt to read back the original value [in case the register exists] 
		 * so that we can write it back again.
		 */
        status = WMRead( hDevice, WM_I2S_INIT_TEST_REGISTER, &regVal );
        if ( WM_ERROR( status ) )
        {
            /* Make sure we've got a value for regVal */
            regVal = 0xFFFF;
        }

        status = WMWrite( hDevice, WM_I2S_INIT_TEST_REGISTER, regVal );
    }
    if ( WM_ERROR( status ) && WMS_UNSUPPORTED != status )
    {
        /*
         * If both the above failed, assume we can't talk to the device.
         */
        WM_TRACE( hDevice, ( "WMPlatform2WireInit: no response from codec" ));
        status = WMS_CODEC_NOT_READY;
        goto error1;
    }
    
    /*
     * It worked.
     */
    pDeviceContext->flags |= DEVICE_INITIALISED;
    return WMS_SUCCESS;

    /*
     * Error cleanup.
     */
error1:
    WMPlatform2WireShutdown( hDevice );
    
error0:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatform2WireShutdown
 *
 * Shutdown the XScale I2C controller.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *
 * Returns:     void
 *
 *---------------------------------------------------------------------------*/
void WMPlatform2WireShutdown( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
	/*
	 * Disable the I2C interface.
	 */
	pDeviceContext->v_pI2CRegs->ICR &= ~ ( XLLP_ICR_UIE | XLLP_ICR_SCLEA );

    /*
     * Disable the I2C Clock.
     */
    pDeviceContext->v_pClkRegs->cken &= ~XLLP_CLKEN_I2C;
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatform2WireWrite
 *
 * Writes some bytes to the device across the 2-wire interface.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      address     2-wire device address
 *      data        data to write
 *      length      data length in bytes
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatform2WireWrite( WM_DEVICE_HANDLE hDevice,
                               unsigned char address,
                               unsigned char *data,
                               unsigned int length
                             )
{
    WMSTATUS        status;
    unsigned int    byte;
    
    /*
     * Send the address.
     */
    status = private_2WireWriteByte( hDevice, 
                                     address,
                                     TRUE,            /* start */
                                     (0 == length)    /* end */
                                   );
    if ( WM_ERROR( status ) )
    {
        goto error;
    }

    /* 
     * Now send each byte.
     */
    for ( byte = 0; byte < length; byte++ )
    {
        WM_BOOL isEnd = (length-1 == byte);
        
        status = private_2WireWriteByte( hDevice, 
                                         data[byte],
                                         FALSE,   /* start */
                                         isEnd    /* end */
                                       );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }
    }

    /*
     * We're done.
     */    
    return WMS_SUCCESS;
    
error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    private_2WireWriteByte
 *
 * Writes a byte to the device across the 2-wire interface.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      value       byte to write
 *      isStart     if this is the first byte of the write
 *      isEnd       if this is the last byte of the write
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_2WireWriteByte( WM_DEVICE_HANDLE hDevice,
                                        unsigned char value,
                                        WM_BOOL isStart,
                                        WM_BOOL isEnd
                                      )
{
    WMSTATUS    status;
    int         icr;
    int         timeout = 0;
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    
    if ( isStart )
    {
        /*
         * We're master so set slave address to 0.
         */
        pDeviceContext->v_pI2CRegs->ISAR = 0x0;
        
        /*
         * Make sure everything's clear before we start.
         */
        pDeviceContext->v_pI2CRegs->ICR = 0;
    }
    
    /*
     * Prepare the byte value.
     */
    pDeviceContext->v_pI2CRegs->IDBR = value;
    
    /*
     * And do the write.
     */
    icr = XLLP_ICR_UIE | XLLP_ICR_SCLEA | XLLP_ICR_TB;
    if ( isStart )
        icr |= XLLP_ICR_START;
    else
        icr &= ~XLLP_ICR_START;
    
    if ( isEnd )
        icr |= XLLP_ICR_STOP;
    else
        icr &= ~XLLP_ICR_STOP;
        
    pDeviceContext->v_pI2CRegs->ICR = icr;
    
    /*
     * Wait for it to finish.
     */
    while ( !( pDeviceContext->v_pI2CRegs->ISR & XLLP_ISR_ITE ) )
    {
        if ( WRITE_TIMEOUT < ++timeout )
        {
            status = WMS_DATA_TIMED_OUT;
            goto error;
        }
    }

    /*
     * And clear the transmit-end flag.
     */
    pDeviceContext->v_pI2CRegs->ISR |= XLLP_ISR_ITE;
    
    /*
     * We're done.
     */
    return WMS_SUCCESS;
    
error:
    return status;
}
#endif /* WM_I2S */

/*------------------------------ END OF FILE ---------------------------------*/

⌨️ 快捷键说明

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