drm/nouveau/bios: extend connector table parsing
authorBen Skeggs <bskeggs@redhat.com>
Wed, 14 May 2014 01:10:02 +0000 (11:10 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 11 Jun 2014 06:10:36 +0000 (16:10 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h
drivers/gpu/drm/nouveau/core/subdev/bios/conn.c
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c

index a32feb3f3fb67f0e1b662d4563ac2183805ca0b2..f3930c27cb7a242b4f75e09cf77ffded63b3e739 100644 (file)
@@ -22,7 +22,25 @@ enum dcb_connector_type {
        DCB_CONNECTOR_NONE = 0xff
 };
 
-u16 dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len);
+struct nvbios_connT {
+};
+
+u32 nvbios_connTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_connTp(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+                 struct nvbios_connT *info);
+
+struct nvbios_connE {
+       u8 type;
+       u8 location;
+       u8 hpd;
+       u8 dp;
+       u8 di;
+       u8 sr;
+       u8 lcdid;
+};
+
+u32 nvbios_connEe(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *hdr);
+u32 nvbios_connEp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *hdr,
+                 struct nvbios_connE *info);
 
 #endif
index 5ac010efd959651d873bc6d186b2dc06dc496968..2ede3bcd96a13f573a965ad35c4eb09baa32f3bd 100644 (file)
 #include <subdev/bios/dcb.h>
 #include <subdev/bios/conn.h>
 
-u16
-dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+u32
+nvbios_connTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
-       u16 dcb = dcb_table(bios, ver, hdr, cnt, len);
+       u32 dcb = dcb_table(bios, ver, hdr, cnt, len);
        if (dcb && *ver >= 0x30 && *hdr >= 0x16) {
-               u16 data = nv_ro16(bios, dcb + 0x14);
+               u32 data = nv_ro16(bios, dcb + 0x14);
                if (data) {
                        *ver = nv_ro08(bios, data + 0);
                        *hdr = nv_ro08(bios, data + 1);
@@ -42,15 +42,59 @@ dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
                        return data;
                }
        }
-       return 0x0000;
+       return 0x00000000;
 }
 
-u16
-dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len)
+u32
+nvbios_connTp(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+             struct nvbios_connT *info)
+{
+       u32 data = nvbios_connTe(bios, ver, hdr, cnt, len);
+       memset(info, 0x00, sizeof(*info));
+       switch (!!data * *ver) {
+       case 0x30:
+       case 0x40:
+               return data;
+       default:
+               break;
+       }
+       return 0x00000000;
+}
+
+u32
+nvbios_connEe(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len)
 {
        u8  hdr, cnt;
-       u16 data = dcb_conntab(bios, ver, &hdr, &cnt, len);
+       u32 data = nvbios_connTe(bios, ver, &hdr, &cnt, len);
        if (data && idx < cnt)
                return data + hdr + (idx * *len);
-       return 0x0000;
+       return 0x00000000;
+}
+
+u32
+nvbios_connEp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
+             struct nvbios_connE *info)
+{
+       u32 data = nvbios_connEe(bios, idx, ver, len);
+       memset(info, 0x00, sizeof(*info));
+       switch (!!data * *ver) {
+       case 0x30:
+       case 0x40:
+               info->type     =  nv_ro08(bios, data + 0x00);
+               info->location =  nv_ro08(bios, data + 0x01) & 0x0f;
+               info->hpd      = (nv_ro08(bios, data + 0x01) & 0x30) >> 4;
+               info->dp       = (nv_ro08(bios, data + 0x01) & 0xc0) >> 6;
+               if (*len < 4)
+                       return data;
+               info->hpd     |= (nv_ro08(bios, data + 0x02) & 0x03) << 2;
+               info->dp      |=  nv_ro08(bios, data + 0x02) & 0x0c;
+               info->di       = (nv_ro08(bios, data + 0x02) & 0xf0) >> 4;
+               info->hpd     |= (nv_ro08(bios, data + 0x03) & 0x07) << 4;
+               info->sr       = (nv_ro08(bios, data + 0x03) & 0x08) >> 3;
+               info->lcdid    = (nv_ro08(bios, data + 0x03) & 0x70) >> 4;
+               return data;
+       default:
+               break;
+       }
+       return 0x00000000;
 }
index acaeaf79e3f0fa797aa974831d6bbb367ebc78ff..626380f9e4c0192e877bef46b4a154b68c972b39 100644 (file)
@@ -98,15 +98,16 @@ static u8
 init_conn(struct nvbios_init *init)
 {
        struct nouveau_bios *bios = init->bios;
-       u8  ver, len;
-       u16 conn;
+       struct nvbios_connE connE;
+       u8  ver, hdr;
+       u32 conn;
 
        if (init_exec(init)) {
                if (init->outp) {
                        conn = init->outp->connector;
-                       conn = dcb_conn(bios, conn, &ver, &len);
+                       conn = nvbios_connEp(bios, conn, &ver, &hdr, &connE);
                        if (conn)
-                               return nv_ro08(bios, conn);
+                               return connE.type;
                }
 
                error("script needs connector type\n");
index 64f8b4702bf7272c3edf7950e16bf46b07d5457a..fcaabe8456e36bac0cf2664fc5305bcb5644c45b 100644 (file)
@@ -150,7 +150,7 @@ mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb)
         * common example is DP->eDP.
         */
        conn  = bios->data;
-       conn += dcb_conn(bios, (ctx.outp[0] & 0x0000f000) >> 12, &ver, &len);
+       conn += nvbios_connEe(bios, (ctx.outp[0] & 0x0000f000) >> 12, &ver, &len);
        type  = conn[0];
        switch (ctx.desc.conn_type) {
        case 0x01: /* LVDS */