📄 via_i2c.c
字号:
/*
* Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sub license,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <linux/ioport.h>
#include <asm/io.h>
#include "chip.h"
#include "debug.h"
#include "via_i2c.h"
#include "share.h"
extern inline void write_reg(u8 index, u16 io_port, u8 data);
extern inline u8 read_reg(int io_port, u8 index);
extern struct chip_information chip_info;
extern struct tv_setting_information tv_setting_info;
/* i2c delay for microsecond*/
void delays(int count)
{
volatile u8 data;
while (count--)
{
// delay 1 us
data = inb(DELAYPORT);
data = inb(DELAYPORT);
data = inb(DELAYPORT);
data = inb(DELAYPORT);
data = inb(DELAYPORT);
}
}
/* Write I2C BUS SDA And SCL*/
void i2cWriteSdaScl(u8 sda, u8 scl)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AMR)
{
data = ((scl << 1) | sda) << 4;
data = data | BIT0; // enable I2C port
port_addr = TVI2CPORT;
write_reg(TVI2CPORTINDEX, port_addr, data); // Write Register Value
}
else
{
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
data = ((scl << 1) | sda) << 4;
data = data | (BIT6+BIT7); // enable GPIO write port
port_addr = TVGPIOPORT;
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
}
void i2cWriteScl(u8 scl)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AMR)
{
data = (scl << 1)<< 4;
data = data | BIT0; // enable I2C port
port_addr = TVI2CPORT;
write_reg(TVI2CPORTINDEX, port_addr, data); // Write Register Value
}
else
{
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
data = (scl << 1) << 4;
data = data & 0xBF; // enable GPIO write clock
port_addr = TVGPIOPORT;
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
}
void i2cReadSdaScl(u8 *pSda, u8 *pScl)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AMR)
{
port_addr = TVI2CPORT;
data = read_reg(port_addr, TVI2CPORTINDEX);
*pSda = (data >> 2) & BIT0; // get sda
*pScl = (data >> 3) & BIT0; // get scl
}
else
{
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
port_addr = TVGPIOPORT;
data = read_reg(port_addr, TVGPIOPORTINDEX);
*pSda = (data >> 2) & BIT0; // get sda
*pScl = (data >> 3) & BIT0; // get scl
}
}
}
void i2cWriteSdaSclDelay(u8 sda, u8 scl)
{
i2cWriteSdaScl(sda, scl);
delays(16); // Wait 16 uS
}
void i2cStartSignal(void)
{
i2cWriteSdaSclDelay(1,1);
i2cWriteSdaSclDelay(0,1);
i2cWriteSdaSclDelay(0,0);
}
void i2cStopSignal(void)
{
u8 data;
u16 port_addr;
i2cWriteSdaSclDelay(0,0);
i2cWriteSdaSclDelay(0,1);
i2cWriteSdaSclDelay(1,1);
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
data = 0x3c; // disable GPIO write port
port_addr = TVGPIOPORT;
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
delays(2);
}
void disableSdaGPIO(void)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
port_addr = TVGPIOPORT;
data = read_reg(port_addr, TVGPIOPORTINDEX);
data = data & (~BIT6); // disable GPIO write port
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
void enableSdaGPIO(void)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
port_addr = TVGPIOPORT;
data = read_reg(port_addr, TVGPIOPORTINDEX);
data = data | (BIT6); // disable GPIO write port
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
void writeSclGPIO(u8 scl)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
port_addr = TVGPIOPORT;
data = read_reg(port_addr, TVGPIOPORTINDEX);
data = data & (~BIT5);
data = (data | (scl<<5)) & (~BIT6); // write data to clock
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
void writeSdaGPIO(u8 sda)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
port_addr = TVGPIOPORT;
data = read_reg(port_addr, TVGPIOPORTINDEX);
data = data & (~BIT4);
data = (data | (sda<<4)) & (~BIT7); // write data to clock
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
void enableGPIO(void)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
port_addr = TVGPIOPORT;
data = read_reg(port_addr, TVGPIOPORTINDEX);
data = data | (BIT4+BIT5+BIT6+BIT7); // enable GPIO write port
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
void releaseGPIO(void)
{
u8 data;
u16 port_addr;
if (chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP)
{
port_addr = TVGPIOPORT;
port_addr = port_addr + 1;
data = read_reg(port_addr, TVGPIOPORTINDEX);
data = data & 0x3c; // disable GPIO write port
port_addr = TVGPIOPORT;
write_reg (TVGPIOPORTINDEX, port_addr, data); // Write Register Value
}
}
int i2CWaitForSlave(void)
{
int time_out = 20000;
u8 sda, scl;
while (time_out--)
{
i2cReadSdaScl(&sda, &scl);
if (scl)
return (OK); // Successful stall
delays(1); // wait 1 uS
}
return (FAIL); // Slave fail
}
int i2cOutByte(u8 data)
{
u8 sda, scl;
u8 out_byte;
int bit_count = 8;
int status;
out_byte = data;
while (bit_count--)
{
sda = (out_byte >> 7) & 1; // Load MSB
out_byte = out_byte << 1; // next bit.
i2cWriteSdaSclDelay(sda, 0);
i2cWriteSdaSclDelay(sda, 1);
status = i2CWaitForSlave();
if (status == FAIL)
{
return (status);
}
i2cWriteSdaSclDelay(sda, 0);
}
if ((chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP))
{
writeSclGPIO(0);
disableSdaGPIO();
delays(2);
writeSclGPIO(1);
delays(2);
i2cReadSdaScl(&sda, &scl);
writeSclGPIO(0);
delays(2);
if (sda == 0)
{
status = OK;
}
else
{
status = FAIL;
}
}
else
{
i2cWriteSdaSclDelay(1,0);
i2cWriteSdaSclDelay(1,1);
status = i2CWaitForSlave();
if (status == FAIL)
{
return (status);
}
i2cReadSdaScl(&sda, &scl);
if (sda == 0)
{
i2cWriteSdaSclDelay(1,0);
status = OK;
}
else
{
i2cWriteSdaSclDelay(1,0);
status = FAIL;
}
}
return (status);
}
int i2cInputByte(u8 *pInByte, int ack)
{
int bit_count = 8;
u8 sda, scl;
u8 data = 0;
int status;
disableSdaGPIO();
while (bit_count--)
{
if ((chip_info.tv_chip_info.tv_chip_on_slot == TV_ON_AGP))
{
writeSclGPIO(1);
delays(2);
status = i2CWaitForSlave();
if (status == FAIL)
return (FAIL);
i2cReadSdaScl(&sda, &scl);
data = data << 1;
data |= sda;
writeSclGPIO(0);
delays(2);
}
else
{
i2cWriteSdaSclDelay(1,1);
status = i2CWaitForSlave();
if (status == FAIL)
return(FAIL);
i2cReadSdaScl(&sda, &scl);
data = data << 1;
data |= sda;
i2cWriteSdaSclDelay(1, 0);
}
}
*pInByte = data;
if (ack)
{
i2cWriteSdaSclDelay(0, 0);
i2cWriteSdaSclDelay(0, 1);
status = i2CWaitForSlave();
if (status == FAIL)
return(status);
i2cWriteSdaSclDelay(0, 0);
}
else
{
i2cWriteSdaSclDelay(1, 0);
i2cWriteSdaSclDelay(1, 1);
status = i2CWaitForSlave();
if (status == FAIL)
return(status);
}
i2cWriteSdaSclDelay(1, 0);
return(OK);
}
int i2cReadByte(u8 slave_addr, u8 index, u8 *pData)
{
int status;
i2cStartSignal();
status = i2cOutByte(slave_addr);
if (status == FAIL)
{
i2cStopSignal();
return(FAIL);
}
status = i2cOutByte(index);
if (status == FAIL)
{
i2cStopSignal();
return (FAIL);
}
i2cStartSignal();
status = i2cOutByte(slave_addr | BIT0);
if (status == FAIL)
{
i2cStopSignal();
return (FAIL);
}
status = i2cInputByte(pData, 0);
if (status == FAIL)
{
i2cStopSignal();
return (FAIL);
}
i2cStopSignal();
return(OK);
}
int i2cWriteByte(u8 slave_addr, u8 index, u8 data)
{
int status;
i2cStartSignal();
status = i2cOutByte(slave_addr);
if (status == FAIL)
{
i2cStopSignal();
return(FAIL);
}
status = i2cOutByte(index);
if (status == FAIL)
{
i2cStopSignal();
return(FAIL);
}
status = i2cOutByte(data);
if (status == FAIL)
{
i2cStopSignal();
return(FAIL);
}
i2cStopSignal();
return(OK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -