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 1024c62e976SGreg Kroah-Hartman static struct i2c_algo_bit_data 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 */ 3154c62e976SGreg Kroah-Hartman void 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 */ 3504c62e976SGreg Kroah-Hartman int 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 } 397457ba4ceSFrank Schaefer 398457ba4ceSFrank Schaefer int fini_bttv_i2c(struct bttv *btv) 399457ba4ceSFrank Schaefer { 400*99bece77SLinus Torvalds if (btv->i2c_rc == 0) 401*99bece77SLinus Torvalds i2c_del_adapter(&btv->c.i2c_adap); 402457ba4ceSFrank Schaefer 403*99bece77SLinus Torvalds return 0; 404457ba4ceSFrank Schaefer } 405