Thread (5 messages) 5 messages, 3 authors, 2008-08-08

Re: [PATCH 12/13] viafb: via_i2c.c, via_i2c.h, viamode.c, viamode.c

From: Ben Dooks <ben-linux@fluff.org>
Date: 2008-06-30 15:44:30
Also in: lkml

On Mon, Jun 30, 2008 at 03:51:19PM +0800, JosephChan@via.com.tw wrote:
quoted hunk ↗ jump to hunk
via_i2c.c, via_i2c.h: Implement i2c specification.
viamode.c, viamode.c: all support modes information.


Signed-off-by: Joseph Chan <redacted>

diff -Nur a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
--- a/drivers/video/via/via_i2c.c	1970-01-01 08:00:00.000000000 +0800
+++ b/drivers/video/via/via_i2c.c	2008-06-30 08:53:33.000000000 +0800
@@ -0,0 +1,377 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+/* i2c delay for microsecond*/
+void viafb_delays(int count)
+{
+	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*/
+static void i2cWriteSdaScl(u8 sda, u8 scl)
+{
+	u8 data;
+	u16 port_addr;
+
+	if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AMR) {
+
+		data = ((scl << 1) | sda) << 4;
+		/* enable I2C port */
+		data = data | BIT0;
+
+		port_addr = I2CPORT;
+		/* Write Register Value */
+		viafb_write_reg(I2CPORTINDEX, port_addr, data);
+	} else {
+		if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
+			data = ((scl << 1) | sda) << 4;
+			/* enable GPIO write port */
+			data = data | (BIT6 + BIT7);
+			port_addr = GPIOPORT;
+			/* Write Register Value */
+			viafb_write_reg(GPIOPORTINDEX, port_addr, data);
+		}
+	}
+}
+
+static void i2cReadSdaScl(u8 *pSda, u8 *pScl)
+{
+	u8 data;
+	u16 port_addr;
+
+	if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AMR) {
+		port_addr = I2CPORT;
+		data = viafb_read_reg(port_addr, I2CPORTINDEX);
+		*pSda = (data >> 2) & BIT0;	/* get sda */
+		*pScl = (data >> 3) & BIT0;	/* get scl */
+	} else {
+		if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
+			port_addr = GPIOPORT;
+			data = viafb_read_reg(port_addr, GPIOPORTINDEX);
+			*pSda = (data >> 2) & BIT0;	/* get sda */
+			*pScl = (data >> 3) & BIT0;	/* get scl */
+		}
+	}
+}
+
+static void i2cWriteSdaSclDelay(u8 sda, u8 scl)
+{
+	i2cWriteSdaScl(sda, scl);
+	viafb_delays(16);		/* Wait 16 uS */
+}
+
+static void i2cStartSignal(void)
+{
+	i2cWriteSdaSclDelay(1, 1);
+	i2cWriteSdaSclDelay(0, 1);
+	i2cWriteSdaSclDelay(0, 0);
+}
+
+static void i2cStopSignal(void)
+{
+	u8 data;
+	u16 port_addr;
+
+	i2cWriteSdaSclDelay(0, 0);
+	i2cWriteSdaSclDelay(0, 1);
+	i2cWriteSdaSclDelay(1, 1);
+
+	if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
+		/* disable GPIO write port */
+		data = 0x3c;
+		port_addr = GPIOPORT;
+		/* Write Register Value */
+		viafb_write_reg(GPIOPORTINDEX, port_addr, data);
+	}
+	viafb_delays(2);
+
+}
+
+static void disableSdaGPIO(void)
+{
+	u8 data;
+	u16 port_addr;
+
+	if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
+		port_addr = GPIOPORT;
+		data = viafb_read_reg(port_addr, GPIOPORTINDEX);
+		/* disable GPIO write port */
+		data = data & (~BIT6);
+		/* Write Register Value */
+		viafb_write_reg(GPIOPORTINDEX, port_addr, data);
+	}
+}
+
+static void writeSclGPIO(u8 scl)
+{
+	u8 data;
+	u16 port_addr;
+
+	if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
+		port_addr = GPIOPORT;
+		data = viafb_read_reg(port_addr, GPIOPORTINDEX);
+		data = data & (~BIT5);
+		/* write data to clock */
+		data = (data | (scl << 5)) & (~BIT6);
+		/* Write Register Value */
+		viafb_write_reg(GPIOPORTINDEX, port_addr, data);
+	}
+}
+
+static int i2CWaitForSlave(void)
+{
+	int time_out = 20000;
+	u8 sda, scl;
+
+	while (time_out--) {
+		i2cReadSdaScl(&sda, &scl);
+		if (scl)
+			return OK;	/* Successful stall */
+		viafb_delays(1);	/* wait 1 uS */
+	}
+	return FAIL;		/* Slave fail */
+}
+
+static 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 ((viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP)) {
+
+		writeSclGPIO(0);
+		disableSdaGPIO();
+		viafb_delays(2);
+		writeSclGPIO(1);
+		viafb_delays(2);
+		i2cReadSdaScl(&sda, &scl);
+		writeSclGPIO(0);
+		viafb_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;
+}
+
+static int i2cInputByte(u8 *pInByte, int ack)
+{
+
+	int bit_count = 8;
+	u8 sda, scl;
+	u8 data = 0;
+	int status;
+
+	disableSdaGPIO();
+
+	while (bit_count--) {
+		if ((viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP)) {
+
+			writeSclGPIO(1);
+			viafb_delays(2);
+			status = i2CWaitForSlave();
+			if (status == FAIL)
+				return FAIL;
+			i2cReadSdaScl(&sda, &scl);
+			data = data << 1;
+			data |= sda;
+			writeSclGPIO(0);
+			viafb_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 viafb_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 viafb_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;
+}
+
+int viafb_i2cReadBytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
+{
+
+	int status, i;
+
+	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;
+	}
+
+	for (i = 0; i < buff_len; i++) {
+		if (buff_len == 1)
+			status = i2cInputByte(buff, 0);	/* send NACK */
+		else if (i < buff_len - 1)
+			status = i2cInputByte(buff, 1);	/* send ACK */
+		else
+			status = i2cInputByte(buff, 0);	/* send NACK */
+		if (status == FAIL) {
+			i2cStopSignal();
+			return (FAIL);
+		}
+		buff++;
+	}
+
+	i2cStopSignal();
+	return OK;
+}
This looks like an attempt at re-doing the already extant i2c gpio
algorithm. Either export via gpiolib and use the i2c-gpio adapter or
use the i2c bit-banging algorithm.

-- 
Ben

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help