public inbox for linux-i2c@vger.kernel.org
 help / color / mirror / Atom feed
From: Dominik Brodowski <linux-X3ehHDuj6sIIGcDfoQAp7OTW4wlIGRCZ@public.gmane.org>
To: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: wnv_cs.c: i2c question
Date: Mon, 27 Sep 2010 09:45:49 +0200	[thread overview]
Message-ID: <20100927074549.GA32061@comet.dominikbrodowski.net> (raw)

Hey,

as I recently obtained such a PCMCIA card, I try to revive the wnv_cs driver
for Winnov Videum Traveler video cards. First (non-working, but compiling
and able to access the EEPROM and to detect the decoder) results may be
found at

http://git.kernel.org/?p=linux/kernel/git/brodo/pcmcia-2.6.git;a=shortlog;h=refs/heads/wnv

Now, I got a bit stuck at the i2c level -- do the following access functions
look familiar to one of the i2c experts? If so, which algo driver is to be
used? Is this an i2c_smbus_, or some very custom interface not worth
converting to use the i2c subsystem? Many thanks!

Best,
	Dominik

PS: The i2c addresses used in this driver are > 0x7f (e.g. 0xa0, 0x8e, 0x48,
	0x4a, 0x34, 0xa8, 0x68)


/*
 *	  2
 *	I   C   B U S   I N T E R F A C E
 *
 */

static __u16
in_ctl(struct videum_device *dev)
{	return wavi_readreg(dev, WAVI_CTL);
}
static void
out_ctl(struct videum_device *dev)
{	wavi_writereg(dev, WAVI_CTL, dev->ctl);
}
static void
i2c_delay(void)
{	udelay(2);
}
static void
i2c_clock(struct videum_device *dev, int c)
{	int	t = 1000;
	if (c) dev->ctl |= WAVI_I2CBIT; else dev->ctl &= ~WAVI_I2CBIT;
	out_ctl(dev);
	if (!c) while (--t && (in_ctl(dev) & WAVI_I2CBIT));
}
static void
i2c_data(struct videum_device *dev, int d)
{	if (d) dev->ctl |= WAVI_IMDBIT; else dev->ctl &= ~WAVI_IMDBIT;
	out_ctl(dev);
}
/* BUG: I2C bit read routines, polarity */

static void
i2c_start(struct videum_device *dev)
{	dev->ctl &= ~(WAVI_I2CBIT | WAVI_IMDBIT);
	out_ctl(dev);		i2c_delay();
	i2c_data(dev, 1);	i2c_delay();
	i2c_clock(dev, 0);	i2c_delay();
}

static int
i2c_get_ack(struct videum_device *dev)
{
	i2c_clock(dev, 1);	i2c_delay();
	i2c_data(dev, 0);	i2c_delay();
	i2c_clock(dev, 0);	i2c_delay();
	i2c_delay();
	return in_ctl(dev) & WAVI_IMDBIT;
}

static void
i2c_send_ack(struct videum_device *dev)
{
	i2c_clock(dev, 1);	i2c_delay();
	i2c_data(dev, 1);	i2c_delay();
	i2c_clock(dev, 0);	i2c_delay();
}

static void
i2c_send_nak(struct videum_device *dev)
{
	i2c_clock(dev, 1);	i2c_delay();
	i2c_data(dev, 0);	i2c_delay();
	i2c_clock(dev, 0);	i2c_delay();
}

static void
i2c_end(struct videum_device *dev)
{
	i2c_clock(dev, 1);	i2c_delay();
	i2c_data(dev, 1);	i2c_delay();
	i2c_clock(dev, 0);	i2c_delay();
	i2c_data(dev, 0);	i2c_delay();
}

static void
i2c_vpxrestart(struct videum_device *dev)
{
	i2c_clock(dev, 1);	i2c_delay();
	i2c_data(dev, 0);	i2c_delay();
	i2c_clock(dev, 0);	i2c_delay();
}

static void
i2c_out8(struct videum_device *dev,
	 int	ndata)
{
	int	i;
	
	ndata = ~ndata;
	for (i = 0; i < 8; ++i)
	{
		i2c_clock(dev, 1);		i2c_delay();
		i2c_data(dev, ndata & 128);	i2c_delay();
		i2c_clock(dev, 0);		i2c_delay();
		ndata <<= 1;
	}
}

