drm/nouveau/bios: add support for ccb 4.1
authorBen Skeggs <bskeggs@redhat.com>
Mon, 18 Aug 2014 22:20:26 +0000 (08:20 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 2 Dec 2014 05:43:46 +0000 (15:43 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h
drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c

index 79c1252e5c342ef77428a455f547be5d56ab5d39..c9bb112895aff3ea8b86eaa6237040ea946b1b96 100644 (file)
@@ -4,11 +4,14 @@
 struct nouveau_bios;
 
 enum dcb_i2c_type {
-       DCB_I2C_NV04_BIT = 0,
-       DCB_I2C_NV4E_BIT = 4,
-       DCB_I2C_NVIO_BIT = 5,
-       DCB_I2C_NVIO_AUX = 6,
-       DCB_I2C_UNUSED = 0xff
+       /* matches bios type field prior to ccb 4.1 */
+       DCB_I2C_NV04_BIT = 0x00,
+       DCB_I2C_NV4E_BIT = 0x04,
+       DCB_I2C_NVIO_BIT = 0x05,
+       DCB_I2C_NVIO_AUX = 0x06,
+       /* made up - mostly */
+       DCB_I2C_PMGR     = 0x80,
+       DCB_I2C_UNUSED   = 0xff
 };
 
 struct dcb_i2c_entry {
index 19ac30b28294df86f49916ddbb7590f39398c87c..282320ba9264155914600c397e34bbef6682db4b 100644 (file)
@@ -39,7 +39,7 @@ dcb_i2c_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
                        i2c = nv_ro16(bios, dcb + 4);
        }
 
-       if (i2c && *ver >= 0x41) {
+       if (i2c && *ver >= 0x42) {
                nv_warn(bios, "ccb %02x not supported\n", *ver);
                return 0x0000;
        }
@@ -75,6 +75,12 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
        u8  ver, len;
        u16 ent = dcb_i2c_entry(bios, idx, &ver, &len);
        if (ent) {
+               if (ver >= 0x41) {
+                       if (!(nv_ro32(bios, ent) & 0x80000000))
+                               info->type = DCB_I2C_UNUSED;
+                       else
+                               info->type = DCB_I2C_PMGR;
+               } else
                if (ver >= 0x30) {
                        info->type = nv_ro08(bios, ent + 0x03);
                } else {
@@ -104,7 +110,16 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
                case DCB_I2C_NVIO_AUX:
                        info->auxch = nv_ro08(bios, ent + 0) & 0x0f;
                        if (nv_ro08(bios, ent + 1) & 0x01)
-                               info->share = info->auxch;
+                                       info->share = info->auxch;
+                       return 0;
+               case DCB_I2C_PMGR:
+                       info->drive = (nv_ro16(bios, ent + 0) & 0x01f) >> 0;
+                       if (info->drive == 0x1f)
+                               info->drive = DCB_I2C_UNUSED;
+                       info->auxch = (nv_ro16(bios, ent + 0) & 0x3e0) >> 5;
+                       if (info->auxch == 0x1f)
+                               info->auxch = DCB_I2C_UNUSED;
+                       info->share = info->auxch;
                        return 0;
                case DCB_I2C_UNUSED:
                        return 0;