xref: /openbmc/linux/drivers/media/pci/bt8xx/bttv-i2c.c (revision b4b1d040)
168de959fSMauro Carvalho Chehab /*
268de959fSMauro Carvalho Chehab 
368de959fSMauro Carvalho Chehab     bttv-i2c.c  --  all the i2c code is here
468de959fSMauro Carvalho Chehab 
568de959fSMauro Carvalho Chehab     bttv - Bt848 frame grabber driver
668de959fSMauro Carvalho Chehab 
768de959fSMauro Carvalho Chehab     Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
868de959fSMauro Carvalho Chehab 			   & Marcus Metzler (mocm@thp.uni-koeln.de)
968de959fSMauro Carvalho Chehab     (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
1068de959fSMauro Carvalho Chehab 
1168de959fSMauro Carvalho Chehab     (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
1268de959fSMauro Carvalho Chehab 	- Multituner support and i2c address binding
1368de959fSMauro Carvalho Chehab 
1468de959fSMauro Carvalho Chehab     This program is free software; you can redistribute it and/or modify
1568de959fSMauro Carvalho Chehab     it under the terms of the GNU General Public License as published by
1668de959fSMauro Carvalho Chehab     the Free Software Foundation; either version 2 of the License, or
1768de959fSMauro Carvalho Chehab     (at your option) any later version.
1868de959fSMauro Carvalho Chehab 
1968de959fSMauro Carvalho Chehab     This program is distributed in the hope that it will be useful,
2068de959fSMauro Carvalho Chehab     but WITHOUT ANY WARRANTY; without even the implied warranty of
2168de959fSMauro Carvalho Chehab     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2268de959fSMauro Carvalho Chehab     GNU General Public License for more details.
2368de959fSMauro Carvalho Chehab 
2468de959fSMauro Carvalho Chehab     You should have received a copy of the GNU General Public License
2568de959fSMauro Carvalho Chehab     along with this program; if not, write to the Free Software
2668de959fSMauro Carvalho Chehab     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2768de959fSMauro Carvalho Chehab 
2868de959fSMauro Carvalho Chehab */
2968de959fSMauro Carvalho Chehab 
3068de959fSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3168de959fSMauro Carvalho Chehab 
3268de959fSMauro Carvalho Chehab #include <linux/module.h>
3368de959fSMauro Carvalho Chehab #include <linux/init.h>
3468de959fSMauro Carvalho Chehab #include <linux/delay.h>
3568de959fSMauro Carvalho Chehab 
3668de959fSMauro Carvalho Chehab #include "bttvp.h"
3768de959fSMauro Carvalho Chehab #include <media/v4l2-common.h>
3868de959fSMauro Carvalho Chehab #include <linux/jiffies.h>
3968de959fSMauro Carvalho Chehab #include <asm/io.h>
4068de959fSMauro Carvalho Chehab 
4168de959fSMauro Carvalho Chehab static int i2c_debug;
4268de959fSMauro Carvalho Chehab static int i2c_hw;
4368de959fSMauro Carvalho Chehab static int i2c_scan;
4468de959fSMauro Carvalho Chehab module_param(i2c_debug, int, 0644);
4568de959fSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug, "configure i2c debug level");
4668de959fSMauro Carvalho Chehab module_param(i2c_hw,    int, 0444);
4768de959fSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
4868de959fSMauro Carvalho Chehab 			"instead of software bitbang");
4968de959fSMauro Carvalho Chehab module_param(i2c_scan,  int, 0444);
5068de959fSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
5168de959fSMauro Carvalho Chehab 
5268de959fSMauro Carvalho Chehab static unsigned int i2c_udelay = 5;
5368de959fSMauro Carvalho Chehab module_param(i2c_udelay, int, 0444);
5468de959fSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_udelay,"soft i2c delay at insmod time, in usecs "
5568de959fSMauro Carvalho Chehab 		"(should be 5 or higher). Lower value means higher bus speed.");
5668de959fSMauro Carvalho Chehab 
5768de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
5868de959fSMauro Carvalho Chehab /* I2C functions - bitbanging adapter (software i2c)                       */
5968de959fSMauro Carvalho Chehab 
6068de959fSMauro Carvalho Chehab static void bttv_bit_setscl(void *data, int state)
6168de959fSMauro Carvalho Chehab {
6268de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
6368de959fSMauro Carvalho Chehab 
6468de959fSMauro Carvalho Chehab 	if (state)
6568de959fSMauro Carvalho Chehab 		btv->i2c_state |= 0x02;
6668de959fSMauro Carvalho Chehab 	else
6768de959fSMauro Carvalho Chehab 		btv->i2c_state &= ~0x02;
6868de959fSMauro Carvalho Chehab 	btwrite(btv->i2c_state, BT848_I2C);
6968de959fSMauro Carvalho Chehab 	btread(BT848_I2C);
7068de959fSMauro Carvalho Chehab }
7168de959fSMauro Carvalho Chehab 
7268de959fSMauro Carvalho Chehab static void bttv_bit_setsda(void *data, int state)
7368de959fSMauro Carvalho Chehab {
7468de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
7568de959fSMauro Carvalho Chehab 
7668de959fSMauro Carvalho Chehab 	if (state)
7768de959fSMauro Carvalho Chehab 		btv->i2c_state |= 0x01;
7868de959fSMauro Carvalho Chehab 	else
7968de959fSMauro Carvalho Chehab 		btv->i2c_state &= ~0x01;
8068de959fSMauro Carvalho Chehab 	btwrite(btv->i2c_state, BT848_I2C);
8168de959fSMauro Carvalho Chehab 	btread(BT848_I2C);
8268de959fSMauro Carvalho Chehab }
8368de959fSMauro Carvalho Chehab 
8468de959fSMauro Carvalho Chehab static int bttv_bit_getscl(void *data)
8568de959fSMauro Carvalho Chehab {
8668de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
8768de959fSMauro Carvalho Chehab 	int state;
8868de959fSMauro Carvalho Chehab 
8968de959fSMauro Carvalho Chehab 	state = btread(BT848_I2C) & 0x02 ? 1 : 0;
9068de959fSMauro Carvalho Chehab 	return state;
9168de959fSMauro Carvalho Chehab }
9268de959fSMauro Carvalho Chehab 
9368de959fSMauro Carvalho Chehab static int bttv_bit_getsda(void *data)
9468de959fSMauro Carvalho Chehab {
9568de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
9668de959fSMauro Carvalho Chehab 	int state;
9768de959fSMauro Carvalho Chehab 
9868de959fSMauro Carvalho Chehab 	state = btread(BT848_I2C) & 0x01;
9968de959fSMauro Carvalho Chehab 	return state;
10068de959fSMauro Carvalho Chehab }
10168de959fSMauro Carvalho Chehab 
10268de959fSMauro Carvalho Chehab static struct i2c_algo_bit_data __devinitdata bttv_i2c_algo_bit_template = {
10368de959fSMauro Carvalho Chehab 	.setsda  = bttv_bit_setsda,
10468de959fSMauro Carvalho Chehab 	.setscl  = bttv_bit_setscl,
10568de959fSMauro Carvalho Chehab 	.getsda  = bttv_bit_getsda,
10668de959fSMauro Carvalho Chehab 	.getscl  = bttv_bit_getscl,
10768de959fSMauro Carvalho Chehab 	.udelay  = 16,
10868de959fSMauro Carvalho Chehab 	.timeout = 200,
10968de959fSMauro Carvalho Chehab };
11068de959fSMauro Carvalho Chehab 
11168de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
11268de959fSMauro Carvalho Chehab /* I2C functions - hardware i2c                                            */
11368de959fSMauro Carvalho Chehab 
11468de959fSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *adap)
11568de959fSMauro Carvalho Chehab {
11668de959fSMauro Carvalho Chehab 	return I2C_FUNC_SMBUS_EMUL;
11768de959fSMauro Carvalho Chehab }
11868de959fSMauro Carvalho Chehab 
11968de959fSMauro Carvalho Chehab static int
12068de959fSMauro Carvalho Chehab bttv_i2c_wait_done(struct bttv *btv)
12168de959fSMauro Carvalho Chehab {
12268de959fSMauro Carvalho Chehab 	int rc = 0;
12368de959fSMauro Carvalho Chehab 
12468de959fSMauro Carvalho Chehab 	/* timeout */
12568de959fSMauro Carvalho Chehab 	if (wait_event_interruptible_timeout(btv->i2c_queue,
12668de959fSMauro Carvalho Chehab 	    btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS)
12768de959fSMauro Carvalho Chehab 		rc = -EIO;
12868de959fSMauro Carvalho Chehab 
12968de959fSMauro Carvalho Chehab 	if (btv->i2c_done & BT848_INT_RACK)
13068de959fSMauro Carvalho Chehab 		rc = 1;
13168de959fSMauro Carvalho Chehab 	btv->i2c_done = 0;
13268de959fSMauro Carvalho Chehab 	return rc;
13368de959fSMauro Carvalho Chehab }
13468de959fSMauro Carvalho Chehab 
13568de959fSMauro Carvalho Chehab #define I2C_HW (BT878_I2C_MODE  | BT848_I2C_SYNC |\
13668de959fSMauro Carvalho Chehab 		BT848_I2C_SCL | BT848_I2C_SDA)
13768de959fSMauro Carvalho Chehab 
13868de959fSMauro Carvalho Chehab static int
13968de959fSMauro Carvalho Chehab bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
14068de959fSMauro Carvalho Chehab {
14168de959fSMauro Carvalho Chehab 	u32 xmit;
14268de959fSMauro Carvalho Chehab 	int retval,cnt;
14368de959fSMauro Carvalho Chehab 
14468de959fSMauro Carvalho Chehab 	/* sanity checks */
14568de959fSMauro Carvalho Chehab 	if (0 == msg->len)
14668de959fSMauro Carvalho Chehab 		return -EINVAL;
14768de959fSMauro Carvalho Chehab 
14868de959fSMauro Carvalho Chehab 	/* start, address + first byte */
14968de959fSMauro Carvalho Chehab 	xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW;
15068de959fSMauro Carvalho Chehab 	if (msg->len > 1 || !last)
15168de959fSMauro Carvalho Chehab 		xmit |= BT878_I2C_NOSTOP;
15268de959fSMauro Carvalho Chehab 	btwrite(xmit, BT848_I2C);
15368de959fSMauro Carvalho Chehab 	retval = bttv_i2c_wait_done(btv);
15468de959fSMauro Carvalho Chehab 	if (retval < 0)
15568de959fSMauro Carvalho Chehab 		goto err;
15668de959fSMauro Carvalho Chehab 	if (retval == 0)
15768de959fSMauro Carvalho Chehab 		goto eio;
15868de959fSMauro Carvalho Chehab 	if (i2c_debug) {
15968de959fSMauro Carvalho Chehab 		pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
16068de959fSMauro Carvalho Chehab 	}
16168de959fSMauro Carvalho Chehab 
16268de959fSMauro Carvalho Chehab 	for (cnt = 1; cnt < msg->len; cnt++ ) {
16368de959fSMauro Carvalho Chehab 		/* following bytes */
16468de959fSMauro Carvalho Chehab 		xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART;
16568de959fSMauro Carvalho Chehab 		if (cnt < msg->len-1 || !last)
16668de959fSMauro Carvalho Chehab 			xmit |= BT878_I2C_NOSTOP;
16768de959fSMauro Carvalho Chehab 		btwrite(xmit, BT848_I2C);
16868de959fSMauro Carvalho Chehab 		retval = bttv_i2c_wait_done(btv);
16968de959fSMauro Carvalho Chehab 		if (retval < 0)
17068de959fSMauro Carvalho Chehab 			goto err;
17168de959fSMauro Carvalho Chehab 		if (retval == 0)
17268de959fSMauro Carvalho Chehab 			goto eio;
17368de959fSMauro Carvalho Chehab 		if (i2c_debug)
17468de959fSMauro Carvalho Chehab 			pr_cont(" %02x", msg->buf[cnt]);
17568de959fSMauro Carvalho Chehab 	}
1761ca6ae8dSJohn Törnblom 	if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
17768de959fSMauro Carvalho Chehab 		pr_cont(">\n");
17868de959fSMauro Carvalho Chehab 	return msg->len;
17968de959fSMauro Carvalho Chehab 
18068de959fSMauro Carvalho Chehab  eio:
18168de959fSMauro Carvalho Chehab 	retval = -EIO;
18268de959fSMauro Carvalho Chehab  err:
18368de959fSMauro Carvalho Chehab 	if (i2c_debug)
18468de959fSMauro Carvalho Chehab 		pr_cont(" ERR: %d\n",retval);
18568de959fSMauro Carvalho Chehab 	return retval;
18668de959fSMauro Carvalho Chehab }
18768de959fSMauro Carvalho Chehab 
18868de959fSMauro Carvalho Chehab static int
18968de959fSMauro Carvalho Chehab bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
19068de959fSMauro Carvalho Chehab {
19168de959fSMauro Carvalho Chehab 	u32 xmit;
19268de959fSMauro Carvalho Chehab 	u32 cnt;
19368de959fSMauro Carvalho Chehab 	int retval;
19468de959fSMauro Carvalho Chehab 
19568de959fSMauro Carvalho Chehab 	for (cnt = 0; cnt < msg->len; cnt++) {
19668de959fSMauro Carvalho Chehab 		xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
19768de959fSMauro Carvalho Chehab 		if (cnt < msg->len-1)
19868de959fSMauro Carvalho Chehab 			xmit |= BT848_I2C_W3B;
19968de959fSMauro Carvalho Chehab 		if (cnt < msg->len-1 || !last)
20068de959fSMauro Carvalho Chehab 			xmit |= BT878_I2C_NOSTOP;
20168de959fSMauro Carvalho Chehab 		if (cnt)
20268de959fSMauro Carvalho Chehab 			xmit |= BT878_I2C_NOSTART;
20368de959fSMauro Carvalho Chehab 
20468de959fSMauro Carvalho Chehab 		if (i2c_debug) {
20568de959fSMauro Carvalho Chehab 			if (!(xmit & BT878_I2C_NOSTART))
20668de959fSMauro Carvalho Chehab 				pr_cont(" <R %02x", (msg->addr << 1) +1);
20768de959fSMauro Carvalho Chehab 		}
20868de959fSMauro Carvalho Chehab 
20968de959fSMauro Carvalho Chehab 		btwrite(xmit, BT848_I2C);
21068de959fSMauro Carvalho Chehab 		retval = bttv_i2c_wait_done(btv);
21168de959fSMauro Carvalho Chehab 		if (retval < 0)
21268de959fSMauro Carvalho Chehab 			goto err;
21368de959fSMauro Carvalho Chehab 		if (retval == 0)
21468de959fSMauro Carvalho Chehab 			goto eio;
21568de959fSMauro Carvalho Chehab 		msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
21668de959fSMauro Carvalho Chehab 		if (i2c_debug) {
21768de959fSMauro Carvalho Chehab 			pr_cont(" =%02x", msg->buf[cnt]);
21868de959fSMauro Carvalho Chehab 		}
21968de959fSMauro Carvalho Chehab 		if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
22068de959fSMauro Carvalho Chehab 			pr_cont(" >\n");
22168de959fSMauro Carvalho Chehab 	}
22268de959fSMauro Carvalho Chehab 
22368de959fSMauro Carvalho Chehab 
22468de959fSMauro Carvalho Chehab 	return msg->len;
22568de959fSMauro Carvalho Chehab 
22668de959fSMauro Carvalho Chehab  eio:
22768de959fSMauro Carvalho Chehab 	retval = -EIO;
22868de959fSMauro Carvalho Chehab  err:
22968de959fSMauro Carvalho Chehab 	if (i2c_debug)
23068de959fSMauro Carvalho Chehab 		pr_cont(" ERR: %d\n",retval);
23168de959fSMauro Carvalho Chehab 	return retval;
23268de959fSMauro Carvalho Chehab }
23368de959fSMauro Carvalho Chehab 
23468de959fSMauro Carvalho Chehab static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
23568de959fSMauro Carvalho Chehab {
23668de959fSMauro Carvalho Chehab 	struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
23768de959fSMauro Carvalho Chehab 	struct bttv *btv = to_bttv(v4l2_dev);
23868de959fSMauro Carvalho Chehab 	int retval = 0;
23968de959fSMauro Carvalho Chehab 	int i;
24068de959fSMauro Carvalho Chehab 
24168de959fSMauro Carvalho Chehab 	if (i2c_debug)
24268de959fSMauro Carvalho Chehab 		pr_debug("bt-i2c:");
24368de959fSMauro Carvalho Chehab 
24468de959fSMauro Carvalho Chehab 	btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
24568de959fSMauro Carvalho Chehab 	for (i = 0 ; i < num; i++) {
24668de959fSMauro Carvalho Chehab 		if (msgs[i].flags & I2C_M_RD) {
24768de959fSMauro Carvalho Chehab 			/* read */
24868de959fSMauro Carvalho Chehab 			retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num);
24968de959fSMauro Carvalho Chehab 			if (retval < 0)
25068de959fSMauro Carvalho Chehab 				goto err;
25168de959fSMauro Carvalho Chehab 		} else {
25268de959fSMauro Carvalho Chehab 			/* write */
25368de959fSMauro Carvalho Chehab 			retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num);
25468de959fSMauro Carvalho Chehab 			if (retval < 0)
25568de959fSMauro Carvalho Chehab 				goto err;
25668de959fSMauro Carvalho Chehab 		}
25768de959fSMauro Carvalho Chehab 	}
25868de959fSMauro Carvalho Chehab 	return num;
25968de959fSMauro Carvalho Chehab 
26068de959fSMauro Carvalho Chehab  err:
26168de959fSMauro Carvalho Chehab 	return retval;
26268de959fSMauro Carvalho Chehab }
26368de959fSMauro Carvalho Chehab 
26468de959fSMauro Carvalho Chehab static const struct i2c_algorithm bttv_algo = {
26568de959fSMauro Carvalho Chehab 	.master_xfer   = bttv_i2c_xfer,
26668de959fSMauro Carvalho Chehab 	.functionality = functionality,
26768de959fSMauro Carvalho Chehab };
26868de959fSMauro Carvalho Chehab 
26968de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
27068de959fSMauro Carvalho Chehab /* I2C functions - common stuff                                            */
27168de959fSMauro Carvalho Chehab 
27268de959fSMauro Carvalho Chehab /* read I2C */
27368de959fSMauro Carvalho Chehab int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
27468de959fSMauro Carvalho Chehab {
27568de959fSMauro Carvalho Chehab 	unsigned char buffer = 0;
27668de959fSMauro Carvalho Chehab 
27768de959fSMauro Carvalho Chehab 	if (0 != btv->i2c_rc)
27868de959fSMauro Carvalho Chehab 		return -1;
27968de959fSMauro Carvalho Chehab 	if (bttv_verbose && NULL != probe_for)
28068de959fSMauro Carvalho Chehab 		pr_info("%d: i2c: checking for %s @ 0x%02x... ",
28168de959fSMauro Carvalho Chehab 			btv->c.nr, probe_for, addr);
28268de959fSMauro Carvalho Chehab 	btv->i2c_client.addr = addr >> 1;
28368de959fSMauro Carvalho Chehab 	if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
28468de959fSMauro Carvalho Chehab 		if (NULL != probe_for) {
28568de959fSMauro Carvalho Chehab 			if (bttv_verbose)
28668de959fSMauro Carvalho Chehab 				pr_cont("not found\n");
28768de959fSMauro Carvalho Chehab 		} else
28868de959fSMauro Carvalho Chehab 			pr_warn("%d: i2c read 0x%x: error\n",
28968de959fSMauro Carvalho Chehab 				btv->c.nr, addr);
29068de959fSMauro Carvalho Chehab 		return -1;
29168de959fSMauro Carvalho Chehab 	}
29268de959fSMauro Carvalho Chehab 	if (bttv_verbose && NULL != probe_for)
29368de959fSMauro Carvalho Chehab 		pr_cont("found\n");
29468de959fSMauro Carvalho Chehab 	return buffer;
29568de959fSMauro Carvalho Chehab }
29668de959fSMauro Carvalho Chehab 
29768de959fSMauro Carvalho Chehab /* write I2C */
29868de959fSMauro Carvalho Chehab int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
29968de959fSMauro Carvalho Chehab 		    unsigned char b2, int both)
30068de959fSMauro Carvalho Chehab {
30168de959fSMauro Carvalho Chehab 	unsigned char buffer[2];
30268de959fSMauro Carvalho Chehab 	int bytes = both ? 2 : 1;
30368de959fSMauro Carvalho Chehab 
30468de959fSMauro Carvalho Chehab 	if (0 != btv->i2c_rc)
30568de959fSMauro Carvalho Chehab 		return -1;
30668de959fSMauro Carvalho Chehab 	btv->i2c_client.addr = addr >> 1;
30768de959fSMauro Carvalho Chehab 	buffer[0] = b1;
30868de959fSMauro Carvalho Chehab 	buffer[1] = b2;
30968de959fSMauro Carvalho Chehab 	if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
31068de959fSMauro Carvalho Chehab 		return -1;
31168de959fSMauro Carvalho Chehab 	return 0;
31268de959fSMauro Carvalho Chehab }
31368de959fSMauro Carvalho Chehab 
31468de959fSMauro Carvalho Chehab /* read EEPROM content */
31568de959fSMauro Carvalho Chehab void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
31668de959fSMauro Carvalho Chehab {
31768de959fSMauro Carvalho Chehab 	memset(eedata, 0, 256);
31868de959fSMauro Carvalho Chehab 	if (0 != btv->i2c_rc)
31968de959fSMauro Carvalho Chehab 		return;
32068de959fSMauro Carvalho Chehab 	btv->i2c_client.addr = addr >> 1;
32168de959fSMauro Carvalho Chehab 	tveeprom_read(&btv->i2c_client, eedata, 256);
32268de959fSMauro Carvalho Chehab }
32368de959fSMauro Carvalho Chehab 
32468de959fSMauro Carvalho Chehab static char *i2c_devs[128] = {
32568de959fSMauro Carvalho Chehab 	[ 0x1c >> 1 ] = "lgdt330x",
32668de959fSMauro Carvalho Chehab 	[ 0x30 >> 1 ] = "IR (hauppauge)",
32768de959fSMauro Carvalho Chehab 	[ 0x80 >> 1 ] = "msp34xx",
32868de959fSMauro Carvalho Chehab 	[ 0x86 >> 1 ] = "tda9887",
32968de959fSMauro Carvalho Chehab 	[ 0xa0 >> 1 ] = "eeprom",
33068de959fSMauro Carvalho Chehab 	[ 0xc0 >> 1 ] = "tuner (analog)",
33168de959fSMauro Carvalho Chehab 	[ 0xc2 >> 1 ] = "tuner (analog)",
33268de959fSMauro Carvalho Chehab };
33368de959fSMauro Carvalho Chehab 
33468de959fSMauro Carvalho Chehab static void do_i2c_scan(char *name, struct i2c_client *c)
33568de959fSMauro Carvalho Chehab {
33668de959fSMauro Carvalho Chehab 	unsigned char buf;
33768de959fSMauro Carvalho Chehab 	int i,rc;
33868de959fSMauro Carvalho Chehab 
33968de959fSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
34068de959fSMauro Carvalho Chehab 		c->addr = i;
34168de959fSMauro Carvalho Chehab 		rc = i2c_master_recv(c,&buf,0);
34268de959fSMauro Carvalho Chehab 		if (rc < 0)
34368de959fSMauro Carvalho Chehab 			continue;
34468de959fSMauro Carvalho Chehab 		pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
34568de959fSMauro Carvalho Chehab 			name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
34668de959fSMauro Carvalho Chehab 	}
34768de959fSMauro Carvalho Chehab }
34868de959fSMauro Carvalho Chehab 
34968de959fSMauro Carvalho Chehab /* init + register i2c adapter */
35068de959fSMauro Carvalho Chehab int __devinit init_bttv_i2c(struct bttv *btv)
35168de959fSMauro Carvalho Chehab {
35268de959fSMauro Carvalho Chehab 	strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
35368de959fSMauro Carvalho Chehab 
35468de959fSMauro Carvalho Chehab 	if (i2c_hw)
35568de959fSMauro Carvalho Chehab 		btv->use_i2c_hw = 1;
35668de959fSMauro Carvalho Chehab 	if (btv->use_i2c_hw) {
35768de959fSMauro Carvalho Chehab 		/* bt878 */
35868de959fSMauro Carvalho Chehab 		strlcpy(btv->c.i2c_adap.name, "bt878",
35968de959fSMauro Carvalho Chehab 			sizeof(btv->c.i2c_adap.name));
36068de959fSMauro Carvalho Chehab 		btv->c.i2c_adap.algo = &bttv_algo;
36168de959fSMauro Carvalho Chehab 	} else {
36268de959fSMauro Carvalho Chehab 		/* bt848 */
36368de959fSMauro Carvalho Chehab 	/* Prevents usage of invalid delay values */
36468de959fSMauro Carvalho Chehab 		if (i2c_udelay<5)
36568de959fSMauro Carvalho Chehab 			i2c_udelay=5;
36668de959fSMauro Carvalho Chehab 
36768de959fSMauro Carvalho Chehab 		strlcpy(btv->c.i2c_adap.name, "bttv",
36868de959fSMauro Carvalho Chehab 			sizeof(btv->c.i2c_adap.name));
369b4b1d040SEzequiel Garcia 		btv->i2c_algo = bttv_i2c_algo_bit_template;
37068de959fSMauro Carvalho Chehab 		btv->i2c_algo.udelay = i2c_udelay;
37168de959fSMauro Carvalho Chehab 		btv->i2c_algo.data = btv;
37268de959fSMauro Carvalho Chehab 		btv->c.i2c_adap.algo_data = &btv->i2c_algo;
37368de959fSMauro Carvalho Chehab 	}
37468de959fSMauro Carvalho Chehab 	btv->c.i2c_adap.owner = THIS_MODULE;
37568de959fSMauro Carvalho Chehab 
37668de959fSMauro Carvalho Chehab 	btv->c.i2c_adap.dev.parent = &btv->c.pci->dev;
37768de959fSMauro Carvalho Chehab 	snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name),
37868de959fSMauro Carvalho Chehab 		 "bt%d #%d [%s]", btv->id, btv->c.nr,
37968de959fSMauro Carvalho Chehab 		 btv->use_i2c_hw ? "hw" : "sw");
38068de959fSMauro Carvalho Chehab 
38168de959fSMauro Carvalho Chehab 	i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev);
38268de959fSMauro Carvalho Chehab 	btv->i2c_client.adapter = &btv->c.i2c_adap;
38368de959fSMauro Carvalho Chehab 
38468de959fSMauro Carvalho Chehab 
38568de959fSMauro Carvalho Chehab 	if (btv->use_i2c_hw) {
38668de959fSMauro Carvalho Chehab 		btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
38768de959fSMauro Carvalho Chehab 	} else {
38868de959fSMauro Carvalho Chehab 		bttv_bit_setscl(btv,1);
38968de959fSMauro Carvalho Chehab 		bttv_bit_setsda(btv,1);
39068de959fSMauro Carvalho Chehab 		btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap);
39168de959fSMauro Carvalho Chehab 	}
39268de959fSMauro Carvalho Chehab 	if (0 == btv->i2c_rc && i2c_scan)
39368de959fSMauro Carvalho Chehab 		do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
39468de959fSMauro Carvalho Chehab 
39568de959fSMauro Carvalho Chehab 	return btv->i2c_rc;
39668de959fSMauro Carvalho Chehab }
397