static int
i2c_in8(struct videum_device *dev)
{
	int	i;
	int	ndata = ~0;

	dev->ctl &= ~WAVI_IMDBIT;// Don't write to h/w now
	for (i = 0; i < 8; ++i)
	{
		i2c_clock(dev, 1);	i2c_delay();
		i2c_clock(dev, 0);	i2c_delay();
		ndata = (in_ctl(dev) & 1) | (ndata << 1);
	}
	return ~ndata;
}

static void
i2c_get_ready(struct videum_device *dev)
{/*	Prepare I2C bus for operation	*/
	dev->ctl = in_ctl(dev);	/* initialize the CTL register shadow */
	i2c_end(dev);	/* idle the I2C bus */
}

static int
i2c_error(struct videum_device *dev)
{
	i2c_end(dev);
	return -1;
}

// Returns -1 on error.
static int i2c_read_reg_byte(struct videum_device *dev, int addr, int reg)
{	int	ndata;

	i2c_start(dev);
	i2c_out8(dev, addr);
	if (!i2c_get_ack(dev))
		return i2c_error(dev);/* no ACK from device */
	i2c_out8(dev, reg);
	i2c_get_ack(dev); /* assume it succeeds if the first one succeeded */
	if (addr == 0x86 || addr == 0x8E)/* ITT VPX is a little different  */
		i2c_vpxrestart(dev);
	else
		i2c_end(dev);
	i2c_start(dev);
	i2c_out8(dev, addr | 1);
	if (!i2c_get_ack(dev))
		return i2c_error(dev);
	ndata = i2c_in8(dev);
	if (addr == 0x86 || addr == 0x8E)/* ITT VPX is a little different  */
		i2c_send_nak(dev);
	i2c_end(dev);
	return ndata;
}

static int /* -1 on error */
i2c_write_reg_byte(struct videum_device *dev, 
		   int addr, int reg, int ndata)
{
	i2c_start(dev);
	i2c_out8(dev, addr);
	if (!i2c_get_ack(dev))
		return i2c_error(dev);/* no ACK from device */
	i2c_out8(dev, reg);
	i2c_get_ack(dev);
	i2c_out8(dev, ndata);
	i2c_get_ack(dev);
	i2c_end(dev);
	return 0;
}

static int /* -1 on error */
i2c_read_reg_word(struct videum_device *dev, 
		  int addr, int reg)
{
	int	ndata;
	
	i2c_start(dev);
	i2c_out8(dev, addr);
	if (!i2c_get_ack(dev))
		return i2c_error(dev);/* no ACK from device */
	i2c_out8(dev, reg);
	i2c_get_ack(dev); /* assume it succeeds if the first one succeeded */
	if (addr == 0x86 || addr == 0x8E)/* ITT VPX is a little different  */
		i2c_vpxrestart(dev);
	else
		i2c_end(dev);
	i2c_start(dev);
	i2c_out8(dev, addr | 1);
	if (!i2c_get_ack(dev))
		return i2c_error(dev);
	ndata = i2c_in8(dev) << 8;
	i2c_send_ack(dev);
	ndata |= i2c_in8(dev);
	i2c_send_nak(dev);
	i2c_end(dev);
	return ndata;
}

static int /* -1 on error */
i2c_write_reg_word(struct videum_device *dev, 
		   int addr, int reg, int ndata)
{
	i2c_start(dev);
	i2c_out8(dev, addr);
	if (!i2c_get_ack(dev))
		return i2c_error(dev);/* no ACK from device */
	i2c_out8(dev, reg);
	i2c_get_ack(dev);
	i2c_out8(dev, ndata >> 8);
	i2c_get_ack(dev);
	i2c_out8(dev, ndata & 0xFF);
	i2c_get_ack(dev);
	i2c_end(dev);
	return 0;
}

             reply	other threads:[~2010-09-27  7:45 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-27  7:45 Dominik Brodowski [this message]
2010-09-28 20:37 ` [SOLVED] wnv_cs.c: i2c question Dominik Brodowski

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=20100927074549.GA32061@comet.dominikbrodowski.net \
    --to=linux-x3ehhduj6siigcdfoqap7otw4wligrcz@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.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