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

📄 via_i2c.c

📁 VIA Framebuffer driver
💻 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 + -