xref: /openbmc/linux/drivers/media/pci/bt8xx/bttv-i2c.c (revision 3259081991a9398434f6f49468b960f136ac0158)
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 
11*32590819SMauro Carvalho Chehab     (c) 2005 Mauro Carvalho Chehab <mchehab@kernel.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);
47652fd6eaSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_hw, "force use of hardware i2c support, instead of software bitbang");
4868de959fSMauro Carvalho Chehab module_param(i2c_scan,  int, 0444);
4968de959fSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
5068de959fSMauro Carvalho Chehab 
5168de959fSMauro Carvalho Chehab static unsigned int i2c_udelay = 5;
5268de959fSMauro Carvalho Chehab module_param(i2c_udelay, int, 0444);
53652fd6eaSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_udelay, "soft i2c delay at insmod time, in usecs (should be 5 or higher). Lower value means higher bus speed.");
5468de959fSMauro Carvalho Chehab 
5568de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
5668de959fSMauro Carvalho Chehab /* I2C functions - bitbanging adapter (software i2c)                       */
5768de959fSMauro Carvalho Chehab 
5868de959fSMauro Carvalho Chehab static void bttv_bit_setscl(void *data, int state)
5968de959fSMauro Carvalho Chehab {
6068de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
6168de959fSMauro Carvalho Chehab 
6268de959fSMauro Carvalho Chehab 	if (state)
6368de959fSMauro Carvalho Chehab 		btv->i2c_state |= 0x02;
6468de959fSMauro Carvalho Chehab 	else
6568de959fSMauro Carvalho Chehab 		btv->i2c_state &= ~0x02;
6668de959fSMauro Carvalho Chehab 	btwrite(btv->i2c_state, BT848_I2C);
6768de959fSMauro Carvalho Chehab 	btread(BT848_I2C);
6868de959fSMauro Carvalho Chehab }
6968de959fSMauro Carvalho Chehab 
7068de959fSMauro Carvalho Chehab static void bttv_bit_setsda(void *data, int state)
7168de959fSMauro Carvalho Chehab {
7268de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
7368de959fSMauro Carvalho Chehab 
7468de959fSMauro Carvalho Chehab 	if (state)
7568de959fSMauro Carvalho Chehab 		btv->i2c_state |= 0x01;
7668de959fSMauro Carvalho Chehab 	else
7768de959fSMauro Carvalho Chehab 		btv->i2c_state &= ~0x01;
7868de959fSMauro Carvalho Chehab 	btwrite(btv->i2c_state, BT848_I2C);
7968de959fSMauro Carvalho Chehab 	btread(BT848_I2C);
8068de959fSMauro Carvalho Chehab }
8168de959fSMauro Carvalho Chehab 
8268de959fSMauro Carvalho Chehab static int bttv_bit_getscl(void *data)
8368de959fSMauro Carvalho Chehab {
8468de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
8568de959fSMauro Carvalho Chehab 	int state;
8668de959fSMauro Carvalho Chehab 
8768de959fSMauro Carvalho Chehab 	state = btread(BT848_I2C) & 0x02 ? 1 : 0;
8868de959fSMauro Carvalho Chehab 	return state;
8968de959fSMauro Carvalho Chehab }
9068de959fSMauro Carvalho Chehab 
9168de959fSMauro Carvalho Chehab static int bttv_bit_getsda(void *data)
9268de959fSMauro Carvalho Chehab {
9368de959fSMauro Carvalho Chehab 	struct bttv *btv = (struct bttv*)data;
9468de959fSMauro Carvalho Chehab 	int state;
9568de959fSMauro Carvalho Chehab 
9668de959fSMauro Carvalho Chehab 	state = btread(BT848_I2C) & 0x01;
9768de959fSMauro Carvalho Chehab 	return state;
9868de959fSMauro Carvalho Chehab }
9968de959fSMauro Carvalho Chehab 
1004d947447SBhumika Goyal static const struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
10168de959fSMauro Carvalho Chehab 	.setsda  = bttv_bit_setsda,
10268de959fSMauro Carvalho Chehab 	.setscl  = bttv_bit_setscl,
10368de959fSMauro Carvalho Chehab 	.getsda  = bttv_bit_getsda,
10468de959fSMauro Carvalho Chehab 	.getscl  = bttv_bit_getscl,
10568de959fSMauro Carvalho Chehab 	.udelay  = 16,
10668de959fSMauro Carvalho Chehab 	.timeout = 200,
10768de959fSMauro Carvalho Chehab };
10868de959fSMauro Carvalho Chehab 
10968de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
11068de959fSMauro Carvalho Chehab /* I2C functions - hardware i2c                                            */
11168de959fSMauro Carvalho Chehab 
11268de959fSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *adap)
11368de959fSMauro Carvalho Chehab {
11468de959fSMauro Carvalho Chehab 	return I2C_FUNC_SMBUS_EMUL;
11568de959fSMauro Carvalho Chehab }
11668de959fSMauro Carvalho Chehab 
11768de959fSMauro Carvalho Chehab static int
11868de959fSMauro Carvalho Chehab bttv_i2c_wait_done(struct bttv *btv)
11968de959fSMauro Carvalho Chehab {
12068de959fSMauro Carvalho Chehab 	int rc = 0;
12168de959fSMauro Carvalho Chehab 
12268de959fSMauro Carvalho Chehab 	/* timeout */
12368de959fSMauro Carvalho Chehab 	if (wait_event_interruptible_timeout(btv->i2c_queue,
12468de959fSMauro Carvalho Chehab 	    btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS)
12568de959fSMauro Carvalho Chehab 		rc = -EIO;
12668de959fSMauro Carvalho Chehab 
12768de959fSMauro Carvalho Chehab 	if (btv->i2c_done & BT848_INT_RACK)
12868de959fSMauro Carvalho Chehab 		rc = 1;
12968de959fSMauro Carvalho Chehab 	btv->i2c_done = 0;
13068de959fSMauro Carvalho Chehab 	return rc;
13168de959fSMauro Carvalho Chehab }
13268de959fSMauro Carvalho Chehab 
13368de959fSMauro Carvalho Chehab #define I2C_HW (BT878_I2C_MODE  | BT848_I2C_SYNC |\
13468de959fSMauro Carvalho Chehab 		BT848_I2C_SCL | BT848_I2C_SDA)
13568de959fSMauro Carvalho Chehab 
13668de959fSMauro Carvalho Chehab static int
13768de959fSMauro Carvalho Chehab bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
13868de959fSMauro Carvalho Chehab {
13968de959fSMauro Carvalho Chehab 	u32 xmit;
14068de959fSMauro Carvalho Chehab 	int retval,cnt;
14168de959fSMauro Carvalho Chehab 
14268de959fSMauro Carvalho Chehab 	/* sanity checks */
14368de959fSMauro Carvalho Chehab 	if (0 == msg->len)
14468de959fSMauro Carvalho Chehab 		return -EINVAL;
14568de959fSMauro Carvalho Chehab 
14668de959fSMauro Carvalho Chehab 	/* start, address + first byte */
14768de959fSMauro Carvalho Chehab 	xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW;
14868de959fSMauro Carvalho Chehab 	if (msg->len > 1 || !last)
14968de959fSMauro Carvalho Chehab 		xmit |= BT878_I2C_NOSTOP;
15068de959fSMauro Carvalho Chehab 	btwrite(xmit, BT848_I2C);
15168de959fSMauro Carvalho Chehab 	retval = bttv_i2c_wait_done(btv);
15268de959fSMauro Carvalho Chehab 	if (retval < 0)
15368de959fSMauro Carvalho Chehab 		goto err;
15468de959fSMauro Carvalho Chehab 	if (retval == 0)
15568de959fSMauro Carvalho Chehab 		goto eio;
15668de959fSMauro Carvalho Chehab 	if (i2c_debug) {
15768de959fSMauro Carvalho Chehab 		pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
15868de959fSMauro Carvalho Chehab 	}
15968de959fSMauro Carvalho Chehab 
16068de959fSMauro Carvalho Chehab 	for (cnt = 1; cnt < msg->len; cnt++ ) {
16168de959fSMauro Carvalho Chehab 		/* following bytes */
16268de959fSMauro Carvalho Chehab 		xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART;
16368de959fSMauro Carvalho Chehab 		if (cnt < msg->len-1 || !last)
16468de959fSMauro Carvalho Chehab 			xmit |= BT878_I2C_NOSTOP;
16568de959fSMauro Carvalho Chehab 		btwrite(xmit, BT848_I2C);
16668de959fSMauro Carvalho Chehab 		retval = bttv_i2c_wait_done(btv);
16768de959fSMauro Carvalho Chehab 		if (retval < 0)
16868de959fSMauro Carvalho Chehab 			goto err;
16968de959fSMauro Carvalho Chehab 		if (retval == 0)
17068de959fSMauro Carvalho Chehab 			goto eio;
17168de959fSMauro Carvalho Chehab 		if (i2c_debug)
17268de959fSMauro Carvalho Chehab 			pr_cont(" %02x", msg->buf[cnt]);
17368de959fSMauro Carvalho Chehab 	}
1741ca6ae8dSJohn Törnblom 	if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
17568de959fSMauro Carvalho Chehab 		pr_cont(">\n");
17668de959fSMauro Carvalho Chehab 	return msg->len;
17768de959fSMauro Carvalho Chehab 
17868de959fSMauro Carvalho Chehab  eio:
17968de959fSMauro Carvalho Chehab 	retval = -EIO;
18068de959fSMauro Carvalho Chehab  err:
18168de959fSMauro Carvalho Chehab 	if (i2c_debug)
18268de959fSMauro Carvalho Chehab 		pr_cont(" ERR: %d\n",retval);
18368de959fSMauro Carvalho Chehab 	return retval;
18468de959fSMauro Carvalho Chehab }
18568de959fSMauro Carvalho Chehab 
18668de959fSMauro Carvalho Chehab static int
18768de959fSMauro Carvalho Chehab bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
18868de959fSMauro Carvalho Chehab {
18968de959fSMauro Carvalho Chehab 	u32 xmit;
19068de959fSMauro Carvalho Chehab 	u32 cnt;
19168de959fSMauro Carvalho Chehab 	int retval;
19268de959fSMauro Carvalho Chehab 
19368de959fSMauro Carvalho Chehab 	for (cnt = 0; cnt < msg->len; cnt++) {
19468de959fSMauro Carvalho Chehab 		xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
19568de959fSMauro Carvalho Chehab 		if (cnt < msg->len-1)
19668de959fSMauro Carvalho Chehab 			xmit |= BT848_I2C_W3B;
19768de959fSMauro Carvalho Chehab 		if (cnt < msg->len-1 || !last)
19868de959fSMauro Carvalho Chehab 			xmit |= BT878_I2C_NOSTOP;
19968de959fSMauro Carvalho Chehab 		if (cnt)
20068de959fSMauro Carvalho Chehab 			xmit |= BT878_I2C_NOSTART;
20168de959fSMauro Carvalho Chehab 
20268de959fSMauro Carvalho Chehab 		if (i2c_debug) {
20368de959fSMauro Carvalho Chehab 			if (!(xmit & BT878_I2C_NOSTART))
20468de959fSMauro Carvalho Chehab 				pr_cont(" <R %02x", (msg->addr << 1) +1);
20568de959fSMauro Carvalho Chehab 		}
20668de959fSMauro Carvalho Chehab 
20768de959fSMauro Carvalho Chehab 		btwrite(xmit, BT848_I2C);
20868de959fSMauro Carvalho Chehab 		retval = bttv_i2c_wait_done(btv);
20968de959fSMauro Carvalho Chehab 		if (retval < 0)
21068de959fSMauro Carvalho Chehab 			goto err;
21168de959fSMauro Carvalho Chehab 		if (retval == 0)
21268de959fSMauro Carvalho Chehab 			goto eio;
21368de959fSMauro Carvalho Chehab 		msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
21468de959fSMauro Carvalho Chehab 		if (i2c_debug) {
21568de959fSMauro Carvalho Chehab 			pr_cont(" =%02x", msg->buf[cnt]);
21668de959fSMauro Carvalho Chehab 		}
21768de959fSMauro Carvalho Chehab 		if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
21868de959fSMauro Carvalho Chehab 			pr_cont(" >\n");
21968de959fSMauro Carvalho Chehab 	}
22068de959fSMauro Carvalho Chehab 
22168de959fSMauro Carvalho Chehab 
22268de959fSMauro Carvalho Chehab 	return msg->len;
22368de959fSMauro Carvalho Chehab 
22468de959fSMauro Carvalho Chehab  eio:
22568de959fSMauro Carvalho Chehab 	retval = -EIO;
22668de959fSMauro Carvalho Chehab  err:
22768de959fSMauro Carvalho Chehab 	if (i2c_debug)
22868de959fSMauro Carvalho Chehab 		pr_cont(" ERR: %d\n",retval);
22968de959fSMauro Carvalho Chehab 	return retval;
23068de959fSMauro Carvalho Chehab }
23168de959fSMauro Carvalho Chehab 
23268de959fSMauro Carvalho Chehab static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
23368de959fSMauro Carvalho Chehab {
23468de959fSMauro Carvalho Chehab 	struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
23568de959fSMauro Carvalho Chehab 	struct bttv *btv = to_bttv(v4l2_dev);
23668de959fSMauro Carvalho Chehab 	int retval = 0;
23768de959fSMauro Carvalho Chehab 	int i;
23868de959fSMauro Carvalho Chehab 
23968de959fSMauro Carvalho Chehab 	if (i2c_debug)
24068de959fSMauro Carvalho Chehab 		pr_debug("bt-i2c:");
24168de959fSMauro Carvalho Chehab 
24268de959fSMauro Carvalho Chehab 	btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
24368de959fSMauro Carvalho Chehab 	for (i = 0 ; i < num; i++) {
24468de959fSMauro Carvalho Chehab 		if (msgs[i].flags & I2C_M_RD) {
24568de959fSMauro Carvalho Chehab 			/* read */
24668de959fSMauro Carvalho Chehab 			retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num);
24768de959fSMauro Carvalho Chehab 			if (retval < 0)
24868de959fSMauro Carvalho Chehab 				goto err;
24968de959fSMauro Carvalho Chehab 		} else {
25068de959fSMauro Carvalho Chehab 			/* write */
25168de959fSMauro Carvalho Chehab 			retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num);
25268de959fSMauro Carvalho Chehab 			if (retval < 0)
25368de959fSMauro Carvalho Chehab 				goto err;
25468de959fSMauro Carvalho Chehab 		}
25568de959fSMauro Carvalho Chehab 	}
25668de959fSMauro Carvalho Chehab 	return num;
25768de959fSMauro Carvalho Chehab 
25868de959fSMauro Carvalho Chehab  err:
25968de959fSMauro Carvalho Chehab 	return retval;
26068de959fSMauro Carvalho Chehab }
26168de959fSMauro Carvalho Chehab 
26268de959fSMauro Carvalho Chehab static const struct i2c_algorithm bttv_algo = {
26368de959fSMauro Carvalho Chehab 	.master_xfer   = bttv_i2c_xfer,
26468de959fSMauro Carvalho Chehab 	.functionality = functionality,
26568de959fSMauro Carvalho Chehab };
26668de959fSMauro Carvalho Chehab 
26768de959fSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */
26868de959fSMauro Carvalho Chehab /* I2C functions - common stuff                                            */
26968de959fSMauro Carvalho Chehab 
27068de959fSMauro Carvalho Chehab /* read I2C */
27168de959fSMauro Carvalho Chehab int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
27268de959fSMauro Carvalho Chehab {
27368de959fSMauro Carvalho Chehab 	unsigned char buffer = 0;
27468de959fSMauro Carvalho Chehab 
27568de959fSMauro Carvalho Chehab 	if (0 != btv->i2c_rc)
27668de959fSMauro Carvalho Chehab 		return -1;
27768de959fSMauro Carvalho Chehab 	if (bttv_verbose && NULL != probe_for)
27868de959fSMauro Carvalho Chehab 		pr_info("%d: i2c: checking for %s @ 0x%02x... ",
27968de959fSMauro Carvalho Chehab 			btv->c.nr, probe_for, addr);
28068de959fSMauro Carvalho Chehab 	btv->i2c_client.addr = addr >> 1;
28168de959fSMauro Carvalho Chehab 	if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
28268de959fSMauro Carvalho Chehab 		if (NULL != probe_for) {
28368de959fSMauro Carvalho Chehab 			if (bttv_verbose)
28468de959fSMauro Carvalho Chehab 				pr_cont("not found\n");
28568de959fSMauro Carvalho Chehab 		} else
28668de959fSMauro Carvalho Chehab 			pr_warn("%d: i2c read 0x%x: error\n",
28768de959fSMauro Carvalho Chehab 				btv->c.nr, addr);
28868de959fSMauro Carvalho Chehab 		return -1;
28968de959fSMauro Carvalho Chehab 	}
29068de959fSMauro Carvalho Chehab 	if (bttv_verbose && NULL != probe_for)
29168de959fSMauro Carvalho Chehab 		pr_cont("found\n");
29268de959fSMauro Carvalho Chehab 	return buffer;
29368de959fSMauro Carvalho Chehab }
29468de959fSMauro Carvalho Chehab 
29568de959fSMauro Carvalho Chehab /* write I2C */
29668de959fSMauro Carvalho Chehab int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
29768de959fSMauro Carvalho Chehab 		    unsigned char b2, int both)
29868de959fSMauro Carvalho Chehab {
29968de959fSMauro Carvalho Chehab 	unsigned char buffer[2];
30068de959fSMauro Carvalho Chehab 	int bytes = both ? 2 : 1;
30168de959fSMauro Carvalho Chehab 
30268de959fSMauro Carvalho Chehab 	if (0 != btv->i2c_rc)
30368de959fSMauro Carvalho Chehab 		return -1;
30468de959fSMauro Carvalho Chehab 	btv->i2c_client.addr = addr >> 1;
30568de959fSMauro Carvalho Chehab 	buffer[0] = b1;
30668de959fSMauro Carvalho Chehab 	buffer[1] = b2;
30768de959fSMauro Carvalho Chehab 	if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
30868de959fSMauro Carvalho Chehab 		return -1;
30968de959fSMauro Carvalho Chehab 	return 0;
31068de959fSMauro Carvalho Chehab }
31168de959fSMauro Carvalho Chehab 
31268de959fSMauro Carvalho Chehab /* read EEPROM content */
3134c62e976SGreg Kroah-Hartman void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
31468de959fSMauro Carvalho Chehab {
31568de959fSMauro Carvalho Chehab 	memset(eedata, 0, 256);
31668de959fSMauro Carvalho Chehab 	if (0 != btv->i2c_rc)
31768de959fSMauro Carvalho Chehab 		return;
31868de959fSMauro Carvalho Chehab 	btv->i2c_client.addr = addr >> 1;
31968de959fSMauro Carvalho Chehab 	tveeprom_read(&btv->i2c_client, eedata, 256);
32068de959fSMauro Carvalho Chehab }
32168de959fSMauro Carvalho Chehab 
32268de959fSMauro Carvalho Chehab static char *i2c_devs[128] = {
32368de959fSMauro Carvalho Chehab 	[ 0x1c >> 1 ] = "lgdt330x",
32468de959fSMauro Carvalho Chehab 	[ 0x30 >> 1 ] = "IR (hauppauge)",
32568de959fSMauro Carvalho Chehab 	[ 0x80 >> 1 ] = "msp34xx",
32668de959fSMauro Carvalho Chehab 	[ 0x86 >> 1 ] = "tda9887",
32768de959fSMauro Carvalho Chehab 	[ 0xa0 >> 1 ] = "eeprom",
32868de959fSMauro Carvalho Chehab 	[ 0xc0 >> 1 ] = "tuner (analog)",
32968de959fSMauro Carvalho Chehab 	[ 0xc2 >> 1 ] = "tuner (analog)",
33068de959fSMauro Carvalho Chehab };
33168de959fSMauro Carvalho Chehab 
33268de959fSMauro Carvalho Chehab static void do_i2c_scan(char *name, struct i2c_client *c)
33368de959fSMauro Carvalho Chehab {
33468de959fSMauro Carvalho Chehab 	unsigned char buf;
33568de959fSMauro Carvalho Chehab 	int i,rc;
33668de959fSMauro Carvalho Chehab 
33768de959fSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
33868de959fSMauro Carvalho Chehab 		c->addr = i;
33968de959fSMauro Carvalho Chehab 		rc = i2c_master_recv(c,&buf,0);
34068de959fSMauro Carvalho Chehab 		if (rc < 0)
34168de959fSMauro Carvalho Chehab 			continue;
34268de959fSMauro Carvalho Chehab 		pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
34368de959fSMauro Carvalho Chehab 			name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
34468de959fSMauro Carvalho Chehab 	}
34568de959fSMauro Carvalho Chehab }
34668de959fSMauro Carvalho Chehab 
34768de959fSMauro Carvalho Chehab /* init + register i2c adapter */
3484c62e976SGreg Kroah-Hartman int init_bttv_i2c(struct bttv *btv)
34968de959fSMauro Carvalho Chehab {
35068de959fSMauro Carvalho Chehab 	strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
35168de959fSMauro Carvalho Chehab 
35268de959fSMauro Carvalho Chehab 	if (i2c_hw)
35368de959fSMauro Carvalho Chehab 		btv->use_i2c_hw = 1;
35468de959fSMauro Carvalho Chehab 	if (btv->use_i2c_hw) {
35568de959fSMauro Carvalho Chehab 		/* bt878 */
35668de959fSMauro Carvalho Chehab 		strlcpy(btv->c.i2c_adap.name, "bt878",
35768de959fSMauro Carvalho Chehab 			sizeof(btv->c.i2c_adap.name));
35868de959fSMauro Carvalho Chehab 		btv->c.i2c_adap.algo = &bttv_algo;
35968de959fSMauro Carvalho Chehab 	} else {
36068de959fSMauro Carvalho Chehab 		/* bt848 */
36168de959fSMauro Carvalho Chehab 	/* Prevents usage of invalid delay values */
36268de959fSMauro Carvalho Chehab 		if (i2c_udelay<5)
36368de959fSMauro Carvalho Chehab 			i2c_udelay=5;
36468de959fSMauro Carvalho Chehab 
36568de959fSMauro Carvalho Chehab 		strlcpy(btv->c.i2c_adap.name, "bttv",
36668de959fSMauro Carvalho Chehab 			sizeof(btv->c.i2c_adap.name));
367b4b1d040SEzequiel Garcia 		btv->i2c_algo = bttv_i2c_algo_bit_template;
36868de959fSMauro Carvalho Chehab 		btv->i2c_algo.udelay = i2c_udelay;
36968de959fSMauro Carvalho Chehab 		btv->i2c_algo.data = btv;
37068de959fSMauro Carvalho Chehab 		btv->c.i2c_adap.algo_data = &btv->i2c_algo;
37168de959fSMauro Carvalho Chehab 	}
37268de959fSMauro Carvalho Chehab 	btv->c.i2c_adap.owner = THIS_MODULE;
37368de959fSMauro Carvalho Chehab 
37468de959fSMauro Carvalho Chehab 	btv->c.i2c_adap.dev.parent = &btv->c.pci->dev;
37568de959fSMauro Carvalho Chehab 	snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name),
37668de959fSMauro Carvalho Chehab 		 "bt%d #%d [%s]", btv->id, btv->c.nr,
37768de959fSMauro Carvalho Chehab 		 btv->use_i2c_hw ? "hw" : "sw");
37868de959fSMauro Carvalho Chehab 
37968de959fSMauro Carvalho Chehab 	i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev);
38068de959fSMauro Carvalho Chehab 	btv->i2c_client.adapter = &btv->c.i2c_adap;
38168de959fSMauro Carvalho Chehab 
38268de959fSMauro Carvalho Chehab 
38368de959fSMauro Carvalho Chehab 	if (btv->use_i2c_hw) {
38468de959fSMauro Carvalho Chehab 		btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
38568de959fSMauro Carvalho Chehab 	} else {
38668de959fSMauro Carvalho Chehab 		bttv_bit_setscl(btv,1);
38768de959fSMauro Carvalho Chehab 		bttv_bit_setsda(btv,1);
38868de959fSMauro Carvalho Chehab 		btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap);
38968de959fSMauro Carvalho Chehab 	}
39068de959fSMauro Carvalho Chehab 	if (0 == btv->i2c_rc && i2c_scan)
39168de959fSMauro Carvalho Chehab 		do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
39268de959fSMauro Carvalho Chehab 
39368de959fSMauro Carvalho Chehab 	return btv->i2c_rc;
39468de959fSMauro Carvalho Chehab }
395457ba4ceSFrank Schaefer 
396457ba4ceSFrank Schaefer int fini_bttv_i2c(struct bttv *btv)
397457ba4ceSFrank Schaefer {
39899bece77SLinus Torvalds 	if (btv->i2c_rc == 0)
39999bece77SLinus Torvalds 		i2c_del_adapter(&btv->c.i2c_adap);
400457ba4ceSFrank Schaefer 
40199bece77SLinus Torvalds 	return 0;
402457ba4ceSFrank Schaefer }
403