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