[media] mt2060: add param to split long i2c writes
authorAntti Palosaari <crope@iki.fi>
Sun, 26 Jul 2015 20:30:07 +0000 (17:30 -0300)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Fri, 3 Feb 2017 08:44:03 +0000 (06:44 -0200)
Add configuration parameter to split long i2c writes as some I2C
adapters cannot write 10 bytes used as a one go.

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/tuners/mt2060.c
drivers/media/tuners/mt2060.h
drivers/media/tuners/mt2060_priv.h

index b8acfa27e84241c002e965f3870eeea835ff402d..14f5935f8898b9542a1f2070c8f507c4bc2152ce 100644 (file)
@@ -67,13 +67,24 @@ static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
 // Writes a set of consecutive registers
 static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
 {
+       int rem, val_len;
+       u8 xfer_buf[16];
        struct i2c_msg msg = {
-               .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
+               .addr = priv->cfg->i2c_address, .flags = 0, .buf = xfer_buf
        };
-       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-               printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len);
-               return -EREMOTEIO;
+
+       for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) {
+               val_len = min_t(int, rem, priv->i2c_max_regs);
+               msg.len = 1 + val_len;
+               xfer_buf[0] = buf[0] + len - 1 - rem;
+               memcpy(&xfer_buf[1], &buf[1 + len - 1 - rem], val_len);
+
+               if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+                       printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n", val_len);
+                       return -EREMOTEIO;
+               }
        }
+
        return 0;
 }
 
@@ -365,6 +376,7 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter
        priv->cfg      = cfg;
        priv->i2c      = i2c;
        priv->if1_freq = if1;
+       priv->i2c_max_regs = ~0;
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
@@ -422,6 +434,7 @@ static int mt2060_probe(struct i2c_client *client,
        dev->i2c = client->adapter;
        dev->if1_freq = pdata->if1 ? pdata->if1 : 1220;
        dev->client = client;
+       dev->i2c_max_regs = pdata->i2c_write_max ? pdata->i2c_write_max - 1 : ~0;
 
        ret = mt2060_readreg(dev, REG_PART_REV, &chip_id);
        if (ret) {
index 41feb2c1d2cd34b043ffdc29d5cb121c917f502d..cc534eb41378ffbeff1982d35cd6d65d92c2c059 100644 (file)
@@ -30,12 +30,15 @@ struct i2c_adapter;
  * struct mt2060_platform_data - Platform data for the mt2060 driver
  * @clock_out: Clock output setting. 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1.
  * @if1: First IF used [MHz]. 0 defaults to 1220.
+ * @i2c_write_max: Maximum number of bytes I2C adapter can write at once.
+ *  0 defaults to maximum.
  * @dvb_frontend: DVB frontend.
  */
 
 struct mt2060_platform_data {
        u8 clock_out;
        u16 if1;
+       unsigned int i2c_write_max:5;
        struct dvb_frontend *dvb_frontend;
 };
 
index af677b24528678a5b9552f7bb1549902cdd22b16..cc738aa82fe4edca14ec53ac28c256f5dbb1daa8 100644 (file)
@@ -94,6 +94,7 @@ struct mt2060_priv {
        struct i2c_client *client;
        struct mt2060_config config;
 
+       u8 i2c_max_regs;
        u32 frequency;
        u16 if1_freq;
        u8  fmfreq;