--- zzzz-none-000/linux-3.10.107/drivers/media/usb/em28xx/em28xx-i2c.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/usb/em28xx/em28xx-i2c.c 2021-02-04 17:41:59.000000000 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include #include "em28xx.h" #include "tuner-xc2028.h" @@ -40,7 +41,7 @@ static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); +MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I2C transfers)"); /* * em2800_i2c_send_bytes() @@ -48,8 +49,8 @@ */ static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) { + unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); int ret; - int write_timeout; u8 b2[6]; if (len < 1 || len > 4) @@ -74,22 +75,26 @@ return (ret < 0) ? ret : -EIO; } /* wait for completion */ - for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { + while (time_is_after_jiffies(timeout)) { ret = dev->em28xx_read_reg(dev, 0x05); - if (ret == 0x80 + len - 1) { + if (ret == 0x80 + len - 1) return len; - } else if (ret == 0x94 + len - 1) { - return -ENODEV; - } else if (ret < 0) { + if (ret == 0x94 + len - 1) { + if (i2c_debug == 1) + em28xx_warn("R05 returned 0x%02x: I2C ACK error\n", + ret); + return -ENXIO; + } + if (ret < 0) { em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", ret); return ret; } msleep(5); } - em28xx_warn("write to i2c device at 0x%x timed out\n", addr); - return -EIO; + if (i2c_debug) + em28xx_warn("write to i2c device at 0x%x timed out\n", addr); + return -ETIMEDOUT; } /* @@ -98,9 +103,9 @@ */ static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) { + unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); u8 buf2[4]; int ret; - int read_timeout; int i; if (len < 1 || len > 4) @@ -117,22 +122,28 @@ } /* wait for completion */ - for (read_timeout = EM2800_I2C_XFER_TIMEOUT; read_timeout > 0; - read_timeout -= 5) { + while (time_is_after_jiffies(timeout)) { ret = dev->em28xx_read_reg(dev, 0x05); - if (ret == 0x84 + len - 1) { + if (ret == 0x84 + len - 1) break; - } else if (ret == 0x94 + len - 1) { - return -ENODEV; - } else if (ret < 0) { + if (ret == 0x94 + len - 1) { + if (i2c_debug == 1) + em28xx_warn("R05 returned 0x%02x: I2C ACK error\n", + ret); + return -ENXIO; + } + if (ret < 0) { em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", ret); return ret; } msleep(5); } - if (ret != 0x84 + len - 1) - em28xx_warn("read from i2c device at 0x%x timed out\n", addr); + if (ret != 0x84 + len - 1) { + if (i2c_debug) + em28xx_warn("read from i2c device at 0x%x timed out\n", + addr); + } /* get the received message */ ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len); @@ -168,7 +179,8 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len, int stop) { - int write_timeout, ret; + unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT); + int ret; if (len < 1 || len > 64) return -EOPNOTSUPP; @@ -191,16 +203,19 @@ } } - /* Check success of the i2c operation */ - for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { + /* wait for completion */ + while (time_is_after_jiffies(timeout)) { ret = dev->em28xx_read_reg(dev, 0x05); - if (ret == 0) { /* success */ + if (ret == 0) /* success */ return len; - } else if (ret == 0x10) { - return -ENODEV; - } else if (ret < 0) { - em28xx_warn("failed to read i2c transfer status from bridge (error=%i)\n", + if (ret == 0x10) { + if (i2c_debug == 1) + em28xx_warn("I2C ACK error on writing to addr 0x%02x\n", + addr); + return -ENXIO; + } + if (ret < 0) { + em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", ret); return ret; } @@ -211,7 +226,17 @@ * (even with high payload) ... */ } - em28xx_warn("write to i2c device at 0x%x timed out\n", addr); + + if (ret == 0x02 || ret == 0x04) { + /* NOTE: these errors seem to be related to clock stretching */ + if (i2c_debug) + em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n", + addr, ret); + return -ETIMEDOUT; + } + + em28xx_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n", + addr, ret); return -EIO; } @@ -242,26 +267,37 @@ * bytes if we are on bus B AND there was no write attempt to the * specified slave address before AND no device is present at the * requested slave address. - * Anyway, the next check will fail with -ENODEV in this case, so avoid + * Anyway, the next check will fail with -ENXIO in this case, so avoid * spamming the system log on device probing and do nothing here. */ /* Check success of the i2c operation */ ret = dev->em28xx_read_reg(dev, 0x05); + if (ret == 0) /* success */ + return len; if (ret < 0) { - em28xx_warn("failed to read i2c transfer status from bridge (error=%i)\n", + em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n", ret); return ret; } - if (ret > 0) { - if (ret == 0x10) { - return -ENODEV; - } else { - em28xx_warn("unknown i2c error (status=%i)\n", ret); - return -EIO; - } + if (ret == 0x10) { + if (i2c_debug == 1) + em28xx_warn("I2C ACK error on writing to addr 0x%02x\n", + addr); + return -ENXIO; } - return len; + + if (ret == 0x02 || ret == 0x04) { + /* NOTE: these errors seem to be related to clock stretching */ + if (i2c_debug) + em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n", + addr, ret); + return -ETIMEDOUT; + } + + em28xx_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n", + addr, ret); + return -EIO; } /* @@ -316,8 +352,12 @@ */ if (!ret) return len; - else if (ret > 0) - return -ENODEV; + else if (ret > 0) { + if (i2c_debug == 1) + em28xx_warn("Bus B R08 returned 0x%02x: I2C ACK error\n", + ret); + return -ENXIO; + } return ret; /* @@ -355,7 +395,7 @@ * bytes if we are on bus B AND there was no write attempt to the * specified slave address before AND no device is present at the * requested slave address. - * Anyway, the next check will fail with -ENODEV in this case, so avoid + * Anyway, the next check will fail with -ENXIO in this case, so avoid * spamming the system log on device probing and do nothing here. */ @@ -367,8 +407,12 @@ */ if (!ret) return len; - else if (ret > 0) - return -ENODEV; + else if (ret > 0) { + if (i2c_debug == 1) + em28xx_warn("Bus B R08 returned 0x%02x: I2C ACK error\n", + ret); + return -ENXIO; + } return ret; /* @@ -409,10 +453,6 @@ rc = em2800_i2c_check_for_device(dev, addr); else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) rc = em25xx_bus_B_check_for_device(dev, addr); - if (rc == -ENODEV) { - if (i2c_debug) - printk(" no device\n"); - } return rc; } @@ -421,7 +461,7 @@ { struct em28xx *dev = i2c_bus->dev; u16 addr = msg.addr << 1; - int byte, rc = -EOPNOTSUPP; + int rc = -EOPNOTSUPP; if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len); @@ -429,10 +469,6 @@ rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len); else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len); - if (i2c_debug) { - for (byte = 0; byte < msg.len; byte++) - printk(" %02x", msg.buf[byte]); - } return rc; } @@ -441,12 +477,8 @@ { struct em28xx *dev = i2c_bus->dev; u16 addr = msg.addr << 1; - int byte, rc = -EOPNOTSUPP; + int rc = -EOPNOTSUPP; - if (i2c_debug) { - for (byte = 0; byte < msg.len; byte++) - printk(" %02x", msg.buf[byte]); - } if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop); else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) @@ -469,6 +501,12 @@ int addr, rc, i; u8 reg; + /* prevent i2c xfer attempts after device is disconnected + some fe's try to do i2c writes/reads from their release + interfaces when called in disconnect path */ + if (dev->disconnected) + return -ENODEV; + if (!rt_mutex_trylock(&dev->i2c_bus_lock)) return -EAGAIN; @@ -490,33 +528,53 @@ } for (i = 0; i < num; i++) { addr = msgs[i].addr << 1; - if (i2c_debug) + if (i2c_debug > 1) printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:", dev->name, __func__ , (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (!msgs[i].len) { /* no len: check only for device presence */ + if (!msgs[i].len) { + /* + * no len: check only for device presence + * This code is only called during device probe. + */ rc = i2c_check_for_device(i2c_bus, addr); - if (rc == -ENODEV) { + if (rc < 0) { + if (rc == -ENXIO) { + if (i2c_debug > 1) + printk(KERN_CONT " no device\n"); + rc = -ENODEV; + } else { + if (i2c_debug > 1) + printk(KERN_CONT " ERROR: %i\n", rc); + } rt_mutex_unlock(&dev->i2c_bus_lock); return rc; } } else if (msgs[i].flags & I2C_M_RD) { /* read bytes */ rc = i2c_recv_bytes(i2c_bus, msgs[i]); + + if (i2c_debug > 1 && rc >= 0) + printk(KERN_CONT " %*ph", + msgs[i].len, msgs[i].buf); } else { + if (i2c_debug > 1) + printk(KERN_CONT " %*ph", + msgs[i].len, msgs[i].buf); + /* write bytes */ rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1); } if (rc < 0) { - if (i2c_debug) - printk(" ERROR: %i\n", rc); + if (i2c_debug > 1) + printk(KERN_CONT " ERROR: %i\n", rc); rt_mutex_unlock(&dev->i2c_bus_lock); return rc; } - if (i2c_debug) - printk("\n"); + if (i2c_debug > 1) + printk(KERN_CONT "\n"); } rt_mutex_unlock(&dev->i2c_bus_lock); @@ -534,6 +592,7 @@ unsigned long l = 0; int len = 0; unsigned char c; + do { if (len == length) { c = (char)len; @@ -599,7 +658,7 @@ * calculation and returned device dataset. Simplifies the code a lot, * but we might have to deal with multiple sizes in the future ! */ - int i, err; + int err; struct em28xx_eeprom *dev_config; u8 buf, *data; @@ -630,20 +689,14 @@ goto error; } - /* Display eeprom content */ - for (i = 0; i < len; i++) { - if (0 == (i % 16)) { - if (dev->eeprom_addrwidth_16bit) - em28xx_info("i2c eeprom %04x:", i); - else - em28xx_info("i2c eeprom %02x:", i); - } - printk(" %02x", data[i]); - if (15 == (i % 16)) - printk("\n"); + if (i2c_debug) { + /* Display eeprom content */ + print_hex_dump(KERN_INFO, "eeprom ", DUMP_PREFIX_OFFSET, + 16, 1, data, len, true); + + if (dev->eeprom_addrwidth_16bit) + em28xx_info("eeprom %06x: ... (skipped)\n", 256); } - if (dev->eeprom_addrwidth_16bit) - em28xx_info("i2c eeprom %04x: ... (skipped)\n", i); if (dev->eeprom_addrwidth_16bit && data[0] == 0x26 && data[3] == 0x00) { @@ -735,10 +788,16 @@ em28xx_info("\tAC97 audio (5 sample rates)\n"); break; case 2: - em28xx_info("\tI2S audio, sample rate=32k\n"); + if (dev->chip_id < CHIP_ID_EM2860) + em28xx_info("\tI2S audio, sample rate=32k\n"); + else + em28xx_info("\tI2S audio, 3 sample rates\n"); break; case 3: - em28xx_info("\tI2S audio, 3 sample rates\n"); + if (dev->chip_id < CHIP_ID_EM2860) + em28xx_info("\tI2S audio, 3 sample rates\n"); + else + em28xx_info("\tI2S audio, 5 sample rates\n"); break; } @@ -818,6 +877,7 @@ * incomplete list of known devices */ static char *i2c_devs[128] = { + [0x1c >> 1] = "lgdt330x", [0x3e >> 1] = "remote IR sensor", [0x4a >> 1] = "saa7113h", [0x52 >> 1] = "drxk", @@ -886,12 +946,11 @@ dev->i2c_bus[bus].algo_type = algo_type; dev->i2c_bus[bus].dev = dev; dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus]; - i2c_set_adapdata(&dev->i2c_adap[bus], &dev->v4l2_dev); retval = i2c_add_adapter(&dev->i2c_adap[bus]); if (retval < 0) { em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", - __func__, retval); + __func__, retval); return retval; } @@ -903,7 +962,7 @@ retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len); if ((retval < 0) && (retval != -ENODEV)) { em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", - __func__, retval); + __func__, retval); return retval; }