10c0d06caSMauro Carvalho Chehab /* 20c0d06caSMauro Carvalho Chehab em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices 30c0d06caSMauro Carvalho Chehab 40c0d06caSMauro Carvalho Chehab Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> 50c0d06caSMauro Carvalho Chehab Markus Rechberger <mrechberger@gmail.com> 60c0d06caSMauro Carvalho Chehab Mauro Carvalho Chehab <mchehab@infradead.org> 70c0d06caSMauro Carvalho Chehab Sascha Sommer <saschasommer@freenet.de> 8a3ea4bf9SFrank Schaefer Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com> 90c0d06caSMauro Carvalho Chehab 100c0d06caSMauro Carvalho Chehab This program is free software; you can redistribute it and/or modify 110c0d06caSMauro Carvalho Chehab it under the terms of the GNU General Public License as published by 120c0d06caSMauro Carvalho Chehab the Free Software Foundation; either version 2 of the License, or 130c0d06caSMauro Carvalho Chehab (at your option) any later version. 140c0d06caSMauro Carvalho Chehab 150c0d06caSMauro Carvalho Chehab This program is distributed in the hope that it will be useful, 160c0d06caSMauro Carvalho Chehab but WITHOUT ANY WARRANTY; without even the implied warranty of 170c0d06caSMauro Carvalho Chehab MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 180c0d06caSMauro Carvalho Chehab GNU General Public License for more details. 190c0d06caSMauro Carvalho Chehab 200c0d06caSMauro Carvalho Chehab You should have received a copy of the GNU General Public License 210c0d06caSMauro Carvalho Chehab along with this program; if not, write to the Free Software 220c0d06caSMauro Carvalho Chehab Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 230c0d06caSMauro Carvalho Chehab */ 240c0d06caSMauro Carvalho Chehab 250c0d06caSMauro Carvalho Chehab #include <linux/module.h> 260c0d06caSMauro Carvalho Chehab #include <linux/kernel.h> 270c0d06caSMauro Carvalho Chehab #include <linux/usb.h> 280c0d06caSMauro Carvalho Chehab #include <linux/i2c.h> 294b83626aSMauro Carvalho Chehab #include <linux/jiffies.h> 300c0d06caSMauro Carvalho Chehab 310c0d06caSMauro Carvalho Chehab #include "em28xx.h" 320c0d06caSMauro Carvalho Chehab #include "tuner-xc2028.h" 330c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h> 340c0d06caSMauro Carvalho Chehab #include <media/tuner.h> 350c0d06caSMauro Carvalho Chehab 360c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 370c0d06caSMauro Carvalho Chehab 380c0d06caSMauro Carvalho Chehab static unsigned int i2c_scan; 390c0d06caSMauro Carvalho Chehab module_param(i2c_scan, int, 0444); 400c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); 410c0d06caSMauro Carvalho Chehab 420c0d06caSMauro Carvalho Chehab static unsigned int i2c_debug; 430c0d06caSMauro Carvalho Chehab module_param(i2c_debug, int, 0644); 440c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); 450c0d06caSMauro Carvalho Chehab 460c0d06caSMauro Carvalho Chehab /* 47f5ae371aSFrank Schaefer * em2800_i2c_send_bytes() 48f5ae371aSFrank Schaefer * send up to 4 bytes to the em2800 i2c device 490c0d06caSMauro Carvalho Chehab */ 50f5ae371aSFrank Schaefer static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) 510c0d06caSMauro Carvalho Chehab { 52d1b7213bSMauro Carvalho Chehab unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); 530c0d06caSMauro Carvalho Chehab int ret; 54a6bad040SFrank Schaefer u8 b2[6]; 55f5ae371aSFrank Schaefer 56f5ae371aSFrank Schaefer if (len < 1 || len > 4) 57f5ae371aSFrank Schaefer return -EOPNOTSUPP; 58f5ae371aSFrank Schaefer 590c0d06caSMauro Carvalho Chehab BUG_ON(len < 1 || len > 4); 600c0d06caSMauro Carvalho Chehab b2[5] = 0x80 + len - 1; 610c0d06caSMauro Carvalho Chehab b2[4] = addr; 620c0d06caSMauro Carvalho Chehab b2[3] = buf[0]; 630c0d06caSMauro Carvalho Chehab if (len > 1) 640c0d06caSMauro Carvalho Chehab b2[2] = buf[1]; 650c0d06caSMauro Carvalho Chehab if (len > 2) 660c0d06caSMauro Carvalho Chehab b2[1] = buf[2]; 670c0d06caSMauro Carvalho Chehab if (len > 3) 680c0d06caSMauro Carvalho Chehab b2[0] = buf[3]; 690c0d06caSMauro Carvalho Chehab 702fcc82d8SFrank Schaefer /* trigger write */ 710c0d06caSMauro Carvalho Chehab ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); 720c0d06caSMauro Carvalho Chehab if (ret != 2 + len) { 73d230d5adSFrank Schaefer em28xx_warn("failed to trigger write to i2c address 0x%x (error=%i)\n", 74d230d5adSFrank Schaefer addr, ret); 7545f04e82SFrank Schaefer return (ret < 0) ? ret : -EIO; 760c0d06caSMauro Carvalho Chehab } 772fcc82d8SFrank Schaefer /* wait for completion */ 784b83626aSMauro Carvalho Chehab while (time_is_after_jiffies(timeout)) { 790c0d06caSMauro Carvalho Chehab ret = dev->em28xx_read_reg(dev, 0x05); 804b83626aSMauro Carvalho Chehab if (ret == 0x80 + len - 1) 810c0d06caSMauro Carvalho Chehab return len; 824b83626aSMauro Carvalho Chehab if (ret == 0x94 + len - 1) { 83*e63b009dSMauro Carvalho Chehab return -ENXIO; 844b83626aSMauro Carvalho Chehab } 854b83626aSMauro Carvalho Chehab if (ret < 0) { 86d230d5adSFrank Schaefer em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", 87d230d5adSFrank Schaefer ret); 8845f04e82SFrank Schaefer return ret; 8945f04e82SFrank Schaefer } 900c0d06caSMauro Carvalho Chehab msleep(5); 910c0d06caSMauro Carvalho Chehab } 9245f04e82SFrank Schaefer em28xx_warn("write to i2c device at 0x%x timed out\n", addr); 93*e63b009dSMauro Carvalho Chehab return -ETIMEDOUT; 940c0d06caSMauro Carvalho Chehab } 950c0d06caSMauro Carvalho Chehab 960c0d06caSMauro Carvalho Chehab /* 970c0d06caSMauro Carvalho Chehab * em2800_i2c_recv_bytes() 982fcc82d8SFrank Schaefer * read up to 4 bytes from the em2800 i2c device 990c0d06caSMauro Carvalho Chehab */ 100a6bad040SFrank Schaefer static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) 1010c0d06caSMauro Carvalho Chehab { 102d1b7213bSMauro Carvalho Chehab unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); 1032fcc82d8SFrank Schaefer u8 buf2[4]; 1040c0d06caSMauro Carvalho Chehab int ret; 1052fcc82d8SFrank Schaefer int i; 106f5ae371aSFrank Schaefer 107f5ae371aSFrank Schaefer if (len < 1 || len > 4) 108f5ae371aSFrank Schaefer return -EOPNOTSUPP; 109f5ae371aSFrank Schaefer 1102fcc82d8SFrank Schaefer /* trigger read */ 1112fcc82d8SFrank Schaefer buf2[1] = 0x84 + len - 1; 1122fcc82d8SFrank Schaefer buf2[0] = addr; 1132fcc82d8SFrank Schaefer ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2); 1142fcc82d8SFrank Schaefer if (ret != 2) { 115d230d5adSFrank Schaefer em28xx_warn("failed to trigger read from i2c address 0x%x (error=%i)\n", 116d230d5adSFrank Schaefer addr, ret); 1172fcc82d8SFrank Schaefer return (ret < 0) ? ret : -EIO; 1182fcc82d8SFrank Schaefer } 1192fcc82d8SFrank Schaefer 1202fcc82d8SFrank Schaefer /* wait for completion */ 1214b83626aSMauro Carvalho Chehab while (time_is_after_jiffies(timeout)) { 1222fcc82d8SFrank Schaefer ret = dev->em28xx_read_reg(dev, 0x05); 1234b83626aSMauro Carvalho Chehab if (ret == 0x84 + len - 1) 1242fcc82d8SFrank Schaefer break; 1254b83626aSMauro Carvalho Chehab if (ret == 0x94 + len - 1) { 126*e63b009dSMauro Carvalho Chehab return -ENXIO; 1274b83626aSMauro Carvalho Chehab } 1284b83626aSMauro Carvalho Chehab if (ret < 0) { 129d230d5adSFrank Schaefer em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", 130d230d5adSFrank Schaefer ret); 1310c0d06caSMauro Carvalho Chehab return ret; 1320c0d06caSMauro Carvalho Chehab } 1332fcc82d8SFrank Schaefer msleep(5); 1342fcc82d8SFrank Schaefer } 1352fcc82d8SFrank Schaefer if (ret != 0x84 + len - 1) 1362fcc82d8SFrank Schaefer em28xx_warn("read from i2c device at 0x%x timed out\n", addr); 1372fcc82d8SFrank Schaefer 1382fcc82d8SFrank Schaefer /* get the received message */ 1392fcc82d8SFrank Schaefer ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len); 1402fcc82d8SFrank Schaefer if (ret != len) { 141d230d5adSFrank Schaefer em28xx_warn("reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n", 142d230d5adSFrank Schaefer addr, ret); 1432fcc82d8SFrank Schaefer return (ret < 0) ? ret : -EIO; 1442fcc82d8SFrank Schaefer } 1452fcc82d8SFrank Schaefer for (i = 0; i < len; i++) 1462fcc82d8SFrank Schaefer buf[i] = buf2[len - 1 - i]; 1472fcc82d8SFrank Schaefer 1480c0d06caSMauro Carvalho Chehab return ret; 1490c0d06caSMauro Carvalho Chehab } 1502fcc82d8SFrank Schaefer 1512fcc82d8SFrank Schaefer /* 1522fcc82d8SFrank Schaefer * em2800_i2c_check_for_device() 1532fcc82d8SFrank Schaefer * check if there is an i2c device at the supplied address 1542fcc82d8SFrank Schaefer */ 1552fcc82d8SFrank Schaefer static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr) 1562fcc82d8SFrank Schaefer { 1572fcc82d8SFrank Schaefer u8 buf; 1582fcc82d8SFrank Schaefer int ret; 1592fcc82d8SFrank Schaefer 1602fcc82d8SFrank Schaefer ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1); 1612fcc82d8SFrank Schaefer if (ret == 1) 1622fcc82d8SFrank Schaefer return 0; 1632fcc82d8SFrank Schaefer return (ret < 0) ? ret : -EIO; 1640c0d06caSMauro Carvalho Chehab } 1650c0d06caSMauro Carvalho Chehab 1660c0d06caSMauro Carvalho Chehab /* 1670c0d06caSMauro Carvalho Chehab * em28xx_i2c_send_bytes() 1680c0d06caSMauro Carvalho Chehab */ 169a6bad040SFrank Schaefer static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, 170a6bad040SFrank Schaefer u16 len, int stop) 1710c0d06caSMauro Carvalho Chehab { 172d1b7213bSMauro Carvalho Chehab unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); 1734b83626aSMauro Carvalho Chehab int ret; 1740c0d06caSMauro Carvalho Chehab 175f5ae371aSFrank Schaefer if (len < 1 || len > 64) 176f5ae371aSFrank Schaefer return -EOPNOTSUPP; 177fa74aca3SFrank Schaefer /* 178fa74aca3SFrank Schaefer * NOTE: limited by the USB ctrl message constraints 179fa74aca3SFrank Schaefer * Zero length reads always succeed, even if no device is connected 180fa74aca3SFrank Schaefer */ 181f5ae371aSFrank Schaefer 18245f04e82SFrank Schaefer /* Write to i2c device */ 18345f04e82SFrank Schaefer ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); 18445f04e82SFrank Schaefer if (ret != len) { 18545f04e82SFrank Schaefer if (ret < 0) { 186d230d5adSFrank Schaefer em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n", 187d230d5adSFrank Schaefer addr, ret); 18845f04e82SFrank Schaefer return ret; 18945f04e82SFrank Schaefer } else { 190d230d5adSFrank Schaefer em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n", 19145f04e82SFrank Schaefer len, addr, ret); 19245f04e82SFrank Schaefer return -EIO; 19345f04e82SFrank Schaefer } 19445f04e82SFrank Schaefer } 1950c0d06caSMauro Carvalho Chehab 1964b83626aSMauro Carvalho Chehab /* wait for completion */ 1974b83626aSMauro Carvalho Chehab while (time_is_after_jiffies(timeout)) { 1980c0d06caSMauro Carvalho Chehab ret = dev->em28xx_read_reg(dev, 0x05); 1994b83626aSMauro Carvalho Chehab if (ret == 0) /* success */ 20045f04e82SFrank Schaefer return len; 2014b83626aSMauro Carvalho Chehab if (ret == 0x10) { 202*e63b009dSMauro Carvalho Chehab return -ENXIO; 2034b83626aSMauro Carvalho Chehab } 2044b83626aSMauro Carvalho Chehab if (ret < 0) { 2054b83626aSMauro Carvalho Chehab em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", 206d230d5adSFrank Schaefer ret); 20745f04e82SFrank Schaefer return ret; 2080c0d06caSMauro Carvalho Chehab } 20945f04e82SFrank Schaefer msleep(5); 210fa74aca3SFrank Schaefer /* 211fa74aca3SFrank Schaefer * NOTE: do we really have to wait for success ? 212fa74aca3SFrank Schaefer * Never seen anything else than 0x00 or 0x10 213fa74aca3SFrank Schaefer * (even with high payload) ... 214fa74aca3SFrank Schaefer */ 21545f04e82SFrank Schaefer } 216*e63b009dSMauro Carvalho Chehab em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n", addr, ret); 217*e63b009dSMauro Carvalho Chehab return -ETIMEDOUT; 2180c0d06caSMauro Carvalho Chehab } 2190c0d06caSMauro Carvalho Chehab 2200c0d06caSMauro Carvalho Chehab /* 2210c0d06caSMauro Carvalho Chehab * em28xx_i2c_recv_bytes() 2220c0d06caSMauro Carvalho Chehab * read a byte from the i2c device 2230c0d06caSMauro Carvalho Chehab */ 224a6bad040SFrank Schaefer static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len) 2250c0d06caSMauro Carvalho Chehab { 2260c0d06caSMauro Carvalho Chehab int ret; 227f5ae371aSFrank Schaefer 228f5ae371aSFrank Schaefer if (len < 1 || len > 64) 229f5ae371aSFrank Schaefer return -EOPNOTSUPP; 230fa74aca3SFrank Schaefer /* 231fa74aca3SFrank Schaefer * NOTE: limited by the USB ctrl message constraints 232fa74aca3SFrank Schaefer * Zero length reads always succeed, even if no device is connected 233fa74aca3SFrank Schaefer */ 234f5ae371aSFrank Schaefer 23545f04e82SFrank Schaefer /* Read data from i2c device */ 2360c0d06caSMauro Carvalho Chehab ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); 2370c0d06caSMauro Carvalho Chehab if (ret < 0) { 2387f6301d1SFrank Schaefer em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n", 2397f6301d1SFrank Schaefer addr, ret); 24045f04e82SFrank Schaefer return ret; 24145f04e82SFrank Schaefer } 242fa74aca3SFrank Schaefer /* 243fa74aca3SFrank Schaefer * NOTE: some devices with two i2c busses have the bad habit to return 0 2447f6301d1SFrank Schaefer * bytes if we are on bus B AND there was no write attempt to the 2457f6301d1SFrank Schaefer * specified slave address before AND no device is present at the 2467f6301d1SFrank Schaefer * requested slave address. 247*e63b009dSMauro Carvalho Chehab * Anyway, the next check will fail with -ENXIO in this case, so avoid 2487f6301d1SFrank Schaefer * spamming the system log on device probing and do nothing here. 2497f6301d1SFrank Schaefer */ 25045f04e82SFrank Schaefer 25145f04e82SFrank Schaefer /* Check success of the i2c operation */ 25245f04e82SFrank Schaefer ret = dev->em28xx_read_reg(dev, 0x05); 2534b83626aSMauro Carvalho Chehab if (ret == 0) /* success */ 2544b83626aSMauro Carvalho Chehab return len; 25545f04e82SFrank Schaefer if (ret < 0) { 2564b83626aSMauro Carvalho Chehab em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", 257d230d5adSFrank Schaefer ret); 2580c0d06caSMauro Carvalho Chehab return ret; 2590c0d06caSMauro Carvalho Chehab } 2604b83626aSMauro Carvalho Chehab if (ret == 0x10) 261*e63b009dSMauro Carvalho Chehab return -ENXIO; 2624b83626aSMauro Carvalho Chehab 26345f04e82SFrank Schaefer em28xx_warn("unknown i2c error (status=%i)\n", ret); 264*e63b009dSMauro Carvalho Chehab return -ETIMEDOUT; 26545f04e82SFrank Schaefer } 2660c0d06caSMauro Carvalho Chehab 2670c0d06caSMauro Carvalho Chehab /* 2680c0d06caSMauro Carvalho Chehab * em28xx_i2c_check_for_device() 2690c0d06caSMauro Carvalho Chehab * check if there is a i2c_device at the supplied address 2700c0d06caSMauro Carvalho Chehab */ 271a6bad040SFrank Schaefer static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr) 2720c0d06caSMauro Carvalho Chehab { 2730c0d06caSMauro Carvalho Chehab int ret; 27445f04e82SFrank Schaefer u8 buf; 2750c0d06caSMauro Carvalho Chehab 27645f04e82SFrank Schaefer ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1); 27745f04e82SFrank Schaefer if (ret == 1) 2780c0d06caSMauro Carvalho Chehab return 0; 27945f04e82SFrank Schaefer return (ret < 0) ? ret : -EIO; 2800c0d06caSMauro Carvalho Chehab } 2810c0d06caSMauro Carvalho Chehab 2820c0d06caSMauro Carvalho Chehab /* 283a3ea4bf9SFrank Schaefer * em25xx_bus_B_send_bytes 284a3ea4bf9SFrank Schaefer * write bytes to the i2c device 285a3ea4bf9SFrank Schaefer */ 286a3ea4bf9SFrank Schaefer static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, 287a3ea4bf9SFrank Schaefer u16 len) 288a3ea4bf9SFrank Schaefer { 289a3ea4bf9SFrank Schaefer int ret; 290a3ea4bf9SFrank Schaefer 291a3ea4bf9SFrank Schaefer if (len < 1 || len > 64) 292a3ea4bf9SFrank Schaefer return -EOPNOTSUPP; 293a3ea4bf9SFrank Schaefer /* 294a3ea4bf9SFrank Schaefer * NOTE: limited by the USB ctrl message constraints 295a3ea4bf9SFrank Schaefer * Zero length reads always succeed, even if no device is connected 296a3ea4bf9SFrank Schaefer */ 297a3ea4bf9SFrank Schaefer 298a3ea4bf9SFrank Schaefer /* Set register and write value */ 299a3ea4bf9SFrank Schaefer ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len); 300a3ea4bf9SFrank Schaefer if (ret != len) { 301a3ea4bf9SFrank Schaefer if (ret < 0) { 302a3ea4bf9SFrank Schaefer em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n", 303a3ea4bf9SFrank Schaefer addr, ret); 304a3ea4bf9SFrank Schaefer return ret; 305a3ea4bf9SFrank Schaefer } else { 306a3ea4bf9SFrank Schaefer em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n", 307a3ea4bf9SFrank Schaefer len, addr, ret); 308a3ea4bf9SFrank Schaefer return -EIO; 309a3ea4bf9SFrank Schaefer } 310a3ea4bf9SFrank Schaefer } 311a3ea4bf9SFrank Schaefer /* Check success */ 312a3ea4bf9SFrank Schaefer ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000); 313a3ea4bf9SFrank Schaefer /* 314a3ea4bf9SFrank Schaefer * NOTE: the only error we've seen so far is 315a3ea4bf9SFrank Schaefer * 0x01 when the slave device is not present 316a3ea4bf9SFrank Schaefer */ 317a3ea4bf9SFrank Schaefer if (!ret) 318a3ea4bf9SFrank Schaefer return len; 319a3ea4bf9SFrank Schaefer else if (ret > 0) 320*e63b009dSMauro Carvalho Chehab return -ENXIO; 321a3ea4bf9SFrank Schaefer 322a3ea4bf9SFrank Schaefer return ret; 323a3ea4bf9SFrank Schaefer /* 324a3ea4bf9SFrank Schaefer * NOTE: With chip types (other chip IDs) which actually don't support 325a3ea4bf9SFrank Schaefer * this operation, it seems to succeed ALWAYS ! (even if there is no 326a3ea4bf9SFrank Schaefer * slave device or even no second i2c bus provided) 327a3ea4bf9SFrank Schaefer */ 328a3ea4bf9SFrank Schaefer } 329a3ea4bf9SFrank Schaefer 330a3ea4bf9SFrank Schaefer /* 331a3ea4bf9SFrank Schaefer * em25xx_bus_B_recv_bytes 332a3ea4bf9SFrank Schaefer * read bytes from the i2c device 333a3ea4bf9SFrank Schaefer */ 334a3ea4bf9SFrank Schaefer static int em25xx_bus_B_recv_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 /* Read value */ 347a3ea4bf9SFrank Schaefer ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len); 348a3ea4bf9SFrank Schaefer if (ret < 0) { 349a3ea4bf9SFrank Schaefer em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n", 350a3ea4bf9SFrank Schaefer addr, ret); 351a3ea4bf9SFrank Schaefer return ret; 352a3ea4bf9SFrank Schaefer } 353a3ea4bf9SFrank Schaefer /* 354a3ea4bf9SFrank Schaefer * NOTE: some devices with two i2c busses have the bad habit to return 0 355a3ea4bf9SFrank Schaefer * bytes if we are on bus B AND there was no write attempt to the 356a3ea4bf9SFrank Schaefer * specified slave address before AND no device is present at the 357a3ea4bf9SFrank Schaefer * requested slave address. 358*e63b009dSMauro Carvalho Chehab * Anyway, the next check will fail with -ENXIO in this case, so avoid 359a3ea4bf9SFrank Schaefer * spamming the system log on device probing and do nothing here. 360a3ea4bf9SFrank Schaefer */ 361a3ea4bf9SFrank Schaefer 362a3ea4bf9SFrank Schaefer /* Check success */ 363a3ea4bf9SFrank Schaefer ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000); 364a3ea4bf9SFrank Schaefer /* 365a3ea4bf9SFrank Schaefer * NOTE: the only error we've seen so far is 366a3ea4bf9SFrank Schaefer * 0x01 when the slave device is not present 367a3ea4bf9SFrank Schaefer */ 368a3ea4bf9SFrank Schaefer if (!ret) 369a3ea4bf9SFrank Schaefer return len; 370a3ea4bf9SFrank Schaefer else if (ret > 0) 371*e63b009dSMauro Carvalho Chehab return -ENXIO; 372a3ea4bf9SFrank Schaefer 373a3ea4bf9SFrank Schaefer return ret; 374a3ea4bf9SFrank Schaefer /* 375a3ea4bf9SFrank Schaefer * NOTE: With chip types (other chip IDs) which actually don't support 376a3ea4bf9SFrank Schaefer * this operation, it seems to succeed ALWAYS ! (even if there is no 377a3ea4bf9SFrank Schaefer * slave device or even no second i2c bus provided) 378a3ea4bf9SFrank Schaefer */ 379a3ea4bf9SFrank Schaefer } 380a3ea4bf9SFrank Schaefer 381a3ea4bf9SFrank Schaefer /* 382a3ea4bf9SFrank Schaefer * em25xx_bus_B_check_for_device() 383a3ea4bf9SFrank Schaefer * check if there is a i2c device at the supplied address 384a3ea4bf9SFrank Schaefer */ 385a3ea4bf9SFrank Schaefer static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr) 386a3ea4bf9SFrank Schaefer { 387a3ea4bf9SFrank Schaefer u8 buf; 388a3ea4bf9SFrank Schaefer int ret; 389a3ea4bf9SFrank Schaefer 390a3ea4bf9SFrank Schaefer ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1); 391a3ea4bf9SFrank Schaefer if (ret < 0) 392a3ea4bf9SFrank Schaefer return ret; 393a3ea4bf9SFrank Schaefer 394a3ea4bf9SFrank Schaefer return 0; 395a3ea4bf9SFrank Schaefer /* 396a3ea4bf9SFrank Schaefer * NOTE: With chips which do not support this operation, 397a3ea4bf9SFrank Schaefer * it seems to succeed ALWAYS ! (even if no device connected) 398a3ea4bf9SFrank Schaefer */ 399a3ea4bf9SFrank Schaefer } 400a3ea4bf9SFrank Schaefer 401a3ea4bf9SFrank Schaefer static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr) 402a3ea4bf9SFrank Schaefer { 403a3ea4bf9SFrank Schaefer struct em28xx *dev = i2c_bus->dev; 404a3ea4bf9SFrank Schaefer int rc = -EOPNOTSUPP; 405a3ea4bf9SFrank Schaefer 406a3ea4bf9SFrank Schaefer if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) 407a3ea4bf9SFrank Schaefer rc = em28xx_i2c_check_for_device(dev, addr); 408a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) 409a3ea4bf9SFrank Schaefer rc = em2800_i2c_check_for_device(dev, addr); 410a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) 411a3ea4bf9SFrank Schaefer rc = em25xx_bus_B_check_for_device(dev, addr); 412*e63b009dSMauro Carvalho Chehab if (rc == -ENXIO) { 413a3ea4bf9SFrank Schaefer if (i2c_debug) 414a3ea4bf9SFrank Schaefer printk(" no device\n"); 415a3ea4bf9SFrank Schaefer } 416a3ea4bf9SFrank Schaefer return rc; 417a3ea4bf9SFrank Schaefer } 418a3ea4bf9SFrank Schaefer 419a3ea4bf9SFrank Schaefer static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus, 420a3ea4bf9SFrank Schaefer struct i2c_msg msg) 421a3ea4bf9SFrank Schaefer { 422a3ea4bf9SFrank Schaefer struct em28xx *dev = i2c_bus->dev; 423a3ea4bf9SFrank Schaefer u16 addr = msg.addr << 1; 424a3ea4bf9SFrank Schaefer int byte, rc = -EOPNOTSUPP; 425a3ea4bf9SFrank Schaefer 426a3ea4bf9SFrank Schaefer if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) 427a3ea4bf9SFrank Schaefer rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len); 428a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) 429a3ea4bf9SFrank Schaefer rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len); 430a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) 431a3ea4bf9SFrank Schaefer rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len); 432a3ea4bf9SFrank Schaefer if (i2c_debug) { 433a3ea4bf9SFrank Schaefer for (byte = 0; byte < msg.len; byte++) 434a3ea4bf9SFrank Schaefer printk(" %02x", msg.buf[byte]); 435a3ea4bf9SFrank Schaefer } 436a3ea4bf9SFrank Schaefer return rc; 437a3ea4bf9SFrank Schaefer } 438a3ea4bf9SFrank Schaefer 439a3ea4bf9SFrank Schaefer static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus, 440a3ea4bf9SFrank Schaefer struct i2c_msg msg, int stop) 441a3ea4bf9SFrank Schaefer { 442a3ea4bf9SFrank Schaefer struct em28xx *dev = i2c_bus->dev; 443a3ea4bf9SFrank Schaefer u16 addr = msg.addr << 1; 444a3ea4bf9SFrank Schaefer int byte, rc = -EOPNOTSUPP; 445a3ea4bf9SFrank Schaefer 446a3ea4bf9SFrank Schaefer if (i2c_debug) { 447a3ea4bf9SFrank Schaefer for (byte = 0; byte < msg.len; byte++) 448a3ea4bf9SFrank Schaefer printk(" %02x", msg.buf[byte]); 449a3ea4bf9SFrank Schaefer } 450a3ea4bf9SFrank Schaefer if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) 451a3ea4bf9SFrank Schaefer rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop); 452a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) 453a3ea4bf9SFrank Schaefer rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len); 454a3ea4bf9SFrank Schaefer else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) 455a3ea4bf9SFrank Schaefer rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len); 456a3ea4bf9SFrank Schaefer return rc; 457a3ea4bf9SFrank Schaefer } 458a3ea4bf9SFrank Schaefer 459a3ea4bf9SFrank Schaefer /* 4600c0d06caSMauro Carvalho Chehab * em28xx_i2c_xfer() 4610c0d06caSMauro Carvalho Chehab * the main i2c transfer function 4620c0d06caSMauro Carvalho Chehab */ 4630c0d06caSMauro Carvalho Chehab static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, 4640c0d06caSMauro Carvalho Chehab struct i2c_msg msgs[], int num) 4650c0d06caSMauro Carvalho Chehab { 466aab3125cSMauro Carvalho Chehab struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data; 467aab3125cSMauro Carvalho Chehab struct em28xx *dev = i2c_bus->dev; 468aab3125cSMauro Carvalho Chehab unsigned bus = i2c_bus->bus; 469a3ea4bf9SFrank Schaefer int addr, rc, i; 4703190fbeeSMauro Carvalho Chehab u8 reg; 4710c0d06caSMauro Carvalho Chehab 472aab3125cSMauro Carvalho Chehab rc = rt_mutex_trylock(&dev->i2c_bus_lock); 473aab3125cSMauro Carvalho Chehab if (rc < 0) 474aab3125cSMauro Carvalho Chehab return rc; 475aab3125cSMauro Carvalho Chehab 476aab3125cSMauro Carvalho Chehab /* Switch I2C bus if needed */ 477a3ea4bf9SFrank Schaefer if (bus != dev->cur_i2c_bus && 478a3ea4bf9SFrank Schaefer i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) { 479aab3125cSMauro Carvalho Chehab if (bus == 1) 4803190fbeeSMauro Carvalho Chehab reg = EM2874_I2C_SECONDARY_BUS_SELECT; 481aab3125cSMauro Carvalho Chehab else 4823190fbeeSMauro Carvalho Chehab reg = 0; 4833190fbeeSMauro Carvalho Chehab em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg, 4843190fbeeSMauro Carvalho Chehab EM2874_I2C_SECONDARY_BUS_SELECT); 485aab3125cSMauro Carvalho Chehab dev->cur_i2c_bus = bus; 486aab3125cSMauro Carvalho Chehab } 487aab3125cSMauro Carvalho Chehab 488aab3125cSMauro Carvalho Chehab if (num <= 0) { 489aab3125cSMauro Carvalho Chehab rt_mutex_unlock(&dev->i2c_bus_lock); 4900c0d06caSMauro Carvalho Chehab return 0; 491aab3125cSMauro Carvalho Chehab } 4920c0d06caSMauro Carvalho Chehab for (i = 0; i < num; i++) { 4930c0d06caSMauro Carvalho Chehab addr = msgs[i].addr << 1; 494d90f0677SFrank Schaefer if (i2c_debug) 495d7a80eaaSFrank Schaefer printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:", 496d7a80eaaSFrank Schaefer dev->name, __func__ , 4970c0d06caSMauro Carvalho Chehab (msgs[i].flags & I2C_M_RD) ? "read" : "write", 498d7a80eaaSFrank Schaefer i == num - 1 ? "stop" : "nonstop", 499d7a80eaaSFrank Schaefer addr, msgs[i].len); 500*e63b009dSMauro Carvalho Chehab if (!msgs[i].len) { 501*e63b009dSMauro Carvalho Chehab /* 502*e63b009dSMauro Carvalho Chehab * no len: check only for device presence 503*e63b009dSMauro Carvalho Chehab * This code is only called during device probe. 504*e63b009dSMauro Carvalho Chehab */ 505a3ea4bf9SFrank Schaefer rc = i2c_check_for_device(i2c_bus, addr); 506*e63b009dSMauro Carvalho Chehab if (rc == -ENXIO) { 507aab3125cSMauro Carvalho Chehab rt_mutex_unlock(&dev->i2c_bus_lock); 508*e63b009dSMauro Carvalho Chehab return -ENODEV; 5090c0d06caSMauro Carvalho Chehab } 5100c0d06caSMauro Carvalho Chehab } else if (msgs[i].flags & I2C_M_RD) { 5110c0d06caSMauro Carvalho Chehab /* read bytes */ 512a3ea4bf9SFrank Schaefer rc = i2c_recv_bytes(i2c_bus, msgs[i]); 5130c0d06caSMauro Carvalho Chehab } else { 5140c0d06caSMauro Carvalho Chehab /* write bytes */ 515a3ea4bf9SFrank Schaefer rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1); 5160c0d06caSMauro Carvalho Chehab } 51745f04e82SFrank Schaefer if (rc < 0) { 518d90f0677SFrank Schaefer if (i2c_debug) 51945f04e82SFrank Schaefer printk(" ERROR: %i\n", rc); 520aab3125cSMauro Carvalho Chehab rt_mutex_unlock(&dev->i2c_bus_lock); 52145f04e82SFrank Schaefer return rc; 52245f04e82SFrank Schaefer } 523d90f0677SFrank Schaefer if (i2c_debug) 5240c0d06caSMauro Carvalho Chehab printk("\n"); 5250c0d06caSMauro Carvalho Chehab } 5260c0d06caSMauro Carvalho Chehab 527aab3125cSMauro Carvalho Chehab rt_mutex_unlock(&dev->i2c_bus_lock); 5280c0d06caSMauro Carvalho Chehab return num; 5290c0d06caSMauro Carvalho Chehab } 5300c0d06caSMauro Carvalho Chehab 531fa74aca3SFrank Schaefer /* 532fa74aca3SFrank Schaefer * based on linux/sunrpc/svcauth.h and linux/hash.h 5330c0d06caSMauro Carvalho Chehab * The original hash function returns a different value, if arch is x86_64 5340c0d06caSMauro Carvalho Chehab * or i386. 5350c0d06caSMauro Carvalho Chehab */ 5360c0d06caSMauro Carvalho Chehab static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) 5370c0d06caSMauro Carvalho Chehab { 5380c0d06caSMauro Carvalho Chehab unsigned long hash = 0; 5390c0d06caSMauro Carvalho Chehab unsigned long l = 0; 5400c0d06caSMauro Carvalho Chehab int len = 0; 5410c0d06caSMauro Carvalho Chehab unsigned char c; 5420c0d06caSMauro Carvalho Chehab do { 5430c0d06caSMauro Carvalho Chehab if (len == length) { 5440c0d06caSMauro Carvalho Chehab c = (char)len; 5450c0d06caSMauro Carvalho Chehab len = -1; 5460c0d06caSMauro Carvalho Chehab } else 5470c0d06caSMauro Carvalho Chehab c = *buf++; 5480c0d06caSMauro Carvalho Chehab l = (l << 8) | c; 5490c0d06caSMauro Carvalho Chehab len++; 5500c0d06caSMauro Carvalho Chehab if ((len & (32 / 8 - 1)) == 0) 5510c0d06caSMauro Carvalho Chehab hash = ((hash^l) * 0x9e370001UL); 5520c0d06caSMauro Carvalho Chehab } while (len); 5530c0d06caSMauro Carvalho Chehab 5540c0d06caSMauro Carvalho Chehab return (hash >> (32 - bits)) & 0xffffffffUL; 5550c0d06caSMauro Carvalho Chehab } 5560c0d06caSMauro Carvalho Chehab 557fa74aca3SFrank Schaefer /* 558fa74aca3SFrank Schaefer * Helper function to read data blocks from i2c clients with 8 or 16 bit 559fa74aca3SFrank Schaefer * address width, 8 bit register width and auto incrementation been activated 560fa74aca3SFrank Schaefer */ 561aab3125cSMauro Carvalho Chehab static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr, 562aab3125cSMauro Carvalho Chehab bool addr_w16, u16 len, u8 *data) 563d832c5b2SFrank Schaefer { 564d832c5b2SFrank Schaefer int remain = len, rsize, rsize_max, ret; 565d832c5b2SFrank Schaefer u8 buf[2]; 566d832c5b2SFrank Schaefer 567d832c5b2SFrank Schaefer /* Sanity check */ 568d832c5b2SFrank Schaefer if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1)) 569d832c5b2SFrank Schaefer return -EINVAL; 570d832c5b2SFrank Schaefer /* Select address */ 571d832c5b2SFrank Schaefer buf[0] = addr >> 8; 572d832c5b2SFrank Schaefer buf[1] = addr & 0xff; 573aab3125cSMauro Carvalho Chehab ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16); 574d832c5b2SFrank Schaefer if (ret < 0) 575d832c5b2SFrank Schaefer return ret; 576d832c5b2SFrank Schaefer /* Read data */ 577d832c5b2SFrank Schaefer if (dev->board.is_em2800) 578d832c5b2SFrank Schaefer rsize_max = 4; 579d832c5b2SFrank Schaefer else 580d832c5b2SFrank Schaefer rsize_max = 64; 581d832c5b2SFrank Schaefer while (remain > 0) { 582d832c5b2SFrank Schaefer if (remain > rsize_max) 583d832c5b2SFrank Schaefer rsize = rsize_max; 584d832c5b2SFrank Schaefer else 585d832c5b2SFrank Schaefer rsize = remain; 586d832c5b2SFrank Schaefer 587aab3125cSMauro Carvalho Chehab ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize); 588d832c5b2SFrank Schaefer if (ret < 0) 589d832c5b2SFrank Schaefer return ret; 590d832c5b2SFrank Schaefer 591d832c5b2SFrank Schaefer remain -= rsize; 592d832c5b2SFrank Schaefer data += rsize; 593d832c5b2SFrank Schaefer } 594d832c5b2SFrank Schaefer 595d832c5b2SFrank Schaefer return len; 596d832c5b2SFrank Schaefer } 597d832c5b2SFrank Schaefer 598aab3125cSMauro Carvalho Chehab static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus, 599aab3125cSMauro Carvalho Chehab u8 **eedata, u16 *eedata_len) 6000c0d06caSMauro Carvalho Chehab { 601510e884cSFrank Schaefer const u16 len = 256; 602fa74aca3SFrank Schaefer /* 603fa74aca3SFrank Schaefer * FIXME common length/size for bytes to read, to display, hash 604510e884cSFrank Schaefer * calculation and returned device dataset. Simplifies the code a lot, 605fa74aca3SFrank Schaefer * but we might have to deal with multiple sizes in the future ! 606fa74aca3SFrank Schaefer */ 607d832c5b2SFrank Schaefer int i, err; 608510e884cSFrank Schaefer struct em28xx_eeprom *dev_config; 609510e884cSFrank Schaefer u8 buf, *data; 6100c0d06caSMauro Carvalho Chehab 611a217968fSFrank Schaefer *eedata = NULL; 612510e884cSFrank Schaefer *eedata_len = 0; 613a217968fSFrank Schaefer 614aab3125cSMauro Carvalho Chehab /* EEPROM is always on i2c bus 0 on all known devices. */ 615aab3125cSMauro Carvalho Chehab 616aab3125cSMauro Carvalho Chehab dev->i2c_client[bus].addr = 0xa0 >> 1; 6170c0d06caSMauro Carvalho Chehab 6180c0d06caSMauro Carvalho Chehab /* Check if board has eeprom */ 619aab3125cSMauro Carvalho Chehab err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0); 6200c0d06caSMauro Carvalho Chehab if (err < 0) { 62112d7ce18SFrank Schaefer em28xx_info("board has no eeprom\n"); 6220c0d06caSMauro Carvalho Chehab return -ENODEV; 6230c0d06caSMauro Carvalho Chehab } 6240c0d06caSMauro Carvalho Chehab 625a217968fSFrank Schaefer data = kzalloc(len, GFP_KERNEL); 626a217968fSFrank Schaefer if (data == NULL) 627a217968fSFrank Schaefer return -ENOMEM; 628a217968fSFrank Schaefer 629d832c5b2SFrank Schaefer /* Read EEPROM content */ 630aab3125cSMauro Carvalho Chehab err = em28xx_i2c_read_block(dev, bus, 0x0000, 631aab3125cSMauro Carvalho Chehab dev->eeprom_addrwidth_16bit, 632a217968fSFrank Schaefer len, data); 633d832c5b2SFrank Schaefer if (err != len) { 63412d7ce18SFrank Schaefer em28xx_errdev("failed to read eeprom (err=%d)\n", err); 635510e884cSFrank Schaefer goto error; 6360c0d06caSMauro Carvalho Chehab } 63790271964SFrank Schaefer 63887b52439SFrank Schaefer /* Display eeprom content */ 6390c0d06caSMauro Carvalho Chehab for (i = 0; i < len; i++) { 64087b52439SFrank Schaefer if (0 == (i % 16)) { 64187b52439SFrank Schaefer if (dev->eeprom_addrwidth_16bit) 64287b52439SFrank Schaefer em28xx_info("i2c eeprom %04x:", i); 64387b52439SFrank Schaefer else 64412d7ce18SFrank Schaefer em28xx_info("i2c eeprom %02x:", i); 64587b52439SFrank Schaefer } 646a217968fSFrank Schaefer printk(" %02x", data[i]); 6470c0d06caSMauro Carvalho Chehab if (15 == (i % 16)) 6480c0d06caSMauro Carvalho Chehab printk("\n"); 6490c0d06caSMauro Carvalho Chehab } 650510e884cSFrank Schaefer if (dev->eeprom_addrwidth_16bit) 651510e884cSFrank Schaefer em28xx_info("i2c eeprom %04x: ... (skipped)\n", i); 6520c0d06caSMauro Carvalho Chehab 65387b52439SFrank Schaefer if (dev->eeprom_addrwidth_16bit && 654a217968fSFrank Schaefer data[0] == 0x26 && data[3] == 0x00) { 65587b52439SFrank Schaefer /* new eeprom format; size 4-64kb */ 656510e884cSFrank Schaefer u16 mc_start; 657510e884cSFrank Schaefer u16 hwconf_offset; 658510e884cSFrank Schaefer 659a217968fSFrank Schaefer dev->hash = em28xx_hash_mem(data, len, 32); 660510e884cSFrank Schaefer mc_start = (data[1] << 8) + 4; /* usually 0x0004 */ 661510e884cSFrank Schaefer 662d230d5adSFrank Schaefer em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n", 663510e884cSFrank Schaefer data[0], data[1], data[2], data[3], dev->hash); 664510e884cSFrank Schaefer em28xx_info("EEPROM info:\n"); 665d230d5adSFrank Schaefer em28xx_info("\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n", 666510e884cSFrank Schaefer mc_start, data[2]); 667fa74aca3SFrank Schaefer /* 668fa74aca3SFrank Schaefer * boot configuration (address 0x0002): 66987b52439SFrank Schaefer * [0] microcode download speed: 1 = 400 kHz; 0 = 100 kHz 67087b52439SFrank Schaefer * [1] always selects 12 kb RAM 67187b52439SFrank Schaefer * [2] USB device speed: 1 = force Full Speed; 0 = auto detect 67287b52439SFrank Schaefer * [4] 1 = force fast mode and no suspend for device testing 67387b52439SFrank Schaefer * [5:7] USB PHY tuning registers; determined by device 67487b52439SFrank Schaefer * characterization 67587b52439SFrank Schaefer */ 67687b52439SFrank Schaefer 677fa74aca3SFrank Schaefer /* 678fa74aca3SFrank Schaefer * Read hardware config dataset offset from address 679fa74aca3SFrank Schaefer * (microcode start + 46) 680fa74aca3SFrank Schaefer */ 681aab3125cSMauro Carvalho Chehab err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2, 682aab3125cSMauro Carvalho Chehab data); 683510e884cSFrank Schaefer if (err != 2) { 684510e884cSFrank Schaefer em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n", 685510e884cSFrank Schaefer err); 686510e884cSFrank Schaefer goto error; 687510e884cSFrank Schaefer } 68887b52439SFrank Schaefer 689510e884cSFrank Schaefer /* Calculate hardware config dataset start address */ 690510e884cSFrank Schaefer hwconf_offset = mc_start + data[0] + (data[1] << 8); 691510e884cSFrank Schaefer 692510e884cSFrank Schaefer /* Read hardware config dataset */ 693fa74aca3SFrank Schaefer /* 694fa74aca3SFrank Schaefer * NOTE: the microcode copy can be multiple pages long, but 695510e884cSFrank Schaefer * we assume the hardware config dataset is the same as in 696510e884cSFrank Schaefer * the old eeprom and not longer than 256 bytes. 697510e884cSFrank Schaefer * tveeprom is currently also limited to 256 bytes. 698510e884cSFrank Schaefer */ 699aab3125cSMauro Carvalho Chehab err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len, 700aab3125cSMauro Carvalho Chehab data); 701510e884cSFrank Schaefer if (err != len) { 702510e884cSFrank Schaefer em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n", 703510e884cSFrank Schaefer err); 704510e884cSFrank Schaefer goto error; 705510e884cSFrank Schaefer } 706510e884cSFrank Schaefer 707510e884cSFrank Schaefer /* Verify hardware config dataset */ 708510e884cSFrank Schaefer /* NOTE: not all devices provide this type of dataset */ 709510e884cSFrank Schaefer if (data[0] != 0x1a || data[1] != 0xeb || 710a217968fSFrank Schaefer data[2] != 0x67 || data[3] != 0x95) { 711510e884cSFrank Schaefer em28xx_info("\tno hardware configuration dataset found in eeprom\n"); 712510e884cSFrank Schaefer kfree(data); 713510e884cSFrank Schaefer return 0; 714510e884cSFrank Schaefer } 715510e884cSFrank Schaefer 716510e884cSFrank Schaefer /* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */ 717510e884cSFrank Schaefer 718510e884cSFrank Schaefer } else if (!dev->eeprom_addrwidth_16bit && 719510e884cSFrank Schaefer data[0] == 0x1a && data[1] == 0xeb && 720510e884cSFrank Schaefer data[2] == 0x67 && data[3] == 0x95) { 721510e884cSFrank Schaefer dev->hash = em28xx_hash_mem(data, len, 32); 722d230d5adSFrank Schaefer em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n", 723510e884cSFrank Schaefer data[0], data[1], data[2], data[3], dev->hash); 724510e884cSFrank Schaefer em28xx_info("EEPROM info:\n"); 725510e884cSFrank Schaefer } else { 72687b52439SFrank Schaefer em28xx_info("unknown eeprom format or eeprom corrupted !\n"); 727510e884cSFrank Schaefer err = -ENODEV; 728510e884cSFrank Schaefer goto error; 729f55eacbeSFrank Schaefer } 730f55eacbeSFrank Schaefer 731a217968fSFrank Schaefer *eedata = data; 732510e884cSFrank Schaefer *eedata_len = len; 73332bf7c6cSAlban Browaeys dev_config = (void *)*eedata; 734a217968fSFrank Schaefer 735510e884cSFrank Schaefer switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) { 7360c0d06caSMauro Carvalho Chehab case 0: 73712d7ce18SFrank Schaefer em28xx_info("\tNo audio on board.\n"); 7380c0d06caSMauro Carvalho Chehab break; 7390c0d06caSMauro Carvalho Chehab case 1: 74012d7ce18SFrank Schaefer em28xx_info("\tAC97 audio (5 sample rates)\n"); 7410c0d06caSMauro Carvalho Chehab break; 7420c0d06caSMauro Carvalho Chehab case 2: 743687ff8b0SFrank Schaefer if (dev->chip_id < CHIP_ID_EM2860) 74412d7ce18SFrank Schaefer em28xx_info("\tI2S audio, sample rate=32k\n"); 745687ff8b0SFrank Schaefer else 746687ff8b0SFrank Schaefer em28xx_info("\tI2S audio, 3 sample rates\n"); 7470c0d06caSMauro Carvalho Chehab break; 7480c0d06caSMauro Carvalho Chehab case 3: 749687ff8b0SFrank Schaefer if (dev->chip_id < CHIP_ID_EM2860) 75012d7ce18SFrank Schaefer em28xx_info("\tI2S audio, 3 sample rates\n"); 751687ff8b0SFrank Schaefer else 752687ff8b0SFrank Schaefer em28xx_info("\tI2S audio, 5 sample rates\n"); 7530c0d06caSMauro Carvalho Chehab break; 7540c0d06caSMauro Carvalho Chehab } 7550c0d06caSMauro Carvalho Chehab 756510e884cSFrank Schaefer if (le16_to_cpu(dev_config->chip_conf) & 1 << 3) 75712d7ce18SFrank Schaefer em28xx_info("\tUSB Remote wakeup capable\n"); 7580c0d06caSMauro Carvalho Chehab 759510e884cSFrank Schaefer if (le16_to_cpu(dev_config->chip_conf) & 1 << 2) 76012d7ce18SFrank Schaefer em28xx_info("\tUSB Self power capable\n"); 7610c0d06caSMauro Carvalho Chehab 762510e884cSFrank Schaefer switch (le16_to_cpu(dev_config->chip_conf) & 0x3) { 7630c0d06caSMauro Carvalho Chehab case 0: 76412d7ce18SFrank Schaefer em28xx_info("\t500mA max power\n"); 7650c0d06caSMauro Carvalho Chehab break; 7660c0d06caSMauro Carvalho Chehab case 1: 76712d7ce18SFrank Schaefer em28xx_info("\t400mA max power\n"); 7680c0d06caSMauro Carvalho Chehab break; 7690c0d06caSMauro Carvalho Chehab case 2: 77012d7ce18SFrank Schaefer em28xx_info("\t300mA max power\n"); 7710c0d06caSMauro Carvalho Chehab break; 7720c0d06caSMauro Carvalho Chehab case 3: 77312d7ce18SFrank Schaefer em28xx_info("\t200mA max power\n"); 7740c0d06caSMauro Carvalho Chehab break; 7750c0d06caSMauro Carvalho Chehab } 77612d7ce18SFrank Schaefer em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", 777510e884cSFrank Schaefer dev_config->string_idx_table, 778510e884cSFrank Schaefer le16_to_cpu(dev_config->string1), 779510e884cSFrank Schaefer le16_to_cpu(dev_config->string2), 780510e884cSFrank Schaefer le16_to_cpu(dev_config->string3)); 7810c0d06caSMauro Carvalho Chehab 7820c0d06caSMauro Carvalho Chehab return 0; 783510e884cSFrank Schaefer 784510e884cSFrank Schaefer error: 785510e884cSFrank Schaefer kfree(data); 786510e884cSFrank Schaefer return err; 7870c0d06caSMauro Carvalho Chehab } 7880c0d06caSMauro Carvalho Chehab 7890c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 7900c0d06caSMauro Carvalho Chehab 7910c0d06caSMauro Carvalho Chehab /* 7920c0d06caSMauro Carvalho Chehab * functionality() 7930c0d06caSMauro Carvalho Chehab */ 794aab3125cSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *i2c_adap) 7950c0d06caSMauro Carvalho Chehab { 796aab3125cSMauro Carvalho Chehab struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data; 797aab3125cSMauro Carvalho Chehab 798a3ea4bf9SFrank Schaefer if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) || 799a3ea4bf9SFrank Schaefer (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) { 800a3ea4bf9SFrank Schaefer return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 801a3ea4bf9SFrank Schaefer } else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) { 802a3ea4bf9SFrank Schaefer return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) & 803a3ea4bf9SFrank Schaefer ~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA; 804a3ea4bf9SFrank Schaefer } 805a3ea4bf9SFrank Schaefer 806a3ea4bf9SFrank Schaefer WARN(1, "Unknown i2c bus algorithm.\n"); 807a3ea4bf9SFrank Schaefer return 0; 8080c0d06caSMauro Carvalho Chehab } 8090c0d06caSMauro Carvalho Chehab 8100c0d06caSMauro Carvalho Chehab static struct i2c_algorithm em28xx_algo = { 8110c0d06caSMauro Carvalho Chehab .master_xfer = em28xx_i2c_xfer, 8120c0d06caSMauro Carvalho Chehab .functionality = functionality, 8130c0d06caSMauro Carvalho Chehab }; 8140c0d06caSMauro Carvalho Chehab 8150c0d06caSMauro Carvalho Chehab static struct i2c_adapter em28xx_adap_template = { 8160c0d06caSMauro Carvalho Chehab .owner = THIS_MODULE, 8170c0d06caSMauro Carvalho Chehab .name = "em28xx", 8180c0d06caSMauro Carvalho Chehab .algo = &em28xx_algo, 8190c0d06caSMauro Carvalho Chehab }; 8200c0d06caSMauro Carvalho Chehab 8210c0d06caSMauro Carvalho Chehab static struct i2c_client em28xx_client_template = { 8220c0d06caSMauro Carvalho Chehab .name = "em28xx internal", 8230c0d06caSMauro Carvalho Chehab }; 8240c0d06caSMauro Carvalho Chehab 8250c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 8260c0d06caSMauro Carvalho Chehab 8270c0d06caSMauro Carvalho Chehab /* 8280c0d06caSMauro Carvalho Chehab * i2c_devs 8290c0d06caSMauro Carvalho Chehab * incomplete list of known devices 8300c0d06caSMauro Carvalho Chehab */ 8310c0d06caSMauro Carvalho Chehab static char *i2c_devs[128] = { 8320b3966e4SFrank Schaefer [0x3e >> 1] = "remote IR sensor", 8330c0d06caSMauro Carvalho Chehab [0x4a >> 1] = "saa7113h", 8340c0d06caSMauro Carvalho Chehab [0x52 >> 1] = "drxk", 8350c0d06caSMauro Carvalho Chehab [0x60 >> 1] = "remote IR sensor", 8360c0d06caSMauro Carvalho Chehab [0x8e >> 1] = "remote IR sensor", 8370c0d06caSMauro Carvalho Chehab [0x86 >> 1] = "tda9887", 8380c0d06caSMauro Carvalho Chehab [0x80 >> 1] = "msp34xx", 8390c0d06caSMauro Carvalho Chehab [0x88 >> 1] = "msp34xx", 8400c0d06caSMauro Carvalho Chehab [0xa0 >> 1] = "eeprom", 8410c0d06caSMauro Carvalho Chehab [0xb0 >> 1] = "tda9874", 8420c0d06caSMauro Carvalho Chehab [0xb8 >> 1] = "tvp5150a", 8430c0d06caSMauro Carvalho Chehab [0xba >> 1] = "webcam sensor or tvp5150a", 8440c0d06caSMauro Carvalho Chehab [0xc0 >> 1] = "tuner (analog)", 8450c0d06caSMauro Carvalho Chehab [0xc2 >> 1] = "tuner (analog)", 8460c0d06caSMauro Carvalho Chehab [0xc4 >> 1] = "tuner (analog)", 8470c0d06caSMauro Carvalho Chehab [0xc6 >> 1] = "tuner (analog)", 8480c0d06caSMauro Carvalho Chehab }; 8490c0d06caSMauro Carvalho Chehab 8500c0d06caSMauro Carvalho Chehab /* 8510c0d06caSMauro Carvalho Chehab * do_i2c_scan() 8520c0d06caSMauro Carvalho Chehab * check i2c address range for devices 8530c0d06caSMauro Carvalho Chehab */ 854aab3125cSMauro Carvalho Chehab void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus) 8550c0d06caSMauro Carvalho Chehab { 8560c0d06caSMauro Carvalho Chehab u8 i2c_devicelist[128]; 8570c0d06caSMauro Carvalho Chehab unsigned char buf; 8580c0d06caSMauro Carvalho Chehab int i, rc; 8590c0d06caSMauro Carvalho Chehab 8600c0d06caSMauro Carvalho Chehab memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); 8610c0d06caSMauro Carvalho Chehab 8620c0d06caSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { 863aab3125cSMauro Carvalho Chehab dev->i2c_client[bus].addr = i; 864aab3125cSMauro Carvalho Chehab rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0); 8650c0d06caSMauro Carvalho Chehab if (rc < 0) 8660c0d06caSMauro Carvalho Chehab continue; 8670c0d06caSMauro Carvalho Chehab i2c_devicelist[i] = i; 868aab3125cSMauro Carvalho Chehab em28xx_info("found i2c device @ 0x%x on bus %d [%s]\n", 869aab3125cSMauro Carvalho Chehab i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???"); 8700c0d06caSMauro Carvalho Chehab } 8710c0d06caSMauro Carvalho Chehab 872aab3125cSMauro Carvalho Chehab if (bus == dev->def_i2c_bus) 8730c0d06caSMauro Carvalho Chehab dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, 8740c0d06caSMauro Carvalho Chehab ARRAY_SIZE(i2c_devicelist), 32); 8750c0d06caSMauro Carvalho Chehab } 8760c0d06caSMauro Carvalho Chehab 8770c0d06caSMauro Carvalho Chehab /* 8780c0d06caSMauro Carvalho Chehab * em28xx_i2c_register() 8790c0d06caSMauro Carvalho Chehab * register i2c bus 8800c0d06caSMauro Carvalho Chehab */ 881a3ea4bf9SFrank Schaefer int em28xx_i2c_register(struct em28xx *dev, unsigned bus, 882a3ea4bf9SFrank Schaefer enum em28xx_i2c_algo_type algo_type) 8830c0d06caSMauro Carvalho Chehab { 8840c0d06caSMauro Carvalho Chehab int retval; 8850c0d06caSMauro Carvalho Chehab 8860c0d06caSMauro Carvalho Chehab BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); 8870c0d06caSMauro Carvalho Chehab BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); 8880c0d06caSMauro Carvalho Chehab 889aab3125cSMauro Carvalho Chehab if (bus >= NUM_I2C_BUSES) 890aab3125cSMauro Carvalho Chehab return -ENODEV; 891aab3125cSMauro Carvalho Chehab 892aab3125cSMauro Carvalho Chehab dev->i2c_adap[bus] = em28xx_adap_template; 893aab3125cSMauro Carvalho Chehab dev->i2c_adap[bus].dev.parent = &dev->udev->dev; 894aab3125cSMauro Carvalho Chehab strcpy(dev->i2c_adap[bus].name, dev->name); 895aab3125cSMauro Carvalho Chehab 896aab3125cSMauro Carvalho Chehab dev->i2c_bus[bus].bus = bus; 897a3ea4bf9SFrank Schaefer dev->i2c_bus[bus].algo_type = algo_type; 898aab3125cSMauro Carvalho Chehab dev->i2c_bus[bus].dev = dev; 899aab3125cSMauro Carvalho Chehab dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus]; 900aab3125cSMauro Carvalho Chehab i2c_set_adapdata(&dev->i2c_adap[bus], &dev->v4l2_dev); 901aab3125cSMauro Carvalho Chehab 902aab3125cSMauro Carvalho Chehab retval = i2c_add_adapter(&dev->i2c_adap[bus]); 9030c0d06caSMauro Carvalho Chehab if (retval < 0) { 9040c0d06caSMauro Carvalho Chehab em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", 9050c0d06caSMauro Carvalho Chehab __func__, retval); 9060c0d06caSMauro Carvalho Chehab return retval; 9070c0d06caSMauro Carvalho Chehab } 9080c0d06caSMauro Carvalho Chehab 909aab3125cSMauro Carvalho Chehab dev->i2c_client[bus] = em28xx_client_template; 910aab3125cSMauro Carvalho Chehab dev->i2c_client[bus].adapter = &dev->i2c_adap[bus]; 9110c0d06caSMauro Carvalho Chehab 912aab3125cSMauro Carvalho Chehab /* Up to now, all eeproms are at bus 0 */ 913aab3125cSMauro Carvalho Chehab if (!bus) { 914aab3125cSMauro Carvalho Chehab retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len); 9150c0d06caSMauro Carvalho Chehab if ((retval < 0) && (retval != -ENODEV)) { 9160c0d06caSMauro Carvalho Chehab em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", 9170c0d06caSMauro Carvalho Chehab __func__, retval); 9180c0d06caSMauro Carvalho Chehab 9190c0d06caSMauro Carvalho Chehab return retval; 9200c0d06caSMauro Carvalho Chehab } 921aab3125cSMauro Carvalho Chehab } 9220c0d06caSMauro Carvalho Chehab 9230c0d06caSMauro Carvalho Chehab if (i2c_scan) 924aab3125cSMauro Carvalho Chehab em28xx_do_i2c_scan(dev, bus); 9250c0d06caSMauro Carvalho Chehab 9260c0d06caSMauro Carvalho Chehab return 0; 9270c0d06caSMauro Carvalho Chehab } 9280c0d06caSMauro Carvalho Chehab 9290c0d06caSMauro Carvalho Chehab /* 9300c0d06caSMauro Carvalho Chehab * em28xx_i2c_unregister() 9310c0d06caSMauro Carvalho Chehab * unregister i2c_bus 9320c0d06caSMauro Carvalho Chehab */ 933aab3125cSMauro Carvalho Chehab int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus) 9340c0d06caSMauro Carvalho Chehab { 935aab3125cSMauro Carvalho Chehab if (bus >= NUM_I2C_BUSES) 936aab3125cSMauro Carvalho Chehab return -ENODEV; 937aab3125cSMauro Carvalho Chehab 938aab3125cSMauro Carvalho Chehab i2c_del_adapter(&dev->i2c_adap[bus]); 9390c0d06caSMauro Carvalho Chehab return 0; 9400c0d06caSMauro Carvalho Chehab } 941