drm/nouveau: fix i2c-related init table handlers
authorBen Skeggs <bskeggs@redhat.com>
Wed, 12 May 2010 06:30:50 +0000 (16:30 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 19 May 2010 06:22:08 +0000 (16:22 +1000)
Mutliple issues.  INIT_ZM_I2C_BYTE/INIT_I2C_BYTE didn't even try and
use the register value, and all the handlers were using the wrong
slave address.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_bios.c

index 327f6f34d78dd725b50b4790451a69ad9f0f24f3..e7e69ccce5c9985ba77b7e7790582f984c8efdb9 100644 (file)
@@ -1448,12 +1448,11 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         */
 
        uint8_t i2c_index = bios->data[offset + 1];
-       uint8_t i2c_address = bios->data[offset + 2];
+       uint8_t i2c_address = bios->data[offset + 2] >> 1;
        uint8_t count = bios->data[offset + 3];
-       int len = 4 + count * 3;
        struct nouveau_i2c_chan *chan;
-       struct i2c_msg msg;
-       int i;
+       int len = 4 + count * 3;
+       int ret, i;
 
        if (!iexec->execute)
                return len;
@@ -1467,32 +1466,31 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                return -ENODEV;
 
        for (i = 0; i < count; i++) {
-               uint8_t i2c_reg = bios->data[offset + 4 + i * 3];
+               uint8_t reg = bios->data[offset + 4 + i * 3];
                uint8_t mask = bios->data[offset + 5 + i * 3];
                uint8_t data = bios->data[offset + 6 + i * 3];
-               uint8_t value;
+               union i2c_smbus_data val;
 
-               msg.addr = i2c_address;
-               msg.flags = I2C_M_RD;
-               msg.len = 1;
-               msg.buf = &value;
-               if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
-                       return -EIO;
+               ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
+                                    I2C_SMBUS_READ, reg,
+                                    I2C_SMBUS_BYTE_DATA, &val);
+               if (ret < 0)
+                       return ret;
 
                BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, "
                              "Mask: 0x%02X, Data: 0x%02X\n",
-                       offset, i2c_reg, value, mask, data);
+                       offset, reg, val.byte, mask, data);
 
-               value = (value & mask) | data;
+               if (!bios->execute)
+                       continue;
 
-               if (bios->execute) {
-                       msg.addr = i2c_address;
-                       msg.flags = 0;
-                       msg.len = 1;
-                       msg.buf = &value;
-                       if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
-                               return -EIO;
-               }
+               val.byte &= mask;
+               val.byte |= data;
+               ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
+                                    I2C_SMBUS_WRITE, reg,
+                                    I2C_SMBUS_BYTE_DATA, &val);
+               if (ret < 0)
+                       return ret;
        }
 
        return len;
@@ -1518,12 +1516,11 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         */
 
        uint8_t i2c_index = bios->data[offset + 1];
-       uint8_t i2c_address = bios->data[offset + 2];
+       uint8_t i2c_address = bios->data[offset + 2] >> 1;
        uint8_t count = bios->data[offset + 3];
-       int len = 4 + count * 2;
        struct nouveau_i2c_chan *chan;
-       struct i2c_msg msg;
-       int i;
+       int len = 4 + count * 2;
+       int ret, i;
 
        if (!iexec->execute)
                return len;
@@ -1537,20 +1534,22 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                return -ENODEV;
 
        for (i = 0; i < count; i++) {
-               uint8_t i2c_reg = bios->data[offset + 4 + i * 2];
-               uint8_t data = bios->data[offset + 5 + i * 2];
+               uint8_t reg = bios->data[offset + 4 + i * 2];
+               union i2c_smbus_data val;
+
+               val.byte = bios->data[offset + 5 + i * 2];
 
                BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Data: 0x%02X\n",
-                       offset, i2c_reg, data);
-
-               if (bios->execute) {
-                       msg.addr = i2c_address;
-                       msg.flags = 0;
-                       msg.len = 1;
-                       msg.buf = &data;
-                       if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
-                               return -EIO;
-               }
+                       offset, reg, val.byte);
+
+               if (!bios->execute)
+                       continue;
+
+               ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
+                                    I2C_SMBUS_WRITE, reg,
+                                    I2C_SMBUS_BYTE_DATA, &val);
+               if (ret < 0)
+                       return ret;
        }
 
        return len;
@@ -1574,7 +1573,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         */
 
        uint8_t i2c_index = bios->data[offset + 1];
-       uint8_t i2c_address = bios->data[offset + 2];
+       uint8_t i2c_address = bios->data[offset + 2] >> 1;
        uint8_t count = bios->data[offset + 3];
        int len = 4 + count;
        struct nouveau_i2c_chan *chan;