1a6c2ba28Sakpm@osdl.org /* 2f7abcd38SMauro Carvalho Chehab em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices 3a6c2ba28Sakpm@osdl.org 4f7abcd38SMauro Carvalho Chehab Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> 5f7abcd38SMauro Carvalho Chehab Markus Rechberger <mrechberger@gmail.com> 62e7c6dc3SMauro Carvalho Chehab Mauro Carvalho Chehab <mchehab@infradead.org> 7f7abcd38SMauro Carvalho Chehab Sascha Sommer <saschasommer@freenet.de> 8a3ea4bf9SFrank Schaefer Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com> 9a6c2ba28Sakpm@osdl.org 10a6c2ba28Sakpm@osdl.org This program is free software; you can redistribute it and/or modify 11a6c2ba28Sakpm@osdl.org it under the terms of the GNU General Public License as published by 12a6c2ba28Sakpm@osdl.org the Free Software Foundation; either version 2 of the License, or 13a6c2ba28Sakpm@osdl.org (at your option) any later version. 14a6c2ba28Sakpm@osdl.org 15a6c2ba28Sakpm@osdl.org This program is distributed in the hope that it will be useful, 16a6c2ba28Sakpm@osdl.org but WITHOUT ANY WARRANTY; without even the implied warranty of 17a6c2ba28Sakpm@osdl.org MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18a6c2ba28Sakpm@osdl.org GNU General Public License for more details. 19a6c2ba28Sakpm@osdl.org 20a6c2ba28Sakpm@osdl.org You should have received a copy of the GNU General Public License 21a6c2ba28Sakpm@osdl.org along with this program; if not, write to the Free Software 22a6c2ba28Sakpm@osdl.org Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23a6c2ba28Sakpm@osdl.org */ 24a6c2ba28Sakpm@osdl.org 258314d402SMauro Carvalho Chehab #include "em28xx.h" 268314d402SMauro Carvalho Chehab 27a6c2ba28Sakpm@osdl.org #include <linux/module.h> 28a6c2ba28Sakpm@osdl.org #include <linux/kernel.h> 29a6c2ba28Sakpm@osdl.org #include <linux/usb.h> 30a6c2ba28Sakpm@osdl.org #include <linux/i2c.h> 314b83626aSMauro Carvalho Chehab #include <linux/jiffies.h> 32a6c2ba28Sakpm@osdl.org 336c362c8eSMauro Carvalho Chehab #include "tuner-xc2028.h" 345e453dc7SMichael Krufky #include <media/v4l2-common.h> 35d5e52653SMauro Carvalho Chehab #include <media/tuner.h> 36a6c2ba28Sakpm@osdl.org 37a6c2ba28Sakpm@osdl.org /* ----------------------------------------------------------- */ 38a6c2ba28Sakpm@osdl.org 39ff699e6bSDouglas Schilling Landgraf static unsigned int i2c_scan; 40a6c2ba28Sakpm@osdl.org module_param(i2c_scan, int, 0444); 41a6c2ba28Sakpm@osdl.org MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); 42a6c2ba28Sakpm@osdl.org 43ff699e6bSDouglas Schilling Landgraf static unsigned int i2c_debug; 44a6c2ba28Sakpm@osdl.org module_param(i2c_debug, int, 0644); 4550f0a9dfSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I2C transfers)"); 46a6c2ba28Sakpm@osdl.org 47ce8591ffSMauro Carvalho Chehab #define dprintk(level, fmt, arg...) do { \ 48ce8591ffSMauro Carvalho Chehab if (i2c_debug > level) \ 49*29b05e22SMauro Carvalho Chehab dev_printk(KERN_DEBUG, &dev->intf->dev, \ 50ce8591ffSMauro Carvalho Chehab "i2c: %s: " fmt, __func__, ## arg); \ 51ce8591ffSMauro Carvalho Chehab } while (0) 52ce8591ffSMauro Carvalho Chehab 53ce8591ffSMauro Carvalho Chehab 54a6c2ba28Sakpm@osdl.org /* 55f5ae371aSFrank Schaefer * em2800_i2c_send_bytes() 56f5ae371aSFrank Schaefer * send up to 4 bytes to the em2800 i2c device 57596d92d5SMauro Carvalho Chehab */ 58f5ae371aSFrank Schaefer static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) 59596d92d5SMauro Carvalho Chehab { 60d1b7213bSMauro Carvalho Chehab unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); 61596d92d5SMauro Carvalho Chehab int ret; 62a6bad040SFrank Schaefer u8 b2[6]; 63f5ae371aSFrank Schaefer 64f5ae371aSFrank Schaefer if (len < 1 || len > 4) 65f5ae371aSFrank Schaefer return -EOPNOTSUPP; 66f5ae371aSFrank Schaefer 67596d92d5SMauro Carvalho Chehab BUG_ON(len < 1 || len > 4); 68596d92d5SMauro Carvalho Chehab b2[5] = 0x80 + len - 1; 69596d92d5SMauro Carvalho Chehab b2[4] = addr; 70596d92d5SMauro Carvalho Chehab b2[3] = buf[0]; 71596d92d5SMauro Carvalho Chehab if (len > 1) 72596d92d5SMauro Carvalho Chehab b2[2] = buf[1]; 73596d92d5SMauro Carvalho Chehab if (len > 2) 74596d92d5SMauro Carvalho Chehab b2[1] = buf[2]; 75596d92d5SMauro Carvalho Chehab if (len > 3) 76596d92d5SMauro Carvalho Chehab b2[0] = buf[3]; 77596d92d5SMauro Carvalho Chehab 782fcc82d8SFrank Schaefer /* trigger write */ 793acf2809SMauro Carvalho Chehab ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); 80596d92d5SMauro Carvalho Chehab if (ret != 2 + len) { 81*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 82ce8591ffSMauro Carvalho Chehab "failed to trigger write to i2c address 0x%x (error=%i)\n", 83d230d5adSFrank Schaefer addr, ret); 8445f04e82SFrank Schaefer return (ret < 0) ? ret : -EIO; 85596d92d5SMauro Carvalho Chehab } 862fcc82d8SFrank Schaefer /* wait for completion */ 874b83626aSMauro Carvalho Chehab while (time_is_after_jiffies(timeout)) { 883acf2809SMauro Carvalho Chehab ret = dev->em28xx_read_reg(dev, 0x05); 894b83626aSMauro Carvalho Chehab if (ret == 0x80 + len - 1) 90596d92d5SMauro Carvalho Chehab return len; 914b83626aSMauro Carvalho Chehab if (ret == 0x94 + len - 1) { 92ce8591ffSMauro Carvalho Chehab dprintk(1, "R05 returned 0x%02x: I2C ACK error\n", ret); 93e63b009dSMauro Carvalho Chehab return -ENXIO; 944b83626aSMauro Carvalho Chehab } 954b83626aSMauro Carvalho Chehab if (ret < 0) { 96*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 97ce8591ffSMauro Carvalho Chehab "failed to get i2c transfer status from bridge register (error=%i)\n", 98d230d5adSFrank Schaefer ret); 9945f04e82SFrank Schaefer return ret; 10045f04e82SFrank Schaefer } 101e8e41da4SMarkus Rechberger msleep(5); 102596d92d5SMauro Carvalho Chehab } 103ce8591ffSMauro Carvalho Chehab dprintk(0, "write to i2c device at 0x%x timed out\n", addr); 104e63b009dSMauro Carvalho Chehab return -ETIMEDOUT; 105596d92d5SMauro Carvalho Chehab } 106596d92d5SMauro Carvalho Chehab 107596d92d5SMauro Carvalho Chehab /* 108596d92d5SMauro Carvalho Chehab * em2800_i2c_recv_bytes() 1092fcc82d8SFrank Schaefer * read up to 4 bytes from the em2800 i2c device 110596d92d5SMauro Carvalho Chehab */ 111a6bad040SFrank Schaefer static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) 112596d92d5SMauro Carvalho Chehab { 113d1b7213bSMauro Carvalho Chehab unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); 1142fcc82d8SFrank Schaefer u8 buf2[4]; 115596d92d5SMauro Carvalho Chehab int ret; 1162fcc82d8SFrank Schaefer int i; 117f5ae371aSFrank Schaefer 118f5ae371aSFrank Schaefer if (len < 1 || len > 4) 119f5ae371aSFrank Schaefer return -EOPNOTSUPP; 120f5ae371aSFrank Schaefer 1212fcc82d8SFrank Schaefer /* trigger read */ 1222fcc82d8SFrank Schaefer buf2[1] = 0x84 + len - 1; 1232fcc82d8SFrank Schaefer buf2[0] = addr; 1242fcc82d8SFrank Schaefer ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2); 1252fcc82d8SFrank Schaefer if (ret != 2) { 126*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 127ce8591ffSMauro Carvalho Chehab "failed to trigger read from i2c address 0x%x (error=%i)\n", 128d230d5adSFrank Schaefer addr, ret); 1292fcc82d8SFrank Schaefer return (ret < 0) ? ret : -EIO; 1302fcc82d8SFrank Schaefer } 1312fcc82d8SFrank Schaefer 1322fcc82d8SFrank Schaefer /* wait for completion */ 1334b83626aSMauro Carvalho Chehab while (time_is_after_jiffies(timeout)) { 1342fcc82d8SFrank Schaefer ret = dev->em28xx_read_reg(dev, 0x05); 1354b83626aSMauro Carvalho Chehab if (ret == 0x84 + len - 1) 1362fcc82d8SFrank Schaefer break; 1374b83626aSMauro Carvalho Chehab if (ret == 0x94 + len - 1) { 138ce8591ffSMauro Carvalho Chehab dprintk(1, "R05 returned 0x%02x: I2C ACK error\n", 139d845fb3aSMauro Carvalho Chehab ret); 140e63b009dSMauro Carvalho Chehab return -ENXIO; 1414b83626aSMauro Carvalho Chehab } 1424b83626aSMauro Carvalho Chehab if (ret < 0) { 143*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 144ce8591ffSMauro Carvalho Chehab "failed to get i2c transfer status from bridge register (error=%i)\n", 145d230d5adSFrank Schaefer ret); 146596d92d5SMauro Carvalho Chehab return ret; 147596d92d5SMauro Carvalho Chehab } 1482fcc82d8SFrank Schaefer msleep(5); 1492fcc82d8SFrank Schaefer } 15050f0a9dfSMauro Carvalho Chehab if (ret != 0x84 + len - 1) { 151ce8591ffSMauro Carvalho Chehab dprintk(0, "read from i2c device at 0x%x timed out\n", addr); 15250f0a9dfSMauro Carvalho Chehab } 1532fcc82d8SFrank Schaefer 1542fcc82d8SFrank Schaefer /* get the received message */ 1552fcc82d8SFrank Schaefer ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len); 1562fcc82d8SFrank Schaefer if (ret != len) { 157*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 158ce8591ffSMauro Carvalho Chehab "reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n", 159d230d5adSFrank Schaefer addr, ret); 1602fcc82d8SFrank Schaefer return (ret < 0) ? ret : -EIO; 1612fcc82d8SFrank Schaefer } 1622fcc82d8SFrank Schaefer for (i = 0; i < len; i++) 1632fcc82d8SFrank Schaefer buf[i] = buf2[len - 1 - i]; 1642fcc82d8SFrank Schaefer 165596d92d5SMauro Carvalho Chehab return ret; 166596d92d5SMauro Carvalho Chehab } 1672fcc82d8SFrank Schaefer 1682fcc82d8SFrank Schaefer /* 1692fcc82d8SFrank Schaefer * em2800_i2c_check_for_device() 1702fcc82d8SFrank Schaefer * check if there is an i2c device at the supplied address 1712fcc82d8SFrank Schaefer */ 1722fcc82d8SFrank Schaefer static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr) 1732fcc82d8SFrank Schaefer { 1742fcc82d8SFrank Schaefer u8 buf; 1752fcc82d8SFrank Schaefer int ret; 1762fcc82d8SFrank Schaefer 1772fcc82d8SFrank Schaefer ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1); 1782fcc82d8SFrank Schaefer if (ret == 1) 1792fcc82d8SFrank Schaefer return 0; 1802fcc82d8SFrank Schaefer return (ret < 0) ? ret : -EIO; 181596d92d5SMauro Carvalho Chehab } 182596d92d5SMauro Carvalho Chehab 183596d92d5SMauro Carvalho Chehab /* 1843acf2809SMauro Carvalho Chehab * em28xx_i2c_send_bytes() 185a6c2ba28Sakpm@osdl.org */ 186a6bad040SFrank Schaefer static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, 187a6bad040SFrank Schaefer u16 len, int stop) 188a6c2ba28Sakpm@osdl.org { 189d1b7213bSMauro Carvalho Chehab unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); 1904b83626aSMauro Carvalho Chehab int ret; 191a6c2ba28Sakpm@osdl.org 192f5ae371aSFrank Schaefer if (len < 1 || len > 64) 193f5ae371aSFrank Schaefer return -EOPNOTSUPP; 194fa74aca3SFrank Schaefer /* 195fa74aca3SFrank Schaefer * NOTE: limited by the USB ctrl message constraints 196fa74aca3SFrank Schaefer * Zero length reads always succeed, even if no device is connected 197fa74aca3SFrank Schaefer */ 198f5ae371aSFrank Schaefer 19945f04e82SFrank Schaefer /* Write to i2c device */ 20045f04e82SFrank Schaefer ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); 20145f04e82SFrank Schaefer if (ret != len) { 20245f04e82SFrank Schaefer if (ret < 0) { 203*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 204ce8591ffSMauro Carvalho Chehab "writing to i2c device at 0x%x failed (error=%i)\n", 205d230d5adSFrank Schaefer addr, ret); 20645f04e82SFrank Schaefer return ret; 20745f04e82SFrank Schaefer } else { 208*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 209ce8591ffSMauro Carvalho Chehab "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n", 21045f04e82SFrank Schaefer len, addr, ret); 21145f04e82SFrank Schaefer return -EIO; 21245f04e82SFrank Schaefer } 21345f04e82SFrank Schaefer } 214a6c2ba28Sakpm@osdl.org 2154b83626aSMauro Carvalho Chehab /* wait for completion */ 2164b83626aSMauro Carvalho Chehab while (time_is_after_jiffies(timeout)) { 217bbc70e64SMauro Carvalho Chehab ret = dev->em28xx_read_reg(dev, 0x05); 2184b83626aSMauro Carvalho Chehab if (ret == 0) /* success */ 21945f04e82SFrank Schaefer return len; 2204b83626aSMauro Carvalho Chehab if (ret == 0x10) { 221ce8591ffSMauro Carvalho Chehab dprintk(1, "I2C ACK error on writing to addr 0x%02x\n", 222d845fb3aSMauro Carvalho Chehab addr); 223e63b009dSMauro Carvalho Chehab return -ENXIO; 2244b83626aSMauro Carvalho Chehab } 2254b83626aSMauro Carvalho Chehab if (ret < 0) { 226*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 227ce8591ffSMauro Carvalho Chehab "failed to get i2c transfer status from bridge register (error=%i)\n", 228d230d5adSFrank Schaefer ret); 22945f04e82SFrank Schaefer return ret; 230bbc70e64SMauro Carvalho Chehab } 23145f04e82SFrank Schaefer msleep(5); 232fa74aca3SFrank Schaefer /* 233fa74aca3SFrank Schaefer * NOTE: do we really have to wait for success ? 234fa74aca3SFrank Schaefer * Never seen anything else than 0x00 or 0x10 235fa74aca3SFrank Schaefer * (even with high payload) ... 236fa74aca3SFrank Schaefer */ 23745f04e82SFrank Schaefer } 238123a17d1SFrank Schaefer 239123a17d1SFrank Schaefer if (ret == 0x02 || ret == 0x04) { 240123a17d1SFrank Schaefer /* NOTE: these errors seem to be related to clock stretching */ 241ce8591ffSMauro Carvalho Chehab dprintk(0, 242ce8591ffSMauro Carvalho Chehab "write to i2c device at 0x%x timed out (status=%i)\n", 24350f0a9dfSMauro Carvalho Chehab addr, ret); 244e63b009dSMauro Carvalho Chehab return -ETIMEDOUT; 245a6c2ba28Sakpm@osdl.org } 246a6c2ba28Sakpm@osdl.org 247*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 248ce8591ffSMauro Carvalho Chehab "write to i2c device at 0x%x failed with unknown error (status=%i)\n", 249123a17d1SFrank Schaefer addr, ret); 250123a17d1SFrank Schaefer return -EIO; 251123a17d1SFrank Schaefer } 252123a17d1SFrank Schaefer 253a6c2ba28Sakpm@osdl.org /* 2543acf2809SMauro Carvalho Chehab * em28xx_i2c_recv_bytes() 255a6c2ba28Sakpm@osdl.org * read a byte from the i2c device 256a6c2ba28Sakpm@osdl.org */ 257a6bad040SFrank Schaefer static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len) 258a6c2ba28Sakpm@osdl.org { 259a6c2ba28Sakpm@osdl.org int ret; 260f5ae371aSFrank Schaefer 261f5ae371aSFrank Schaefer if (len < 1 || len > 64) 262f5ae371aSFrank Schaefer return -EOPNOTSUPP; 263fa74aca3SFrank Schaefer /* 264fa74aca3SFrank Schaefer * NOTE: limited by the USB ctrl message constraints 265fa74aca3SFrank Schaefer * Zero length reads always succeed, even if no device is connected 266fa74aca3SFrank Schaefer */ 267f5ae371aSFrank Schaefer 26845f04e82SFrank Schaefer /* Read data from i2c device */ 2693acf2809SMauro Carvalho Chehab ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); 270a6c2ba28Sakpm@osdl.org if (ret < 0) { 271*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 272ce8591ffSMauro Carvalho Chehab "reading from i2c device at 0x%x failed (error=%i)\n", 2737f6301d1SFrank Schaefer addr, ret); 27445f04e82SFrank Schaefer return ret; 27545f04e82SFrank Schaefer } 276fa74aca3SFrank Schaefer /* 277fa74aca3SFrank Schaefer * NOTE: some devices with two i2c busses have the bad habit to return 0 2787f6301d1SFrank Schaefer * bytes if we are on bus B AND there was no write attempt to the 2797f6301d1SFrank Schaefer * specified slave address before AND no device is present at the 2807f6301d1SFrank Schaefer * requested slave address. 281e63b009dSMauro Carvalho Chehab * Anyway, the next check will fail with -ENXIO in this case, so avoid 2827f6301d1SFrank Schaefer * spamming the system log on device probing and do nothing here. 2837f6301d1SFrank Schaefer */ 28445f04e82SFrank Schaefer 28545f04e82SFrank Schaefer /* Check success of the i2c operation */ 28645f04e82SFrank Schaefer ret = dev->em28xx_read_reg(dev, 0x05); 2874b83626aSMauro Carvalho Chehab if (ret == 0) /* success */ 2884b83626aSMauro Carvalho Chehab return len; 28945f04e82SFrank Schaefer if (ret < 0) { 290*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 291ce8591ffSMauro Carvalho Chehab "failed to get i2c transfer status from bridge register (error=%i)\n", 292d230d5adSFrank Schaefer ret); 293a6c2ba28Sakpm@osdl.org return ret; 294a6c2ba28Sakpm@osdl.org } 295d845fb3aSMauro Carvalho Chehab if (ret == 0x10) { 296ce8591ffSMauro Carvalho Chehab dprintk(1, "I2C ACK error on writing to addr 0x%02x\n", 297d845fb3aSMauro Carvalho Chehab addr); 298e63b009dSMauro Carvalho Chehab return -ENXIO; 299d845fb3aSMauro Carvalho Chehab } 3004b83626aSMauro Carvalho Chehab 301123a17d1SFrank Schaefer if (ret == 0x02 || ret == 0x04) { 302123a17d1SFrank Schaefer /* NOTE: these errors seem to be related to clock stretching */ 303ce8591ffSMauro Carvalho Chehab dprintk(0, 304ce8591ffSMauro Carvalho Chehab "write to i2c device at 0x%x timed out (status=%i)\n", 305123a17d1SFrank Schaefer addr, ret); 306e63b009dSMauro Carvalho Chehab return -ETIMEDOUT; 30745f04e82SFrank Schaefer } 308a6c2ba28Sakpm@osdl.org 309*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 310ce8591ffSMauro Carvalho Chehab "write to i2c device at 0x%x failed with unknown error (status=%i)\n", 311123a17d1SFrank Schaefer addr, ret); 312123a17d1SFrank Schaefer return -EIO; 313123a17d1SFrank Schaefer } 314123a17d1SFrank Schaefer 315a6c2ba28Sakpm@osdl.org /* 3163acf2809SMauro Carvalho Chehab * em28xx_i2c_check_for_device() 317a6c2ba28Sakpm@osdl.org * check if there is a i2c_device at the supplied address 318a6c2ba28Sakpm@osdl.org */ 319a6bad040SFrank Schaefer static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr) 320a6c2ba28Sakpm@osdl.org { 321a6c2ba28Sakpm@osdl.org int ret; 32245f04e82SFrank Schaefer u8 buf; 323a6c2ba28Sakpm@osdl.org 32445f04e82SFrank Schaefer ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1); 32545f04e82SFrank Schaefer if (ret == 1) 326a6c2ba28Sakpm@osdl.org return 0; 32745f04e82SFrank Schaefer return (ret < 0) ? ret : -EIO; 328a6c2ba28Sakpm@osdl.org } 329a6c2ba28Sakpm@osdl.org 330a6c2ba28Sakpm@osdl.org /* 331a3ea4bf9SFrank Schaefer * em25xx_bus_B_send_bytes 332a3ea4bf9SFrank Schaefer * write bytes to the i2c device 333a3ea4bf9SFrank Schaefer */ 334a3ea4bf9SFrank Schaefer static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, 335a3ea4bf9SFrank Schaefer u16 len) 336a3ea4bf9SFrank Schaefer { 337a3ea4bf9SFrank Schaefer int ret; 338a3ea4bf9SFrank Schaefer 339a3ea4bf9SFrank Schaefer if (len < 1 || len > 64) 340a3ea4bf9SFrank Schaefer return -EOPNOTSUPP; 341a3ea4bf9SFrank Schaefer /* 342a3ea4bf9SFrank Schaefer * NOTE: limited by the USB ctrl message constraints 343a3ea4bf9SFrank Schaefer * Zero length reads always succeed, even if no device is connected 344a3ea4bf9SFrank Schaefer */ 345a3ea4bf9SFrank Schaefer 346a3ea4bf9SFrank Schaefer /* Set register and write value */ 347a3ea4bf9SFrank Schaefer ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len); 348a3ea4bf9SFrank Schaefer if (ret != len) { 349a3ea4bf9SFrank Schaefer if (ret < 0) { 350*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 351ce8591ffSMauro Carvalho Chehab "writing to i2c device at 0x%x failed (error=%i)\n", 352a3ea4bf9SFrank Schaefer addr, ret); 353a3ea4bf9SFrank Schaefer return ret; 354a3ea4bf9SFrank Schaefer } else { 355*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 356ce8591ffSMauro Carvalho Chehab "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n", 357a3ea4bf9SFrank Schaefer len, addr, ret); 358a3ea4bf9SFrank Schaefer return -EIO; 359a3ea4bf9SFrank Schaefer } 360a3ea4bf9SFrank Schaefer } 361a3ea4bf9SFrank Schaefer /* Check success */ 362a3ea4bf9SFrank Schaefer ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000); 363a3ea4bf9SFrank Schaefer /* 364a3ea4bf9SFrank Schaefer * NOTE: the only error we've seen so far is 365a3ea4bf9SFrank Schaefer * 0x01 when the slave device is not present 366a3ea4bf9SFrank Schaefer */ 367a3ea4bf9SFrank Schaefer if (!ret) 368a3ea4bf9SFrank Schaefer return len; 369d845fb3aSMauro Carvalho Chehab else if (ret > 0) { 370ce8591ffSMauro Carvalho Chehab dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret); 371e63b009dSMauro Carvalho Chehab return -ENXIO; 372d845fb3aSMauro Carvalho Chehab } 373a3ea4bf9SFrank Schaefer 374a3ea4bf9SFrank Schaefer return ret; 375a3ea4bf9SFrank Schaefer /* 376a3ea4bf9SFrank Schaefer * NOTE: With chip types (other chip IDs) which actually don't support 377a3ea4bf9SFrank Schaefer * this operation, it seems to succeed ALWAYS ! (even if there is no 378a3ea4bf9SFrank Schaefer * slave device or even no second i2c bus provided) 379a3ea4bf9SFrank Schaefer */ 380a3ea4bf9SFrank Schaefer } 381a3ea4bf9SFrank Schaefer 382a3ea4bf9SFrank Schaefer /* 383a3ea4bf9SFrank Schaefer * em25xx_bus_B_recv_bytes 384a3ea4bf9SFrank Schaefer * read bytes from the i2c device 385a3ea4bf9SFrank Schaefer */ 386a3ea4bf9SFrank Schaefer static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, 387a3ea4bf9SFrank Schaefer u16 len) 388a3ea4bf9SFrank Schaefer { 389a3ea4bf9SFrank Schaefer int ret; 390a3ea4bf9SFrank Schaefer 391a3ea4bf9SFrank Schaefer if (len < 1 || len > 64) 392a3ea4bf9SFrank Schaefer return -EOPNOTSUPP; 393a3ea4bf9SFrank Schaefer /* 394a3ea4bf9SFrank Schaefer * NOTE: limited by the USB ctrl message constraints 395a3ea4bf9SFrank Schaefer * Zero length reads always succeed, even if no device is connected 396a3ea4bf9SFrank Schaefer */ 397a3ea4bf9SFrank Schaefer 398a3ea4bf9SFrank Schaefer /* Read value */ 399a3ea4bf9SFrank Schaefer ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len); 400a3ea4bf9SFrank Schaefer if (ret < 0) { 401*29b05e22SMauro Carvalho Chehab dev_warn(&dev->intf->dev, 402ce8591ffSMauro Carvalho Chehab "reading from i2c device at 0x%x failed (error=%i)\n", 403a3ea4bf9SFrank Schaefer addr, ret); 404a3ea4bf9SFrank Schaefer return ret; 405a3ea4bf9SFrank Schaefer } 406a3ea4bf9SFrank Schaefer /* 407a3ea4bf9SFrank Schaefer * NOTE: some devices with two i2c busses have the bad habit to return 0 408a3ea4bf9SFrank Schaefer * bytes if we are on bus B AND there was no write attempt to the 409a3ea4bf9SFrank Schaefer * specified slave address before AND no device is present at the 410a3ea4bf9SFrank Schaefer * requested slave address. 411e63b009dSMauro Carvalho Chehab * Anyway, the next check will fail with -ENXIO in this case, so avoid 412a3ea4bf9SFrank Schaefer * spamming the system log on device probing and do nothing here. 413a3ea4bf9SFrank Schaefer */ 414a3ea4bf9SFrank Schaefer 415a3ea4bf9SFrank Schaefer /* Check success */ 416a3ea4bf9SFrank Schaefer ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000); 417a3ea4bf9SFrank Schaefer /* 418a3ea4bf9SFrank Schaefer * NOTE: the only error we've seen so far is 419a3ea4bf9SFrank Schaefer * 0x01 when the slave device is not present 420a3ea4bf9SFrank Schaefer */ 421a3ea4bf9SFrank Schaefer if (!ret) 422a3ea4bf9SFrank Schaefer return len; 423d845fb3aSMauro Carvalho Chehab else if (ret > 0) { 424ce8591ffSMauro Carvalho Chehab dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret); 425e63b009dSMauro Carvalho Chehab return -ENXIO; 426d845fb3aSMauro Carvalho Chehab } 427a3ea4bf9SFrank Schaefer 428a3ea4bf9SFrank Schaefer return ret; 429a3ea4bf9SFrank Schaefer /* 430a3ea4bf9SFrank Schaefer * NOTE: With chip types (other chip IDs) which actually don't support 431a3ea4bf9SFrank Schaefer * this operation, it seems to succeed ALWAYS ! (even if there is no 432a3ea4bf9SFrank Schaefer * slave device or even no second i2c bus provided) 433a3ea4bf9SFrank Schaefer */ 434a3ea4bf9SFrank Schaefer } 435a3ea4bf9SFrank Schaefer 436a3ea4bf9SFrank Schaefer /* 437a3ea4bf9SFrank Schaefer * em25xx_bus_B_check_for_device() 438a3ea4bf9SFrank Schaefer * check if there is a i2c device at the supplied address 439a3ea4bf9SFrank Schaefer */ 440a3ea4bf9SFrank Schaefer static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr) 441a3ea4bf9SFrank Schaefer { 442a3ea4bf9SFrank Schaefer u8 buf; 443a3ea4bf9SFrank Schaefer int ret; 444a3ea4bf9SFrank Schaefer 445a3ea4bf9SFrank Schaefer ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1); 446a3ea4bf9SFrank Schaefer if (ret < 0) 447a3ea4bf9SFrank Schaefer return ret; 448a3ea4bf9SFrank Schaefer 449a3ea4bf9SFrank Schaefer return 0; 450a3ea4bf9SFrank Schaefer /* 451a3ea4bf9SFrank Schaefer * NOTE: With chips which do not support this operation, 452a3ea4bf9SFrank Schaefer * it seems to succeed ALWAYS ! (even if no device connected) 453a3ea4bf9SFrank Schaefer */ 454a3ea4bf9SFrank Schaefer } 455a3ea4bf9SFrank Schaefer 456a3ea4bf9SFrank Schaefer static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr) 457a3ea4bf9SFrank Schaefer { 458a3ea4bf9SFrank Schaefer struct em28xx *dev = i2c_bus->dev; 459a3ea4bf9SFrank Schaefer int rc = -EOPNOTSUPP; 460a3ea4bf9SFrank Schaefer 461a3ea4bf9SFrank Schaefer if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) 462a3ea4bf9SFrank Schaefer rc = em28xx_i2c_check_for_device(dev, addr); 463a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) 464a3ea4bf9SFrank Schaefer rc = em2800_i2c_check_for_device(dev, addr); 465a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) 466a3ea4bf9SFrank Schaefer rc = em25xx_bus_B_check_for_device(dev, addr); 467a3ea4bf9SFrank Schaefer return rc; 468a3ea4bf9SFrank Schaefer } 469a3ea4bf9SFrank Schaefer 470a3ea4bf9SFrank Schaefer static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus, 471a3ea4bf9SFrank Schaefer struct i2c_msg msg) 472a3ea4bf9SFrank Schaefer { 473a3ea4bf9SFrank Schaefer struct em28xx *dev = i2c_bus->dev; 474a3ea4bf9SFrank Schaefer u16 addr = msg.addr << 1; 47550f0a9dfSMauro Carvalho Chehab int rc = -EOPNOTSUPP; 476a3ea4bf9SFrank Schaefer 477a3ea4bf9SFrank Schaefer if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) 478a3ea4bf9SFrank Schaefer rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len); 479a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) 480a3ea4bf9SFrank Schaefer rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len); 481a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) 482a3ea4bf9SFrank Schaefer rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len); 483a3ea4bf9SFrank Schaefer return rc; 484a3ea4bf9SFrank Schaefer } 485a3ea4bf9SFrank Schaefer 486a3ea4bf9SFrank Schaefer static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus, 487a3ea4bf9SFrank Schaefer struct i2c_msg msg, int stop) 488a3ea4bf9SFrank Schaefer { 489a3ea4bf9SFrank Schaefer struct em28xx *dev = i2c_bus->dev; 490a3ea4bf9SFrank Schaefer u16 addr = msg.addr << 1; 49150f0a9dfSMauro Carvalho Chehab int rc = -EOPNOTSUPP; 492a3ea4bf9SFrank Schaefer 493a3ea4bf9SFrank Schaefer if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) 494a3ea4bf9SFrank Schaefer rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop); 495a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) 496a3ea4bf9SFrank Schaefer rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len); 497a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) 498a3ea4bf9SFrank Schaefer rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len); 499a3ea4bf9SFrank Schaefer return rc; 500a3ea4bf9SFrank Schaefer } 501a3ea4bf9SFrank Schaefer 502a3ea4bf9SFrank Schaefer /* 5033acf2809SMauro Carvalho Chehab * em28xx_i2c_xfer() 504a6c2ba28Sakpm@osdl.org * the main i2c transfer function 505a6c2ba28Sakpm@osdl.org */ 5063acf2809SMauro Carvalho Chehab static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, 507a6c2ba28Sakpm@osdl.org struct i2c_msg msgs[], int num) 508a6c2ba28Sakpm@osdl.org { 509aab3125cSMauro Carvalho Chehab struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data; 510aab3125cSMauro Carvalho Chehab struct em28xx *dev = i2c_bus->dev; 511aab3125cSMauro Carvalho Chehab unsigned bus = i2c_bus->bus; 512a3ea4bf9SFrank Schaefer int addr, rc, i; 5133190fbeeSMauro Carvalho Chehab u8 reg; 514a6c2ba28Sakpm@osdl.org 515cc5c5d20SShuah Khan /* prevent i2c xfer attempts after device is disconnected 516cc5c5d20SShuah Khan some fe's try to do i2c writes/reads from their release 517cc5c5d20SShuah Khan interfaces when called in disconnect path */ 518cc5c5d20SShuah Khan if (dev->disconnected) 519cc5c5d20SShuah Khan return -ENODEV; 520cc5c5d20SShuah Khan 521e44c153bSDan Carpenter if (!rt_mutex_trylock(&dev->i2c_bus_lock)) 522e44c153bSDan Carpenter return -EAGAIN; 523aab3125cSMauro Carvalho Chehab 524aab3125cSMauro Carvalho Chehab /* Switch I2C bus if needed */ 525a3ea4bf9SFrank Schaefer if (bus != dev->cur_i2c_bus && 526a3ea4bf9SFrank Schaefer i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) { 527aab3125cSMauro Carvalho Chehab if (bus == 1) 5283190fbeeSMauro Carvalho Chehab reg = EM2874_I2C_SECONDARY_BUS_SELECT; 529aab3125cSMauro Carvalho Chehab else 5303190fbeeSMauro Carvalho Chehab reg = 0; 5313190fbeeSMauro Carvalho Chehab em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg, 5323190fbeeSMauro Carvalho Chehab EM2874_I2C_SECONDARY_BUS_SELECT); 533aab3125cSMauro Carvalho Chehab dev->cur_i2c_bus = bus; 534aab3125cSMauro Carvalho Chehab } 535aab3125cSMauro Carvalho Chehab 536aab3125cSMauro Carvalho Chehab if (num <= 0) { 537aab3125cSMauro Carvalho Chehab rt_mutex_unlock(&dev->i2c_bus_lock); 538a6c2ba28Sakpm@osdl.org return 0; 539aab3125cSMauro Carvalho Chehab } 540a6c2ba28Sakpm@osdl.org for (i = 0; i < num; i++) { 541a6c2ba28Sakpm@osdl.org addr = msgs[i].addr << 1; 542e63b009dSMauro Carvalho Chehab if (!msgs[i].len) { 543e63b009dSMauro Carvalho Chehab /* 544e63b009dSMauro Carvalho Chehab * no len: check only for device presence 545e63b009dSMauro Carvalho Chehab * This code is only called during device probe. 546e63b009dSMauro Carvalho Chehab */ 547a3ea4bf9SFrank Schaefer rc = i2c_check_for_device(i2c_bus, addr); 548ce8591ffSMauro Carvalho Chehab 549ce8591ffSMauro Carvalho Chehab if (rc == -ENXIO) 55050f0a9dfSMauro Carvalho Chehab rc = -ENODEV; 551596d92d5SMauro Carvalho Chehab } else if (msgs[i].flags & I2C_M_RD) { 552a6c2ba28Sakpm@osdl.org /* read bytes */ 553a3ea4bf9SFrank Schaefer rc = i2c_recv_bytes(i2c_bus, msgs[i]); 554a6c2ba28Sakpm@osdl.org } else { 555a6c2ba28Sakpm@osdl.org /* write bytes */ 556a3ea4bf9SFrank Schaefer rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1); 557e8e41da4SMarkus Rechberger } 558ce8591ffSMauro Carvalho Chehab 559ce8591ffSMauro Carvalho Chehab if (rc < 0) 560ce8591ffSMauro Carvalho Chehab goto error; 561ce8591ffSMauro Carvalho Chehab 562ce8591ffSMauro Carvalho Chehab dprintk(2, "%s %s addr=%02x len=%d: %*ph\n", 563ce8591ffSMauro Carvalho Chehab (msgs[i].flags & I2C_M_RD) ? "read" : "write", 564ce8591ffSMauro Carvalho Chehab i == num - 1 ? "stop" : "nonstop", 565ce8591ffSMauro Carvalho Chehab addr, msgs[i].len, 566ce8591ffSMauro Carvalho Chehab msgs[i].len, msgs[i].buf); 567a6c2ba28Sakpm@osdl.org } 568a6c2ba28Sakpm@osdl.org 569aab3125cSMauro Carvalho Chehab rt_mutex_unlock(&dev->i2c_bus_lock); 570a6c2ba28Sakpm@osdl.org return num; 571ce8591ffSMauro Carvalho Chehab 572ce8591ffSMauro Carvalho Chehab error: 573ce8591ffSMauro Carvalho Chehab dprintk(2, "%s %s addr=%02x len=%d: %sERROR: %i\n", 574ce8591ffSMauro Carvalho Chehab (msgs[i].flags & I2C_M_RD) ? "read" : "write", 575ce8591ffSMauro Carvalho Chehab i == num - 1 ? "stop" : "nonstop", 576ce8591ffSMauro Carvalho Chehab addr, msgs[i].len, 577ce8591ffSMauro Carvalho Chehab (rc == -ENODEV) ? "no device " : "", 578ce8591ffSMauro Carvalho Chehab rc); 579ce8591ffSMauro Carvalho Chehab 580ce8591ffSMauro Carvalho Chehab rt_mutex_unlock(&dev->i2c_bus_lock); 581ce8591ffSMauro Carvalho Chehab return rc; 582a6c2ba28Sakpm@osdl.org } 583a6c2ba28Sakpm@osdl.org 584fa74aca3SFrank Schaefer /* 585fa74aca3SFrank Schaefer * based on linux/sunrpc/svcauth.h and linux/hash.h 58603910cc3SMauro Carvalho Chehab * The original hash function returns a different value, if arch is x86_64 58703910cc3SMauro Carvalho Chehab * or i386. 58803910cc3SMauro Carvalho Chehab */ 58903910cc3SMauro Carvalho Chehab static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) 59003910cc3SMauro Carvalho Chehab { 59103910cc3SMauro Carvalho Chehab unsigned long hash = 0; 59203910cc3SMauro Carvalho Chehab unsigned long l = 0; 59303910cc3SMauro Carvalho Chehab int len = 0; 59403910cc3SMauro Carvalho Chehab unsigned char c; 595fdf1bc9fSMauro Carvalho Chehab 59603910cc3SMauro Carvalho Chehab do { 59703910cc3SMauro Carvalho Chehab if (len == length) { 59803910cc3SMauro Carvalho Chehab c = (char)len; 59903910cc3SMauro Carvalho Chehab len = -1; 60003910cc3SMauro Carvalho Chehab } else 60103910cc3SMauro Carvalho Chehab c = *buf++; 60203910cc3SMauro Carvalho Chehab l = (l << 8) | c; 60303910cc3SMauro Carvalho Chehab len++; 60403910cc3SMauro Carvalho Chehab if ((len & (32 / 8 - 1)) == 0) 60503910cc3SMauro Carvalho Chehab hash = ((hash^l) * 0x9e370001UL); 60603910cc3SMauro Carvalho Chehab } while (len); 60703910cc3SMauro Carvalho Chehab 60803910cc3SMauro Carvalho Chehab return (hash >> (32 - bits)) & 0xffffffffUL; 60903910cc3SMauro Carvalho Chehab } 61003910cc3SMauro Carvalho Chehab 611fa74aca3SFrank Schaefer /* 612fa74aca3SFrank Schaefer * Helper function to read data blocks from i2c clients with 8 or 16 bit 613fa74aca3SFrank Schaefer * address width, 8 bit register width and auto incrementation been activated 614fa74aca3SFrank Schaefer */ 615aab3125cSMauro Carvalho Chehab static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr, 616aab3125cSMauro Carvalho Chehab bool addr_w16, u16 len, u8 *data) 617d832c5b2SFrank Schaefer { 618d832c5b2SFrank Schaefer int remain = len, rsize, rsize_max, ret; 619d832c5b2SFrank Schaefer u8 buf[2]; 620d832c5b2SFrank Schaefer 621d832c5b2SFrank Schaefer /* Sanity check */ 622d832c5b2SFrank Schaefer if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1)) 623d832c5b2SFrank Schaefer return -EINVAL; 624d832c5b2SFrank Schaefer /* Select address */ 625d832c5b2SFrank Schaefer buf[0] = addr >> 8; 626d832c5b2SFrank Schaefer buf[1] = addr & 0xff; 627aab3125cSMauro Carvalho Chehab ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16); 628d832c5b2SFrank Schaefer if (ret < 0) 629d832c5b2SFrank Schaefer return ret; 630d832c5b2SFrank Schaefer /* Read data */ 631d832c5b2SFrank Schaefer if (dev->board.is_em2800) 632d832c5b2SFrank Schaefer rsize_max = 4; 633d832c5b2SFrank Schaefer else 634d832c5b2SFrank Schaefer rsize_max = 64; 635d832c5b2SFrank Schaefer while (remain > 0) { 636d832c5b2SFrank Schaefer if (remain > rsize_max) 637d832c5b2SFrank Schaefer rsize = rsize_max; 638d832c5b2SFrank Schaefer else 639d832c5b2SFrank Schaefer rsize = remain; 640d832c5b2SFrank Schaefer 641aab3125cSMauro Carvalho Chehab ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize); 642d832c5b2SFrank Schaefer if (ret < 0) 643d832c5b2SFrank Schaefer return ret; 644d832c5b2SFrank Schaefer 645d832c5b2SFrank Schaefer remain -= rsize; 646d832c5b2SFrank Schaefer data += rsize; 647d832c5b2SFrank Schaefer } 648d832c5b2SFrank Schaefer 649d832c5b2SFrank Schaefer return len; 650d832c5b2SFrank Schaefer } 651d832c5b2SFrank Schaefer 652aab3125cSMauro Carvalho Chehab static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus, 653aab3125cSMauro Carvalho Chehab u8 **eedata, u16 *eedata_len) 654a6c2ba28Sakpm@osdl.org { 655510e884cSFrank Schaefer const u16 len = 256; 656fa74aca3SFrank Schaefer /* 657fa74aca3SFrank Schaefer * FIXME common length/size for bytes to read, to display, hash 658510e884cSFrank Schaefer * calculation and returned device dataset. Simplifies the code a lot, 659fa74aca3SFrank Schaefer * but we might have to deal with multiple sizes in the future ! 660fa74aca3SFrank Schaefer */ 66150f0a9dfSMauro Carvalho Chehab int err; 662510e884cSFrank Schaefer struct em28xx_eeprom *dev_config; 663510e884cSFrank Schaefer u8 buf, *data; 664a6c2ba28Sakpm@osdl.org 665a217968fSFrank Schaefer *eedata = NULL; 666510e884cSFrank Schaefer *eedata_len = 0; 667a217968fSFrank Schaefer 668aab3125cSMauro Carvalho Chehab /* EEPROM is always on i2c bus 0 on all known devices. */ 669aab3125cSMauro Carvalho Chehab 670aab3125cSMauro Carvalho Chehab dev->i2c_client[bus].addr = 0xa0 >> 1; 671596d92d5SMauro Carvalho Chehab 672596d92d5SMauro Carvalho Chehab /* Check if board has eeprom */ 673aab3125cSMauro Carvalho Chehab err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0); 674f2a01a00SDouglas Schilling Landgraf if (err < 0) { 675*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "board has no eeprom\n"); 676c41109fcSMauro Carvalho Chehab return -ENODEV; 677f2a01a00SDouglas Schilling Landgraf } 678596d92d5SMauro Carvalho Chehab 679a217968fSFrank Schaefer data = kzalloc(len, GFP_KERNEL); 680a217968fSFrank Schaefer if (data == NULL) 681a217968fSFrank Schaefer return -ENOMEM; 682a217968fSFrank Schaefer 683d832c5b2SFrank Schaefer /* Read EEPROM content */ 684aab3125cSMauro Carvalho Chehab err = em28xx_i2c_read_block(dev, bus, 0x0000, 685aab3125cSMauro Carvalho Chehab dev->eeprom_addrwidth_16bit, 686a217968fSFrank Schaefer len, data); 687d832c5b2SFrank Schaefer if (err != len) { 688*29b05e22SMauro Carvalho Chehab dev_err(&dev->intf->dev, 689ce8591ffSMauro Carvalho Chehab "failed to read eeprom (err=%d)\n", err); 690510e884cSFrank Schaefer goto error; 691a6c2ba28Sakpm@osdl.org } 69290271964SFrank Schaefer 69350f0a9dfSMauro Carvalho Chehab if (i2c_debug) { 69487b52439SFrank Schaefer /* Display eeprom content */ 695ce8591ffSMauro Carvalho Chehab print_hex_dump(KERN_DEBUG, "em28xx eeprom ", DUMP_PREFIX_OFFSET, 69650f0a9dfSMauro Carvalho Chehab 16, 1, data, len, true); 69750f0a9dfSMauro Carvalho Chehab 69887b52439SFrank Schaefer if (dev->eeprom_addrwidth_16bit) 699*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 700ce8591ffSMauro Carvalho Chehab "eeprom %06x: ... (skipped)\n", 256); 70187b52439SFrank Schaefer } 702a6c2ba28Sakpm@osdl.org 70387b52439SFrank Schaefer if (dev->eeprom_addrwidth_16bit && 704a217968fSFrank Schaefer data[0] == 0x26 && data[3] == 0x00) { 70587b52439SFrank Schaefer /* new eeprom format; size 4-64kb */ 706510e884cSFrank Schaefer u16 mc_start; 707510e884cSFrank Schaefer u16 hwconf_offset; 708510e884cSFrank Schaefer 709a217968fSFrank Schaefer dev->hash = em28xx_hash_mem(data, len, 32); 710510e884cSFrank Schaefer mc_start = (data[1] << 8) + 4; /* usually 0x0004 */ 711510e884cSFrank Schaefer 712*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 713ce8591ffSMauro Carvalho Chehab "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n", 714510e884cSFrank Schaefer data[0], data[1], data[2], data[3], dev->hash); 715*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 716ce8591ffSMauro Carvalho Chehab "EEPROM info:\n"); 717*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 718ce8591ffSMauro Carvalho Chehab "\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n", 719510e884cSFrank Schaefer mc_start, data[2]); 720fa74aca3SFrank Schaefer /* 721fa74aca3SFrank Schaefer * boot configuration (address 0x0002): 72287b52439SFrank Schaefer * [0] microcode download speed: 1 = 400 kHz; 0 = 100 kHz 72387b52439SFrank Schaefer * [1] always selects 12 kb RAM 72487b52439SFrank Schaefer * [2] USB device speed: 1 = force Full Speed; 0 = auto detect 72587b52439SFrank Schaefer * [4] 1 = force fast mode and no suspend for device testing 72687b52439SFrank Schaefer * [5:7] USB PHY tuning registers; determined by device 72787b52439SFrank Schaefer * characterization 72887b52439SFrank Schaefer */ 72987b52439SFrank Schaefer 730fa74aca3SFrank Schaefer /* 731fa74aca3SFrank Schaefer * Read hardware config dataset offset from address 732fa74aca3SFrank Schaefer * (microcode start + 46) 733fa74aca3SFrank Schaefer */ 734aab3125cSMauro Carvalho Chehab err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2, 735aab3125cSMauro Carvalho Chehab data); 736510e884cSFrank Schaefer if (err != 2) { 737*29b05e22SMauro Carvalho Chehab dev_err(&dev->intf->dev, 738ce8591ffSMauro Carvalho Chehab "failed to read hardware configuration data from eeprom (err=%d)\n", 739510e884cSFrank Schaefer err); 740510e884cSFrank Schaefer goto error; 741510e884cSFrank Schaefer } 74287b52439SFrank Schaefer 743510e884cSFrank Schaefer /* Calculate hardware config dataset start address */ 744510e884cSFrank Schaefer hwconf_offset = mc_start + data[0] + (data[1] << 8); 745510e884cSFrank Schaefer 746510e884cSFrank Schaefer /* Read hardware config dataset */ 747fa74aca3SFrank Schaefer /* 748fa74aca3SFrank Schaefer * NOTE: the microcode copy can be multiple pages long, but 749510e884cSFrank Schaefer * we assume the hardware config dataset is the same as in 750510e884cSFrank Schaefer * the old eeprom and not longer than 256 bytes. 751510e884cSFrank Schaefer * tveeprom is currently also limited to 256 bytes. 752510e884cSFrank Schaefer */ 753aab3125cSMauro Carvalho Chehab err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len, 754aab3125cSMauro Carvalho Chehab data); 755510e884cSFrank Schaefer if (err != len) { 756*29b05e22SMauro Carvalho Chehab dev_err(&dev->intf->dev, 757ce8591ffSMauro Carvalho Chehab "failed to read hardware configuration data from eeprom (err=%d)\n", 758510e884cSFrank Schaefer err); 759510e884cSFrank Schaefer goto error; 760510e884cSFrank Schaefer } 761510e884cSFrank Schaefer 762510e884cSFrank Schaefer /* Verify hardware config dataset */ 763510e884cSFrank Schaefer /* NOTE: not all devices provide this type of dataset */ 764510e884cSFrank Schaefer if (data[0] != 0x1a || data[1] != 0xeb || 765a217968fSFrank Schaefer data[2] != 0x67 || data[3] != 0x95) { 766*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 767ce8591ffSMauro Carvalho Chehab "\tno hardware configuration dataset found in eeprom\n"); 768510e884cSFrank Schaefer kfree(data); 769510e884cSFrank Schaefer return 0; 770510e884cSFrank Schaefer } 771510e884cSFrank Schaefer 772510e884cSFrank Schaefer /* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */ 773510e884cSFrank Schaefer 774510e884cSFrank Schaefer } else if (!dev->eeprom_addrwidth_16bit && 775510e884cSFrank Schaefer data[0] == 0x1a && data[1] == 0xeb && 776510e884cSFrank Schaefer data[2] == 0x67 && data[3] == 0x95) { 777510e884cSFrank Schaefer dev->hash = em28xx_hash_mem(data, len, 32); 778*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 779ce8591ffSMauro Carvalho Chehab "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n", 780510e884cSFrank Schaefer data[0], data[1], data[2], data[3], dev->hash); 781*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 782ce8591ffSMauro Carvalho Chehab "EEPROM info:\n"); 783510e884cSFrank Schaefer } else { 784*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 785ce8591ffSMauro Carvalho Chehab "unknown eeprom format or eeprom corrupted !\n"); 786510e884cSFrank Schaefer err = -ENODEV; 787510e884cSFrank Schaefer goto error; 788f55eacbeSFrank Schaefer } 789f55eacbeSFrank Schaefer 790a217968fSFrank Schaefer *eedata = data; 791510e884cSFrank Schaefer *eedata_len = len; 79232bf7c6cSAlban Browaeys dev_config = (void *)*eedata; 793a217968fSFrank Schaefer 794510e884cSFrank Schaefer switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) { 795a6c2ba28Sakpm@osdl.org case 0: 796*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\tNo audio on board.\n"); 797a6c2ba28Sakpm@osdl.org break; 798a6c2ba28Sakpm@osdl.org case 1: 799*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\tAC97 audio (5 sample rates)\n"); 800a6c2ba28Sakpm@osdl.org break; 801a6c2ba28Sakpm@osdl.org case 2: 802687ff8b0SFrank Schaefer if (dev->chip_id < CHIP_ID_EM2860) 803*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 804ce8591ffSMauro Carvalho Chehab "\tI2S audio, sample rate=32k\n"); 805687ff8b0SFrank Schaefer else 806*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 807ce8591ffSMauro Carvalho Chehab "\tI2S audio, 3 sample rates\n"); 808a6c2ba28Sakpm@osdl.org break; 809a6c2ba28Sakpm@osdl.org case 3: 810687ff8b0SFrank Schaefer if (dev->chip_id < CHIP_ID_EM2860) 811*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 812ce8591ffSMauro Carvalho Chehab "\tI2S audio, 3 sample rates\n"); 813687ff8b0SFrank Schaefer else 814*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 815ce8591ffSMauro Carvalho Chehab "\tI2S audio, 5 sample rates\n"); 816a6c2ba28Sakpm@osdl.org break; 817a6c2ba28Sakpm@osdl.org } 818a6c2ba28Sakpm@osdl.org 819510e884cSFrank Schaefer if (le16_to_cpu(dev_config->chip_conf) & 1 << 3) 820*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\tUSB Remote wakeup capable\n"); 821a6c2ba28Sakpm@osdl.org 822510e884cSFrank Schaefer if (le16_to_cpu(dev_config->chip_conf) & 1 << 2) 823*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\tUSB Self power capable\n"); 824a6c2ba28Sakpm@osdl.org 825510e884cSFrank Schaefer switch (le16_to_cpu(dev_config->chip_conf) & 0x3) { 826a6c2ba28Sakpm@osdl.org case 0: 827*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\t500mA max power\n"); 828a6c2ba28Sakpm@osdl.org break; 829a6c2ba28Sakpm@osdl.org case 1: 830*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\t400mA max power\n"); 831a6c2ba28Sakpm@osdl.org break; 832a6c2ba28Sakpm@osdl.org case 2: 833*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\t300mA max power\n"); 834a6c2ba28Sakpm@osdl.org break; 835a6c2ba28Sakpm@osdl.org case 3: 836*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, "\t200mA max power\n"); 837a6c2ba28Sakpm@osdl.org break; 838a6c2ba28Sakpm@osdl.org } 839*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 840ce8591ffSMauro Carvalho Chehab "\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", 841510e884cSFrank Schaefer dev_config->string_idx_table, 842510e884cSFrank Schaefer le16_to_cpu(dev_config->string1), 843510e884cSFrank Schaefer le16_to_cpu(dev_config->string2), 844510e884cSFrank Schaefer le16_to_cpu(dev_config->string3)); 845a6c2ba28Sakpm@osdl.org 846a6c2ba28Sakpm@osdl.org return 0; 847510e884cSFrank Schaefer 848510e884cSFrank Schaefer error: 849510e884cSFrank Schaefer kfree(data); 850510e884cSFrank Schaefer return err; 851a6c2ba28Sakpm@osdl.org } 852a6c2ba28Sakpm@osdl.org 853a6c2ba28Sakpm@osdl.org /* ----------------------------------------------------------- */ 854a6c2ba28Sakpm@osdl.org 855a6c2ba28Sakpm@osdl.org /* 856a6c2ba28Sakpm@osdl.org * functionality() 857a6c2ba28Sakpm@osdl.org */ 858aab3125cSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *i2c_adap) 859a6c2ba28Sakpm@osdl.org { 860aab3125cSMauro Carvalho Chehab struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data; 861aab3125cSMauro Carvalho Chehab 862a3ea4bf9SFrank Schaefer if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) || 863a3ea4bf9SFrank Schaefer (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) { 864a3ea4bf9SFrank Schaefer return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 865a3ea4bf9SFrank Schaefer } else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) { 866a3ea4bf9SFrank Schaefer return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) & 867a3ea4bf9SFrank Schaefer ~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA; 868a3ea4bf9SFrank Schaefer } 869a3ea4bf9SFrank Schaefer 870a3ea4bf9SFrank Schaefer WARN(1, "Unknown i2c bus algorithm.\n"); 871a3ea4bf9SFrank Schaefer return 0; 872a6c2ba28Sakpm@osdl.org } 873a6c2ba28Sakpm@osdl.org 87478f2c50bSJulia Lawall static const struct i2c_algorithm em28xx_algo = { 8753acf2809SMauro Carvalho Chehab .master_xfer = em28xx_i2c_xfer, 876a6c2ba28Sakpm@osdl.org .functionality = functionality, 877a6c2ba28Sakpm@osdl.org }; 878a6c2ba28Sakpm@osdl.org 8793acf2809SMauro Carvalho Chehab static struct i2c_adapter em28xx_adap_template = { 880a6c2ba28Sakpm@osdl.org .owner = THIS_MODULE, 8813acf2809SMauro Carvalho Chehab .name = "em28xx", 8823acf2809SMauro Carvalho Chehab .algo = &em28xx_algo, 883a6c2ba28Sakpm@osdl.org }; 884a6c2ba28Sakpm@osdl.org 8853acf2809SMauro Carvalho Chehab static struct i2c_client em28xx_client_template = { 8863acf2809SMauro Carvalho Chehab .name = "em28xx internal", 887a6c2ba28Sakpm@osdl.org }; 888a6c2ba28Sakpm@osdl.org 889a6c2ba28Sakpm@osdl.org /* ----------------------------------------------------------- */ 890a6c2ba28Sakpm@osdl.org 891a6c2ba28Sakpm@osdl.org /* 892a6c2ba28Sakpm@osdl.org * i2c_devs 893a6c2ba28Sakpm@osdl.org * incomplete list of known devices 894a6c2ba28Sakpm@osdl.org */ 895a6c2ba28Sakpm@osdl.org static char *i2c_devs[128] = { 8969aa785b1SWilson Michaels [0x1c >> 1] = "lgdt330x", 8970b3966e4SFrank Schaefer [0x3e >> 1] = "remote IR sensor", 898a6c2ba28Sakpm@osdl.org [0x4a >> 1] = "saa7113h", 899729841edSMartin Blumenstingl [0x52 >> 1] = "drxk", 900a6c2ba28Sakpm@osdl.org [0x60 >> 1] = "remote IR sensor", 901da45a2a5SMarkus Rechberger [0x8e >> 1] = "remote IR sensor", 902a6c2ba28Sakpm@osdl.org [0x86 >> 1] = "tda9887", 903a6c2ba28Sakpm@osdl.org [0x80 >> 1] = "msp34xx", 904a6c2ba28Sakpm@osdl.org [0x88 >> 1] = "msp34xx", 905a6c2ba28Sakpm@osdl.org [0xa0 >> 1] = "eeprom", 9062bd1d9ebSVitaly Wool [0xb0 >> 1] = "tda9874", 907a6c2ba28Sakpm@osdl.org [0xb8 >> 1] = "tvp5150a", 908791a08fcSMauro Carvalho Chehab [0xba >> 1] = "webcam sensor or tvp5150a", 909a6c2ba28Sakpm@osdl.org [0xc0 >> 1] = "tuner (analog)", 910a6c2ba28Sakpm@osdl.org [0xc2 >> 1] = "tuner (analog)", 911a6c2ba28Sakpm@osdl.org [0xc4 >> 1] = "tuner (analog)", 912a6c2ba28Sakpm@osdl.org [0xc6 >> 1] = "tuner (analog)", 913a6c2ba28Sakpm@osdl.org }; 914a6c2ba28Sakpm@osdl.org 915a6c2ba28Sakpm@osdl.org /* 916a6c2ba28Sakpm@osdl.org * do_i2c_scan() 917a6c2ba28Sakpm@osdl.org * check i2c address range for devices 918a6c2ba28Sakpm@osdl.org */ 919aab3125cSMauro Carvalho Chehab void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus) 920a6c2ba28Sakpm@osdl.org { 921fad7b958SSascha Sommer u8 i2c_devicelist[128]; 922a6c2ba28Sakpm@osdl.org unsigned char buf; 923a6c2ba28Sakpm@osdl.org int i, rc; 924a6c2ba28Sakpm@osdl.org 925fad7b958SSascha Sommer memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); 926fad7b958SSascha Sommer 92753c4e955SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { 928aab3125cSMauro Carvalho Chehab dev->i2c_client[bus].addr = i; 929aab3125cSMauro Carvalho Chehab rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0); 930a6c2ba28Sakpm@osdl.org if (rc < 0) 931a6c2ba28Sakpm@osdl.org continue; 932fad7b958SSascha Sommer i2c_devicelist[i] = i; 933*29b05e22SMauro Carvalho Chehab dev_info(&dev->intf->dev, 934ce8591ffSMauro Carvalho Chehab "found i2c device @ 0x%x on bus %d [%s]\n", 935aab3125cSMauro Carvalho Chehab i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???"); 936a6c2ba28Sakpm@osdl.org } 937fad7b958SSascha Sommer 938aab3125cSMauro Carvalho Chehab if (bus == dev->def_i2c_bus) 939fad7b958SSascha Sommer dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, 940fad7b958SSascha Sommer ARRAY_SIZE(i2c_devicelist), 32); 941a6c2ba28Sakpm@osdl.org } 942a6c2ba28Sakpm@osdl.org 943a6c2ba28Sakpm@osdl.org /* 9443acf2809SMauro Carvalho Chehab * em28xx_i2c_register() 945a6c2ba28Sakpm@osdl.org * register i2c bus 946a6c2ba28Sakpm@osdl.org */ 947a3ea4bf9SFrank Schaefer int em28xx_i2c_register(struct em28xx *dev, unsigned bus, 948a3ea4bf9SFrank Schaefer enum em28xx_i2c_algo_type algo_type) 949a6c2ba28Sakpm@osdl.org { 950f2a01a00SDouglas Schilling Landgraf int retval; 951f2a01a00SDouglas Schilling Landgraf 9523acf2809SMauro Carvalho Chehab BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); 9533acf2809SMauro Carvalho Chehab BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); 954f2a01a00SDouglas Schilling Landgraf 955aab3125cSMauro Carvalho Chehab if (bus >= NUM_I2C_BUSES) 956aab3125cSMauro Carvalho Chehab return -ENODEV; 957aab3125cSMauro Carvalho Chehab 958aab3125cSMauro Carvalho Chehab dev->i2c_adap[bus] = em28xx_adap_template; 959*29b05e22SMauro Carvalho Chehab dev->i2c_adap[bus].dev.parent = &dev->intf->dev; 960*29b05e22SMauro Carvalho Chehab strcpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev)); 961aab3125cSMauro Carvalho Chehab 962aab3125cSMauro Carvalho Chehab dev->i2c_bus[bus].bus = bus; 963a3ea4bf9SFrank Schaefer dev->i2c_bus[bus].algo_type = algo_type; 964aab3125cSMauro Carvalho Chehab dev->i2c_bus[bus].dev = dev; 965aab3125cSMauro Carvalho Chehab dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus]; 966aab3125cSMauro Carvalho Chehab 967aab3125cSMauro Carvalho Chehab retval = i2c_add_adapter(&dev->i2c_adap[bus]); 968f2a01a00SDouglas Schilling Landgraf if (retval < 0) { 969*29b05e22SMauro Carvalho Chehab dev_err(&dev->intf->dev, 970ce8591ffSMauro Carvalho Chehab "%s: i2c_add_adapter failed! retval [%d]\n", 971f2a01a00SDouglas Schilling Landgraf __func__, retval); 972f2a01a00SDouglas Schilling Landgraf return retval; 973f2a01a00SDouglas Schilling Landgraf } 974a6c2ba28Sakpm@osdl.org 975aab3125cSMauro Carvalho Chehab dev->i2c_client[bus] = em28xx_client_template; 976aab3125cSMauro Carvalho Chehab dev->i2c_client[bus].adapter = &dev->i2c_adap[bus]; 977a6c2ba28Sakpm@osdl.org 978aab3125cSMauro Carvalho Chehab /* Up to now, all eeproms are at bus 0 */ 979aab3125cSMauro Carvalho Chehab if (!bus) { 980aab3125cSMauro Carvalho Chehab retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len); 981c41109fcSMauro Carvalho Chehab if ((retval < 0) && (retval != -ENODEV)) { 982*29b05e22SMauro Carvalho Chehab dev_err(&dev->intf->dev, 983ce8591ffSMauro Carvalho Chehab "%s: em28xx_i2_eeprom failed! retval [%d]\n", 984f2a01a00SDouglas Schilling Landgraf __func__, retval); 985c41109fcSMauro Carvalho Chehab 986f2a01a00SDouglas Schilling Landgraf return retval; 987f2a01a00SDouglas Schilling Landgraf } 988aab3125cSMauro Carvalho Chehab } 989a6c2ba28Sakpm@osdl.org 990a6c2ba28Sakpm@osdl.org if (i2c_scan) 991aab3125cSMauro Carvalho Chehab em28xx_do_i2c_scan(dev, bus); 992c41109fcSMauro Carvalho Chehab 993a6c2ba28Sakpm@osdl.org return 0; 994a6c2ba28Sakpm@osdl.org } 995a6c2ba28Sakpm@osdl.org 996a6c2ba28Sakpm@osdl.org /* 9973acf2809SMauro Carvalho Chehab * em28xx_i2c_unregister() 998a6c2ba28Sakpm@osdl.org * unregister i2c_bus 999a6c2ba28Sakpm@osdl.org */ 1000aab3125cSMauro Carvalho Chehab int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus) 1001a6c2ba28Sakpm@osdl.org { 1002aab3125cSMauro Carvalho Chehab if (bus >= NUM_I2C_BUSES) 1003aab3125cSMauro Carvalho Chehab return -ENODEV; 1004aab3125cSMauro Carvalho Chehab 1005aab3125cSMauro Carvalho Chehab i2c_del_adapter(&dev->i2c_adap[bus]); 1006a6c2ba28Sakpm@osdl.org return 0; 1007a6c2ba28Sakpm@osdl.org } 1008