linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ben Dooks <ben-linux@fluff.org>
To: JosephChan@via.com.tw
Cc: geert@linux-m68k.org, akpm@linux-foundation.org,
	linux-fbdev-devel@lists.sourceforge.net,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 12/13] viafb: via_i2c.c, via_i2c.h, viamode.c, viamode.c
Date: Mon, 30 Jun 2008 16:43:48 +0100	[thread overview]
Message-ID: <20080630154348.GF21835@fluff.org.uk> (raw)
In-Reply-To: <C80EF34A3D2E494DBAF9AC29C7AE4EB8074E78AA@exchtp03.taipei.via.com.tw>

On Mon, Jun 30, 2008 at 03:51:19PM +0800, JosephChan@via.com.tw wrote:
> via_i2c.c, via_i2c.h: Implement i2c specification.
> viamode.c, viamode.c: all support modes information.
> 
> 
> Signed-off-by: Joseph Chan <josephchan@via.com.tw>
> 
> 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

  reply	other threads:[~2008-06-30 15:44 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-06-30  7:51 [PATCH 12/13] viafb: via_i2c.c, via_i2c.h, viamode.c, viamode.c JosephChan
2008-06-30 15:43 ` Ben Dooks [this message]
2008-06-30 17:05   ` Alan Cox
2008-07-01  1:11   ` JosephChan
2008-08-08 10:19 ` [PATCH 12/13 v2] viafb: via_i2c.c, via_i2c.h, viamode.c, viamode.h JosephChan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080630154348.GF21835@fluff.org.uk \
    --to=ben-linux@fluff.org \
    --cc=JosephChan@via.com.tw \
    --cc=akpm@linux-foundation.org \
    --cc=geert@linux-m68k.org \
    --cc=linux-fbdev-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).