drm/nouveau/dp: remove last bits of VBIOS parsing from DRM code
authorBen Skeggs <bskeggs@redhat.com>
Thu, 15 Nov 2012 08:58:01 +0000 (18:58 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 28 Nov 2012 23:57:54 +0000 (09:57 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
12 files changed:
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
drivers/gpu/drm/nouveau/core/include/core/class.h
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bios.h
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_encoder.h

index 3fb5920b6bed037ed680be50da5fdb889f48e91d..a6bb931450f16c630dd663ada1186c687800f5b9 100644 (file)
@@ -26,6 +26,12 @@ struct nv50_disp_priv {
                int (*power)(struct nv50_disp_priv *, int sor, u32 data);
                int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
                int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
+               int (*dp_train_init)(struct nv50_disp_priv *, int sor, int link,
+                                    int head, u16 type, u16 mask, u32 data,
+                                    struct dcb_output *);
+               int (*dp_train_fini)(struct nv50_disp_priv *, int sor, int link,
+                                    int head, u16 type, u16 mask, u32 data,
+                                    struct dcb_output *);
                int (*dp_train)(struct nv50_disp_priv *, int sor, int link,
                                u16 type, u16 mask, u32 data,
                                struct dcb_output *);
@@ -57,6 +63,10 @@ int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
 int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
 int nv50_sor_power(struct nv50_disp_priv *, int, u32);
 
+int nv94_sor_dp_train_init(struct nv50_disp_priv *, int, int, int, u16, u16,
+                          u32, struct dcb_output *);
+int nv94_sor_dp_train_fini(struct nv50_disp_priv *, int, int, int, u16, u16,
+                          u32, struct dcb_output *);
 int nv94_sor_dp_train(struct nv50_disp_priv *, int, int, u16, u16, u32,
                      struct dcb_output *);
 int nv94_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
index b5adcc0bc0da82e6153204960ea45c4244624f7c..ba9dfd4669a2d721b68950ca61aadb87842b0777 100644 (file)
@@ -87,6 +87,8 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hdmi = nv84_hdmi_ctrl;
        priv->sor.dp_train = nv94_sor_dp_train;
+       priv->sor.dp_train_init = nv94_sor_dp_train_init;
+       priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
        priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
        priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
 
index 83ae695ac1df034cd9f5f2ac67e6c134092ba7fc..e9192ca389fa091d5276fcfec39f932542c0b809 100644 (file)
@@ -89,6 +89,8 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.hda_eld = nva3_hda_eld;
        priv->sor.hdmi = nva3_hdmi_ctrl;
        priv->sor.dp_train = nv94_sor_dp_train;
+       priv->sor.dp_train_init = nv94_sor_dp_train_init;
+       priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
        priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
        priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
 
index a618f2213a1478f76df9d9bfa91c6d6076b03e84..24bcbc6a88bb2ed29f5b5834a1ac2a004144b2bc 100644 (file)
@@ -951,6 +951,8 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.hda_eld = nvd0_hda_eld;
        priv->sor.hdmi = nvd0_hdmi_ctrl;
        priv->sor.dp_train = nvd0_sor_dp_train;
+       priv->sor.dp_train_init = nv94_sor_dp_train_init;
+       priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
        priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
        priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
 
index 9b83a70091f953f85416a793a3c7fdaaffadbd8a..259537c4587e32a3f9b7a7e4e7b47d9d5b852612 100644 (file)
@@ -72,6 +72,8 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.hda_eld = nvd0_hda_eld;
        priv->sor.hdmi = nvd0_hdmi_ctrl;
        priv->sor.dp_train = nvd0_sor_dp_train;
+       priv->sor.dp_train_init = nv94_sor_dp_train_init;
+       priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
        priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
        priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
 
index 6fd25730a5888a499d7ad7a5ff44d269f1d3097c..39b6b67732d0b064569b6c11ea729a67395d8ca2 100644 (file)
@@ -80,7 +80,19 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
                ret = 0;
                break;
        case NV94_DISP_SOR_DP_TRAIN:
-               ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
+               switch (data & NV94_DISP_SOR_DP_TRAIN_OP) {
+               case NV94_DISP_SOR_DP_TRAIN_OP_PATTERN:
+                       ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
+                       break;
+               case NV94_DISP_SOR_DP_TRAIN_OP_INIT:
+                       ret = priv->sor.dp_train_init(priv, or, link, head, type, mask, data, &outp);
+                       break;
+               case NV94_DISP_SOR_DP_TRAIN_OP_FINI:
+                       ret = priv->sor.dp_train_fini(priv, or, link, head, type, mask, data, &outp);
+                       break;
+               default:
+                       break;
+               }
                break;
        case NV94_DISP_SOR_DP_LNKCTL:
                ret = priv->sor.dp_lnkctl(priv, or, link, head, type, mask, data, &outp);
index 49bcc76261e6bfc2030d5867e3444aa964058af0..f6edd009762ee3127e78d4ba36fdd15b3c4cc4f2 100644 (file)
@@ -42,6 +42,64 @@ nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
        return nv94[lane];
 }
 
+int
+nv94_sor_dp_train_init(struct nv50_disp_priv *priv, int or, int link, int head,
+                      u16 type, u16 mask, u32 data, struct dcb_output *dcbo)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_dpout info;
+       u8  ver, hdr, cnt, len;
+       u16 outp;
+
+       outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
+       if (outp) {
+               struct nvbios_init init = {
+                       .subdev = nv_subdev(priv),
+                       .bios = bios,
+                       .outp = dcbo,
+                       .crtc = head,
+                       .execute = 1,
+               };
+
+               if (data & NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON)
+                       init.offset = info.script[2];
+               else
+                       init.offset = info.script[3];
+               nvbios_exec(&init);
+
+               init.offset = info.script[0];
+               nvbios_exec(&init);
+       }
+
+       return 0;
+}
+
+int
+nv94_sor_dp_train_fini(struct nv50_disp_priv *priv, int or, int link, int head,
+                      u16 type, u16 mask, u32 data, struct dcb_output *dcbo)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_dpout info;
+       u8  ver, hdr, cnt, len;
+       u16 outp;
+
+       outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
+       if (outp) {
+               struct nvbios_init init = {
+                       .subdev = nv_subdev(priv),
+                       .bios = bios,
+                       .offset = info.script[1],
+                       .outp = dcbo,
+                       .crtc = head,
+                       .execute = 1,
+               };
+
+               nvbios_exec(&init);
+       }
+
+       return 0;
+}
+
 int
 nv94_sor_dp_train(struct nv50_disp_priv *priv, int or, int link,
                  u16 type, u16 mask, u32 data, struct dcb_output *info)
