From e6d87036412b952cb083eff2dc716aee97a771f2 Mon Sep 17 00:00:00 2001 From: Roman Yeryomin Date: Fri, 17 May 2013 20:40:24 +0300 Subject: Move to rsdk 3.2.4. Compiles cleanly. Signed-off-by: Roman Yeryomin --- target/linux/realtek/files/drivers/serial/gpio.h | 11 + .../realtek/files/drivers/serial/gpio_8972d.c | 483 +++++++++++++++++++++ .../realtek/files/drivers/serial/gpio_8972d.h | 93 ++++ .../realtek/files/drivers/serial/gpio_8972d_v100.h | 37 ++ target/linux/realtek/files/drivers/serial/i2c.c | 8 + .../realtek/files/drivers/serial/i2c_alc5628.c | 344 +++++++++++++++ 6 files changed, 976 insertions(+) create mode 100644 target/linux/realtek/files/drivers/serial/gpio_8972d.c create mode 100644 target/linux/realtek/files/drivers/serial/gpio_8972d.h create mode 100644 target/linux/realtek/files/drivers/serial/gpio_8972d_v100.h create mode 100644 target/linux/realtek/files/drivers/serial/i2c_alc5628.c (limited to 'target/linux/realtek/files/drivers/serial') diff --git a/target/linux/realtek/files/drivers/serial/gpio.h b/target/linux/realtek/files/drivers/serial/gpio.h index 39019c669..6029894df 100644 --- a/target/linux/realtek/files/drivers/serial/gpio.h +++ b/target/linux/realtek/files/drivers/serial/gpio.h @@ -33,6 +33,8 @@ #include "gpio_8952.h" #elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8972B_FAMILY) #include "gpio_8972b.h" +#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM89xxD) +#include "gpio_8972d.h" #else #error "unknown gpio driver" #endif @@ -89,10 +91,19 @@ #define RTK_GPIO_GET(pid, pData) _rtl8972B_getGpioDataBit(pid, pData) #define RTK_GPIO_SET(pid, data) _rtl8972B_setGpioDataBit(pid, data) +#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM89xxD) +#define RTK_GPIO_INIT(pid, dedicate, dir, interrupt) _rtl8972D_initGpioPin(pid, dedicate, dir, interrupt) +#define RTK_GPIO_GET(pid, pData) _rtl8972D_getGpioDataBit(pid, pData) +#define RTK_GPIO_SET(pid, data) _rtl8972D_setGpioDataBit(pid, data) #else #error "unknown gpio driver" #endif +// define generic naming for kernel's driver +#define _rtl_generic_initGpioPin(pid, dedicate, dir, interrupt) RTK_GPIO_INIT(pid, dedicate, dir, interrupt) +#define _rtl_generic_getGpioDataBit(pid, pData) RTK_GPIO_GET(pid, pData) +#define _rtl_generic_setGpioDataBit(pid, data) RTK_GPIO_SET(pid, data) + extern int gpio_debug; #endif/*__GPIO__*/ diff --git a/target/linux/realtek/files/drivers/serial/gpio_8972d.c b/target/linux/realtek/files/drivers/serial/gpio_8972d.c new file mode 100644 index 000000000..da3f11e3d --- /dev/null +++ b/target/linux/realtek/files/drivers/serial/gpio_8972d.c @@ -0,0 +1,483 @@ +/* +* Copyright c Realtek Semiconductor Corporation, 2009 +* All rights reserved. +* +* Program : GPIO Driver +* Abstract : +* Author : +*/ + +#include +#include +//#include "voip_init.h" +#include "gpio.h" + +/*==================== FOR RTL89xxD ==================*/ + +#ifdef CONFIG_RTK_VOIP_DRIVERS_PCM89xxD + +enum GPIO_FUNC +{ + GPIO_FUNC_DEDICATE, + + GPIO_FUNC_DIRECTION, + GPIO_FUNC_DATA, + GPIO_FUNC_INTERRUPT_STATUS, + GPIO_FUNC_INTERRUPT_ENABLE, + GPIO_FUNC_MAX, +}; + +//******************************************* GPIO control +static uint32 regGpioControl[] = +{ + GPABCDCNR, /* Port A */ + GPABCDCNR, /* Port B */ + GPABCDCNR, /* Port C */ + GPABCDCNR, /* Port D */ + GPEFGHCNR, /* Port E */ + GPEFGHCNR, /* Port F */ + GPEFGHCNR, /* Port G */ + GPEFGHCNR, /* Port H */ +}; + +static uint32 bitStartGpioControl[] = +{ + 0, /* Port A */ + 8, /* Port B */ + 16, /* Port C */ + 24, /* Port D */ + 0, /* Port E */ + 8, /* Port F */ + 16, /* Port G */ + 24, /* Port H */ +}; + +//******************************************* GPIO Share pin config + +#define SHAREPIN_REGISTER 0xB8000040 +#define SET_BIT(x) (1<> (pin*2+bitStartGpioInterruptEnable[port]) ) & (uint32)0x3; + break; + + case GPIO_FUNC_INTERRUPT_STATUS: + GPIO_PRINT(5, "[%s():%d] regGpioInterruptStatus[port]=0x%08x bitStartGpioInterruptEnable[port]=%d\n", __FUNCTION__, __LINE__, regGpioInterruptStatus[port], bitStartGpioInterruptStatus[port] ); + + if ( REG32(regGpioInterruptStatus[port]) & ( (uint32)1 << (pin+bitStartGpioInterruptStatus[port]) ) ) + return 1; + else + return 0; + break; + + case GPIO_FUNC_MAX: + printk("Wrong GPIO function\n"); + break; + } + return 0xffffffff; +} + + +/* +@func int32 | _setGpio | abstract GPIO registers +@parm enum GPIO_FUNC | func | control/data/interrupt register +@parm enum GPIO_PORT | port | GPIO port +@parm uint32 | pin | pin number +@parm uint32 | data | value +@rvalue NONE +@comm +This function is for internal use only. You don't need to care what register address of GPIO is. +This function abstracts these information. +*/ +static inline void _setGpio( enum GPIO_FUNC func, enum GPIO_PORT port, uint32 pin, uint32 data ) +{ + + GPIO_PRINT(4, "[%s():%d] func=%d port=%d pin=%d data=%d\n", __FUNCTION__, __LINE__, func, port, pin, data ); + switch( func ) + { + case GPIO_FUNC_DEDICATE: + GPIO_PRINT(5, "[%s():%d] regGpioControl[port]=0x%08x bitStartGpioControl[port]=%d\n", __FUNCTION__, __LINE__, regGpioControl[port], bitStartGpioControl[port] ); + + if ( data ) + REG32(regGpioControl[port]) |= (uint32)1 << (pin+bitStartGpioControl[port]); + else { + REG32(regGpioControl[port]) &= ~((uint32)1 << (pin+bitStartGpioControl[port])); + //printk("oldsharepin_register= %x, %x", REG32(SHAREPIN_REGISTER), REG32(SHAREPIN_REGISTER+4)); + REG32(SHAREPIN_REGISTER) = (REG32(SHAREPIN_REGISTER) &(~GpioShare_setting[(port<<3)|pin][0].mask))|GpioShare_setting[(port<<3)|pin][0].value; + //REG32(SHAREPIN_REGISTER) |= GpioShare_setting[(port<<3)|pin][0].value; + REG32(SHAREPIN_REGISTER+4)= (REG32(SHAREPIN_REGISTER+4) &(~GpioShare_setting[(port<<3)|pin][1].mask))|GpioShare_setting[(port<<3)|pin][1].value; + //REG32(SHAREPIN_REGISTER+4) |= GpioShare_setting[(port<<3)|pin][1].value; + //printk("newsharepin_register= %x, %x", REG32(SHAREPIN_REGISTER), REG32(SHAREPIN_REGISTER+4)); + //GPIO_PRINT(5,"GPIOSET(%x)",(port<<3)|pin); + //printk("[%d,%d]GPIOSET(%x)", port, pin,(port<<3)|pin); + } + break; + + case GPIO_FUNC_DIRECTION: + GPIO_PRINT(5, "[%s():%d] regGpioDirection[port]=0x%08x bitStartGpioDirection[port]=%d\n", __FUNCTION__, __LINE__, regGpioDirection[port], bitStartGpioDirection[port] ); + + if ( data ) + REG32(regGpioDirection[port]) |= (uint32)1 << (pin+bitStartGpioDirection[port]); + else + REG32(regGpioDirection[port]) &= ~((uint32)1 << (pin+bitStartGpioDirection[port])); + break; + + case GPIO_FUNC_DATA: + GPIO_PRINT(5, "[%s():%d] regGpioData[port]=0x%08x bitStartGpioData[port]=%d\n", __FUNCTION__, __LINE__, regGpioData[port], bitStartGpioData[port] ); + + if ( data ) + REG32(regGpioData[port]) |= (uint32)1 << (pin+bitStartGpioData[port]); + else + REG32(regGpioData[port]) &= ~((uint32)1 << (pin+bitStartGpioData[port])); + break; + + case GPIO_FUNC_INTERRUPT_ENABLE: + GPIO_PRINT(5, "[%s():%d] regGpioInterruptEnable[port]=0x%08x bitStartGpioInterruptEnable[port]=%d\n", __FUNCTION__, __LINE__, regGpioInterruptEnable[port], bitStartGpioInterruptEnable[port] ); + + REG32(regGpioInterruptEnable[port]) &= ~((uint32)0x3 << (pin*2+bitStartGpioInterruptEnable[port])); + REG32(regGpioInterruptEnable[port]) |= (uint32)data << (pin*2+bitStartGpioInterruptEnable[port]); + break; + + case GPIO_FUNC_INTERRUPT_STATUS: + GPIO_PRINT(5, "[%s():%d] regGpioInterruptStatus[port]=0x%08x bitStartGpioInterruptStatus[port]=%d\n", __FUNCTION__, __LINE__, regGpioInterruptStatus[port], bitStartGpioInterruptStatus[port] ); + + if ( data ) + REG32(regGpioInterruptStatus[port]) |= (uint32)1 << (pin+bitStartGpioInterruptStatus[port]); + else + REG32(regGpioInterruptStatus[port]) &= ~((uint32)1 << (pin+bitStartGpioInterruptStatus[port])); + break; + + case GPIO_FUNC_MAX: + printk("Wrong GPIO function\n"); + break; + } +} + +/* +@func int32 | _rtl8972D_initGpioPin | Initiate a specifed GPIO port. +@parm uint32 | gpioId | The GPIO port that will be configured +@parm enum GPIO_PERIPHERAL | dedicate | Dedicated peripheral type +@parm enum GPIO_DIRECTION | direction | Data direction, in or out +@parm enum GPIO_INTERRUPT_TYPE | interruptEnable | Interrupt mode +@rvalue SUCCESS | success. +@rvalue FAILED | failed. Parameter error. +@comm +This function is used to initialize GPIO port. +*/ +int32 _rtl8972D_initGpioPin( uint32 gpioId, enum GPIO_CONTROL dedicate, + enum GPIO_DIRECTION direction, + enum GPIO_INTERRUPT_TYPE interruptEnable ) +{ + uint32 port = GPIO_PORT( gpioId ); + uint32 pin = GPIO_PIN( gpioId ); + + + if ( port >= GPIO_PORT_MAX ) return FAILED; + if ( pin >= 8 ) return FAILED; + + switch ( dedicate ) + { + case GPIO_CONT_GPIO: + _setGpio( GPIO_FUNC_DEDICATE, port, pin, 0 ); + break; + case GPIO_CONT_PERI: + _setGpio( GPIO_FUNC_DEDICATE, port, pin, 1 ); + break; + } + + _setGpio( GPIO_FUNC_DIRECTION, port, pin, direction ); + + _setGpio( GPIO_FUNC_INTERRUPT_ENABLE, port, pin, interruptEnable ); + + return SUCCESS; +} + +/* +@func int32 | _rtl8972D_getGpioDataBit | Get the bit value of a specified GPIO ID. +@parm uint32 | gpioId | GPIO ID +@parm uint32* | data | Pointer to store return value +@rvalue SUCCESS | success. +@rvalue FAILED | failed. Parameter error. +@comm +*/ +int32 _rtl8972D_getGpioDataBit( uint32 gpioId, uint32* pData ) +{ + uint32 port = GPIO_PORT( gpioId ); + uint32 pin = GPIO_PIN( gpioId ); + + if ( port >= GPIO_PORT_MAX ) return FAILED; + if ( pin >= 8 ) return FAILED; + if ( pData == NULL ) return FAILED; + + *pData = _getGpio( GPIO_FUNC_DATA, port, pin ); + GPIO_PRINT(3, "[%s():%d] (port=%d,pin=%d)=%d\n", __FUNCTION__, __LINE__, port, pin, *pData ); + return SUCCESS; +} + +/* +@func int32 | _rtl8972D_setGpioDataBit | Set the bit value of a specified GPIO ID. +@parm uint32 | gpioId | GPIO ID +@parm uint32 | data | Data to write +@rvalue SUCCESS | success. +@rvalue FAILED | failed. Parameter error. +@comm +*/ +int32 _rtl8972D_setGpioDataBit( uint32 gpioId, uint32 data ) +{ + uint32 port = GPIO_PORT( gpioId ); + uint32 pin = GPIO_PIN( gpioId ); + + if ( port >= GPIO_PORT_MAX ) return FAILED; + if ( pin >= 8 ) return FAILED; + + GPIO_PRINT(3, "[%s():%d] (port=%d,pin=%d)=%d\n", __FUNCTION__, __LINE__, port, pin, data ); + _setGpio( GPIO_FUNC_DATA, port, pin, data ); + return SUCCESS; +} + +/* +@func uint32 | _init_GpioShare_setting | init rtl 8972D revision GPIO registers +@rvalue int | val | 0:success; otherwise fail +@comm +init rtl 8972D GPIO registers in GpioShare_setting table +default value is used for rtl 8972D revision B +*/ +//int __init _init_GpioShare_setting( void ) +//{ +// return 0; +//} + +//voip_initcall(_init_GpioShare_setting); + +#endif //CONFIG_RTK_VOIP_DRIVERS_PCM89xxD + diff --git a/target/linux/realtek/files/drivers/serial/gpio_8972d.h b/target/linux/realtek/files/drivers/serial/gpio_8972d.h new file mode 100644 index 000000000..92ddfc86b --- /dev/null +++ b/target/linux/realtek/files/drivers/serial/gpio_8972d.h @@ -0,0 +1,93 @@ +/* +* Copyright c Realtek Semiconductor Corporation, 2009 +* All rights reserved. +* +* Program : GPIO Header File +* Abstract : +* Author : +* +*/ + + +#ifndef __GPIO_8972D_H__ +#define __GPIO_8972D_H__ + +/* For 8954C V100 EV Board */ +#if defined (CONFIG_RTK_VOIP_GPIO_8972D_V100) +#include "gpio_8972d_v100.h" +#endif + +#ifdef CONFIG_RTK_VOIP_DRIVERS_PCM89xxD + +/******** GPIO define ********/ + +/* define GPIO port */ +enum GPIO_PORT +{ + GPIO_PORT_A = 0, + GPIO_PORT_B, + GPIO_PORT_C, + GPIO_PORT_D, + GPIO_PORT_E, + GPIO_PORT_F, + GPIO_PORT_G, + GPIO_PORT_H, + GPIO_PORT_MAX, + GPIO_PORT_UNDEF, +}; + +/* define GPIO control pin */ +enum GPIO_CONTROL +{ + GPIO_CONT_GPIO = 0, + GPIO_CONT_PERI = 0x1, +}; + +/* define GPIO direction */ +enum GPIO_DIRECTION +{ + GPIO_DIR_IN = 0, + GPIO_DIR_OUT =1, +}; + +/* define GPIO Interrupt Type */ +enum GPIO_INTERRUPT_TYPE +{ + GPIO_INT_DISABLE = 0, + GPIO_INT_FALLING_EDGE, + GPIO_INT_RISING_EDGE, + GPIO_INT_BOTH_EDGE, +}; + +/*************** Define RTL8954C Family GPIO Register Set ************************/ +#define GPABCDCNR 0xB8003500 + +#define GPABCDDIR 0xB8003508 +#define GPABCDDATA 0xB800350C +#define GPABCDISR 0xB8003510 +#define GPABIMR 0xB8003514 +#define GPCDIMR 0xB8003518 +#define GPEFGHCNR 0xB800351C + +#define GPEFGHDIR 0xB8003524 +#define GPEFGHDATA 0xB8003528 +#define GPEFGHISR 0xB800352C +#define GPEFIMR 0xB8003530 +#define GPGHIMR 0xB8003534 +/**************************************************************************/ +/* Register access macro (REG*()).*/ +#define REG32(reg) (*((volatile uint32 *)(reg))) +#define REG16(reg) (*((volatile uint16 *)(reg))) +#define REG8(reg) (*((volatile uint8 *)(reg))) + +/********************* Function Prototype in gpio.c ***********************/ +int32 _rtl8972D_initGpioPin(uint32 gpioId, enum GPIO_CONTROL dedicate, + enum GPIO_DIRECTION, + enum GPIO_INTERRUPT_TYPE interruptEnable ); +int32 _rtl8972D_getGpioDataBit( uint32 gpioId, uint32* pData ); +int32 _rtl8972D_setGpioDataBit( uint32 gpioId, uint32 data ); + +#endif /* CONFIG_RTK_VOIP_DRIVERS_PCM89xxD */ + +#endif /* __GPIO_8972D_H__ */ + diff --git a/target/linux/realtek/files/drivers/serial/gpio_8972d_v100.h b/target/linux/realtek/files/drivers/serial/gpio_8972d_v100.h new file mode 100644 index 000000000..314085e92 --- /dev/null +++ b/target/linux/realtek/files/drivers/serial/gpio_8972d_v100.h @@ -0,0 +1,37 @@ +/* +* Copyright c Realtek Semiconductor Corporation, 2009 +* All rights reserved. +* +* Program : 8972D V100 GPIO Header File +* Abstract : +* Author : +* +*/ + +#ifndef __GPIO_8972D_V100_H__ +#define __GPIO_8972D_V100_H__ + +////// For 8972D V100 ATA SLIC ///// +#if defined(CONFIG_RTK_VOIP_DRIVERS_ATA_SLIC) + +#define GPIO "ATA" +#define PIN_RESET1 GPIO_ID(GPIO_PORT_G,0) //output +//#define PIN_RESET2 GPIO_ID(GPIO_PORT_D,6) //output + +#define PIN_CS1 GPIO_ID(GPIO_PORT_B,7) //output +#define PIN_CS2 GPIO_ID(GPIO_PORT_C,0) //output + +#define PIN_CLK GPIO_ID(GPIO_PORT_C,4) //output +#define PIN_DI GPIO_ID(GPIO_PORT_C,5) //input +#define PIN_DO GPIO_ID(GPIO_PORT_A,1) //output + +/* LED */ +/* V100 use below GPIO as SLIC CS */ +#define PIN_VOIP0_LED GPIO_ID(GPIO_PORT_G,5) +#define PIN_VOIP1_LED GPIO_ID(GPIO_PORT_G,6) + +#endif //CONFIG_RTK_VOIP_DRIVERS_ATA_SLIC + + +#endif /* __GPIO_8972D_V100_H__ */ + diff --git a/target/linux/realtek/files/drivers/serial/i2c.c b/target/linux/realtek/files/drivers/serial/i2c.c index 42fdebd03..1c4a7d00e 100644 --- a/target/linux/realtek/files/drivers/serial/i2c.c +++ b/target/linux/realtek/files/drivers/serial/i2c.c @@ -45,11 +45,17 @@ #endif #elif defined(CONFIG_SERIAL_SC16IS7X0) #define I2C_RATING_FACTOR 1 +#elif defined(CONFIG_SND_RTL8197D_SOC_ALC5628) +#define I2C_RATING_FACTOR 10 #endif #ifdef __kernel_used__ // pkshih: If we use udelay, factor 1 should be work, doesn't it? #undef I2C_RATING_FACTOR + #ifdef CONFIG_SND_RTL8197D_SOC_ALC5628 + #define I2C_RATING_FACTOR 10 + #else #define I2C_RATING_FACTOR 1 + #endif #endif /************************* I2C read/write function ************************/ @@ -285,7 +291,9 @@ void i2c_init_SCL_SDA(i2c_dev_t* pI2C_Dev) __i2c_setGpioDataBit( pI2C_Dev->sclk, 1 ); __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE); __i2c_setGpioDataBit( pI2C_Dev->sdio, 1 ); +#if !defined(CONFIG_SND_RTL8197D_SOC_ALC5628) __i2c_setGpioDataBit( pI2C_Dev->reset, 1); +#endif } void i2c_enable_irq(i2c_dev_t* pI2C_Dev) diff --git a/target/linux/realtek/files/drivers/serial/i2c_alc5628.c b/target/linux/realtek/files/drivers/serial/i2c_alc5628.c new file mode 100644 index 000000000..6568ff791 --- /dev/null +++ b/target/linux/realtek/files/drivers/serial/i2c_alc5628.c @@ -0,0 +1,344 @@ +#ifndef __BOOTCODE__ +#include +#include +#include +#include // GPIO_ABCD_IRQ, PABCD_ISR +#include +#endif + +#ifdef __BOOTCODE__ +#define ENODEV 19 /* No such device */ +#define __init +#endif + +#if defined( LINUX_VERSION_CODE ) && (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,30)) +#define LINUX_KERNEL_VERSION_2_6_30 1 +#endif + +#ifdef LINUX_KERNEL_VERSION_2_6_30 +#include "bspchip.h" // BSP_GPIO_EFGH_IRQ +#endif + + +// ------------------------------------------------------------------ +// ------------------------------------------------------------------ +// Basic setup information + + +// ------------------------------------------------------------------ +// ------------------------------------------------------------------ +// I2C level function + +#ifndef __BOOTCODE__ +#include "i2c.h" +#else +#include "i2c.h" +#endif + +#define I2C_GPIO_ID( port, pin ) ( ( ( port - 'A' ) << 16 ) | ( pin ) ) + +#ifdef CONFIG_SND_RTL8197D_SOC_ALC5628 +#define ALC5628_SCL I2C_GPIO_ID( 'G', 4 ) // SCL = G4 +#define ALC5628_SDA I2C_GPIO_ID( 'G', 6 ) // SDA = G6 +#endif + +#define ALC5628_I2C_ADDR 0x30 +#define ALC5628_I2C_WRITE 0x00 +#define ALC5628_I2C_READ 0x01 + +static i2c_dev_t alc5628_i2c_dev = { + .sclk = ALC5628_SCL, + .sdio = ALC5628_SDA, +}; + +// Register address byte +// 7 : not used +// 6~3: A[3:0] UART's internal register select +// 2~1: channel select: CH1 = 0?!, CH0 = 0 +// 0 : not used +#define MK_SC16IS7X0_REG_ADDR( uart_reg ) ( ( uart_reg & 0x0F ) << 3 ) + +unsigned int serial_in_i2c(unsigned int addr, int offset) +{ + unsigned short int data_hibyte=0; + unsigned short int data_lowbyte=0; + unsigned short int data; + + //printk( "serial_in_i2c(%X):%X\n", addr, offset ); + + if( addr != ALC5628_I2C_ADDR ) + return 0; + + // start + i2c_start_condition( &alc5628_i2c_dev ); + + // addr + write + i2c_serial_write_byte( &alc5628_i2c_dev, ALC5628_I2C_ADDR | + ALC5628_I2C_WRITE ); + + // read ACK + if( i2c_ACK( &alc5628_i2c_dev ) != 0 ) + return 0; + + // write register address + i2c_serial_write_byte( &alc5628_i2c_dev, offset ); + + // read ACK + if( i2c_ACK( &alc5628_i2c_dev ) != 0 ) + return 0; + + // start + i2c_start_condition( &alc5628_i2c_dev ); + + // addr + read + i2c_serial_write_byte( &alc5628_i2c_dev, ALC5628_I2C_ADDR | + ALC5628_I2C_READ ); + + // read ACK + if( i2c_ACK( &alc5628_i2c_dev ) != 0 ) + return 0; + + // read data_hibyte + i2c_serial_read( &alc5628_i2c_dev, &data_hibyte ); + + //write ACK + i2c_ACK_w(&alc5628_i2c_dev, 0); + + // read data_lowbyte + i2c_serial_read( &alc5628_i2c_dev, &data_lowbyte ); + + data = (data_hibyte<<8) | data_lowbyte; + + // write negative-ACK + i2c_ACK_w( &alc5628_i2c_dev, 1 ); + + // stop + i2c_stop_condition( &alc5628_i2c_dev ); + + //printk( "in[%X]\n", data ); + + return data; +} +EXPORT_SYMBOL_GPL(serial_in_i2c); + +unsigned int serial_out_i2c(unsigned int addr, int offset, int value) +{ + //printk( "serial_out_i2c(%X):%X,%X\n", addr, offset, value ); + unsigned short int data_hibyte; + unsigned short int data_lowbyte; + + data_hibyte =(unsigned char) (value>>8); + data_lowbyte =(unsigned char) (value & 0xff); + + if( addr != ALC5628_I2C_ADDR ) + return 0; + //printk("(%d)", __LINE__); + // start + i2c_start_condition( &alc5628_i2c_dev ); + + // addr + write + i2c_serial_write_byte( &alc5628_i2c_dev, ALC5628_I2C_ADDR | ALC5628_I2C_WRITE ); + + // read ACK + if( i2c_ACK( &alc5628_i2c_dev ) != 0 ) + return 0; + //printk("(%d)", __LINE__); + // write register address + i2c_serial_write_byte( &alc5628_i2c_dev, offset ); + + // read ACK + if( i2c_ACK( &alc5628_i2c_dev ) != 0 ) + return 0; + //printk("(%d)", __LINE__); + // write data hibyte + i2c_serial_write_byte( &alc5628_i2c_dev, data_hibyte ); + + // read ACK + if( i2c_ACK( &alc5628_i2c_dev ) != 0 ) + return 0; + //printk("(%d)", __LINE__); + // write data lowbyte + i2c_serial_write_byte( &alc5628_i2c_dev, data_lowbyte ); + + // read ACK + if( i2c_ACK( &alc5628_i2c_dev ) != 0 ) + return 0; + //printk("(%d)", __LINE__); + // stop + i2c_stop_condition( &alc5628_i2c_dev ); + + return 0; +} +EXPORT_SYMBOL_GPL(serial_out_i2c); + +static void __init alc5628_init_i2c( void ) +{ + int temp; + // init SCL / SDA + i2c_init_SCL_SDA( &alc5628_i2c_dev ); + + serial_in_i2c( ALC5628_I2C_ADDR, 0 ); // avoid NO ACK at first time access + + serial_out_i2c( ALC5628_I2C_ADDR, 0x0, 0x707 ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x0, 0x707 ); + + serial_in_i2c( ALC5628_I2C_ADDR, 0 ); + serial_in_i2c( ALC5628_I2C_ADDR, 0 ); + + +// enable playback + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3E ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x3E, (temp) | 0x8000 ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3C ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x3C, (temp) | 0x2000 ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3C ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x3C, (temp) | 0x7F0 ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3A ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x3A, (temp) | 0x8030 ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3E ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x3E, (temp) | 0x600 ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x0C ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x0C, (temp&(~0xBFBF)) | 0x1010 ); + + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x1C ); + serial_out_i2c( ALC5628_I2C_ADDR, 0x1C, (temp) | 0x300 ); + +// temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x0C ); +// serial_out_i2c( ALC5628_I2C_ADDR, 0x0C, (temp&(~0xBFBF)) | 0x1010 ); + + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0 ); + //printk("reg0=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x2 ); + //printk("reg2=%x\n", temp); + + serial_out_i2c( ALC5628_I2C_ADDR, 0x2, 0x0 ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x2 ); + //printk("reg2=%x\n", temp); + + serial_out_i2c( ALC5628_I2C_ADDR, 0x2, 0xFFFF ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x2 ); + //printk("reg2=%x\n", temp); + + + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x4 ); + //printk("reg4=%x\n", temp); + + serial_out_i2c( ALC5628_I2C_ADDR, 0x4, 0x0 ); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x4 ); + //printk("reg4=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0xA ); + //printk("regA=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0xC ); + //printk("regC=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x16 ); + //printk("reg16=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x1C ); + //printk("reg1C=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x34 ); + //printk("reg34=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x38 ); + //printk("reg38=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3A ); + //printk("reg3A=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3C ); + //printk("reg3C=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x3E ); + //printk("reg3E=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x40 ); + //printk("reg40=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x42 ); + //printk("reg42=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x44 ); + //printk("reg44=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x5A ); + //printk("reg5A=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x5C ); + //printk("reg5C=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x5E ); + //printk("reg5E=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x68 ); + //printk("reg68=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x6A ); + //printk("reg6A=%x\n", temp); + + temp = serial_in_i2c( ALC5628_I2C_ADDR, 0x6C ); + //printk("reg6C=%x\n", temp); +} + +// ------------------------------------------------------------------ +// ------------------------------------------------------------------ +// Early printk or bootcode + +#define rtlRegRead(addr) \ + (*(volatile u32 *)addr) + +#define rtlRegWrite(addr, val) \ + ((*(volatile u32 *)addr) = (val)) + +static inline u32 rtlRegMask(u32 addr, u32 mask, u32 value) +{ + u32 reg; + + reg = rtlRegRead(addr); + reg &= ~mask; + reg |= value & mask; + rtlRegWrite(addr, reg); + reg = rtlRegRead(addr); /* flush write to the hardware */ + + return reg; +} + +static int __init alc5628_init(void) +{ + int ret; + rtlRegMask(0xb8000010, 0x03DCB000, 0x01DCB000);//enable iis controller clock + rtlRegMask(0xb8000058, 0x00000001, 0x00000001);//enable 24p576mHz clock + + /* Configure the I2S pins in correct mode */ +#if 1 // set the jtag as iis-audio + rtlRegMask(0xb8000040, 0x00000007, 0x00000003);//change pin mux to iis-voice pin +#else // set the led-phase or lec-sig as iis-audio + rtlRegMask(0xb8000044, 0x001F80DB, 0x00000049);//change pin mux to iis-voice pin +#endif + + alc5628_init_i2c(); + + return 0; +} + +#ifndef __BOOTCODE__ +module_init(alc5628_init); + +MODULE_AUTHOR("Realtek"); +MODULE_DESCRIPTION("i2c driver for ALC5628"); +MODULE_LICENSE("GPL"); +#endif \ No newline at end of file -- cgit v1.2.3