index dd060234b0b0d42a51e93ccb7e4ba1e0c5693652..47c4b3a5bd3a282e4c4f10232ed9de4ecef3a594 100644 (file)
@@ -191,6 +191,13 @@ struct nve0_channel_ind_class {
 #define NV50_DISP_SOR_LVDS_SCRIPT                                    0x00013000
 #define NV50_DISP_SOR_LVDS_SCRIPT_ID                                 0x0000ffff
 #define NV94_DISP_SOR_DP_TRAIN                                       0x00016000
+#define NV94_DISP_SOR_DP_TRAIN_OP                                    0xf0000000
+#define NV94_DISP_SOR_DP_TRAIN_OP_PATTERN                            0x00000000
+#define NV94_DISP_SOR_DP_TRAIN_OP_INIT                               0x10000000
+#define NV94_DISP_SOR_DP_TRAIN_OP_FINI                               0x20000000
+#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD                           0x00000001
+#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF                       0x00000000
+#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON                        0x00000001
 #define NV94_DISP_SOR_DP_TRAIN_PATTERN                               0x00000003
 #define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED                      0x00000000
 #define NV94_DISP_SOR_DP_LNKCTL                                      0x00016040
index 395d2b9372c8af0635b9d172fe9b724033f9e94e..865eddfa30a73faee6f985b0d7176ceefa7e48f9 100644 (file)
@@ -624,34 +624,6 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
        return 0;
 }
 
-/* BIT 'U'/'d' table encoder subtables have hashes matching them to
- * a particular set of encoders.
- *
- * This function returns true if a particular DCB entry matches.
- */
-bool
-bios_encoder_match(struct dcb_output *dcb, u32 hash)
-{
-       if ((hash & 0x000000f0) != (dcb->location << 4))
-               return false;
-       if ((hash & 0x0000000f) != dcb->type)
-               return false;
-       if (!(hash & (dcb->or << 16)))
-               return false;
-
-       switch (dcb->type) {
-       case DCB_OUTPUT_TMDS:
-       case DCB_OUTPUT_LVDS:
-       case DCB_OUTPUT_DP:
-               if (hash & 0x00c00000) {
-                       if (!(hash & (dcb->sorconf.link << 22)))
-                               return false;
-               }
-       default:
-               return true;
-       }
-}
-
 int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk)
 {
        /*
index 9e364b68e6037807635549e5f22460706e618e86..f68c54ca422ff7e541283de8e2aaa53d873258f0 100644 (file)
@@ -187,6 +187,5 @@ int run_tmds_table(struct drm_device *, struct dcb_output *,
                          int head, int pxclk);
 int call_lvds_script(struct drm_device *, struct dcb_output *, int head,
                            enum LVDS_script, int pxclk);
-bool bios_encoder_match(struct dcb_output *, u32 hash);
 
 #endif
index e3f6550ae7728b9ff16be0391f0d3604f2789010..59838651ee8f9be4536ac0ff29242951d40e3b64 100644 (file)
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
 
-u8 *
-nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry)
-{
-       struct nouveau_drm *drm = nouveau_drm(dev);
-       struct bit_entry d;
-       u8 *table;
-       int i;
-
-       if (bit_table(dev, 'd', &d)) {
-               NV_ERROR(drm, "BIT 'd' table not found\n");
-               return NULL;
-       }
-
-       if (d.version != 1) {
-               NV_ERROR(drm, "BIT 'd' table version %d unknown\n", d.version);
-               return NULL;
-       }
-
-       table = ROMPTR(dev, d.data[0]);
-       if (!table) {
-               NV_ERROR(drm, "displayport table pointer invalid\n");
-               return NULL;
-       }
-
-       switch (table[0]) {
-       case 0x20:
-       case 0x21:
-       case 0x30:
-       case 0x40:
-               break;
-       default:
-               NV_ERROR(drm, "displayport table 0x%02x unknown\n", table[0]);
-               return NULL;
-       }
-
-       for (i = 0; i < table[3]; i++) {
-               *entry = ROMPTR(dev, table[table[1] + (i * table[2])]);
-               if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0])))
-                       return table;
-       }
-
-       NV_ERROR(drm, "displayport encoder table not found\n");
-       return NULL;
-}
-
 /******************************************************************************
  * link training
  *****************************************************************************/
@@ -250,54 +205,27 @@ dp_link_train_eq(struct drm_device *dev, struct dp_state *dp)
 }
 
 static void
-dp_set_downspread(struct drm_device *dev, struct dp_state *dp, bool enable)
+dp_link_train_init(struct drm_device *dev, struct dp_state *dp, bool spread)
 {
-       u16 script = 0x0000;
-       u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry);
-       if (table) {
-               if (table[0] >= 0x20 && table[0] <= 0x30) {
-                       if (enable) script = ROM16(entry[12]);
-                       else        script = ROM16(entry[14]);
-               } else
-               if (table[0] == 0x40) {
-                       if (enable) script = ROM16(entry[11]);
-                       else        script = ROM16(entry[13]);
-               }
-       }
-
-       nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
-}
-
-static void
-dp_link_train_init(struct drm_device *dev, struct dp_state *dp)
-{
-       u16 script = 0x0000;
-       u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry);
-       if (table) {
-               if (table[0] >= 0x20 && table[0] <= 0x30)
-                       script = ROM16(entry[6]);
-               else
-               if (table[0] == 0x40)
-                       script = ROM16(entry[5]);
-       }
+       struct dcb_output *dcb = dp->dcb;
+       const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
+       const u32 moff = (dp->crtc << 3) | (link << 2) | or;
 
-       nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
+       nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, (spread ?
+                         NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON :
+                         NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF) |
+                         NV94_DISP_SOR_DP_TRAIN_OP_INIT);
 }
 
 static void
 dp_link_train_fini(struct drm_device *dev, struct dp_state *dp)
 {
-       u16 script = 0x0000;
-       u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry);
-       if (table) {
-               if (table[0] >= 0x20 && table[0] <= 0x30)
-                       script = ROM16(entry[8]);
-               else
-               if (table[0] == 0x40)
-                       script = ROM16(entry[7]);
-       }
+       struct dcb_output *dcb = dp->dcb;
+       const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
+       const u32 moff = (dp->crtc << 3) | (link << 2) | or;
 
-       nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
+       nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff,
+                         NV94_DISP_SOR_DP_TRAIN_OP_FINI);
 }
 
 static bool
@@ -334,11 +262,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
         */
        gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false);
 
-       /* enable down-spreading, if possible */
-       dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1);
-
-       /* execute pre-train script from vbios */
-       dp_link_train_init(dev, &dp);
+       /* enable down-spreading and execute pre-train script from vbios */
+       dp_link_train_init(dev, &dp, nv_encoder->dp.dpcd[3] & 1);
 
        /* start off at highest link rate supported by encoder and display */
        while (*link_bw > nv_encoder->dp.link_bw)
index 06c1bb3a2f2afab759c0d17fe2e2179d666f8be0..6f642df67009436635b672e75d14841d330ad7c1 100644 (file)
@@ -94,7 +94,6 @@ get_slave_funcs(struct drm_encoder *enc)
 bool nouveau_dp_detect(struct drm_encoder *);
 void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate,
                     struct nouveau_object *);
-u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_output *, u8 **);
 
 struct nouveau_connector *
 nouveau_encoder_connector_get(struct nouveau_encoder *encoder);