drm/nouveau/dp: enable down-spread if vbios and sink support it
authorBen Skeggs <bskeggs@redhat.com>
Thu, 4 Aug 2011 04:31:28 +0000 (14:31 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 20 Sep 2011 06:10:35 +0000 (16:10 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_encoder.h

index 3777616cc157ecb502b0e208b63d5865a50a6f2d..89d5c161c8bd9249ade1f4ca8c37ac8852ec2814 100644 (file)
@@ -160,25 +160,6 @@ out:
        return ret;
 }
 
-static int
-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
-{
-       struct drm_device *dev = encoder->dev;
-       struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-       struct nouveau_i2c_chan *auxch;
-       int ret;
-
-       auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-       if (!auxch)
-               return -ENODEV;
-
-       ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
 static u32
 dp_link_bw_get(struct drm_device *dev, int or, int link)
 {
@@ -298,7 +279,7 @@ struct dp_state {
        int crtc;
        int or;
        int link;
-       int enh_frame;
+       u8 *dpcd;
        int link_nr;
        u32 link_bw;
        u8  stat[6];
@@ -343,7 +324,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
        /* configure lane count on the source */
        dp_ctrl = ((1 << dp->link_nr) - 1) << 16;
        sink[1] = dp->link_nr;
-       if (dp->enh_frame) {
+       if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) {
                dp_ctrl |= 0x00004000;
                sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
        }
@@ -505,7 +486,6 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
        const u32 *link_bw = bw_list;
        struct dp_state dp;
        u8 *bios, headerlen;
-       u16 script;
 
        auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
        if (!auxch)
@@ -520,7 +500,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
        dp.auxch = auxch->rd;
        dp.or = nv_encoder->or;
        dp.link = !(nv_encoder->dcb->sorconf.link & 1);
-       dp.enh_frame = nv_encoder->dp.enhanced_frame;
+       dp.dpcd = nv_encoder->dp.dpcd;
 
        /* some sinks toggle hotplug in response to some of the actions
         * we take during link training (DP_SET_POWER is one), we need
@@ -528,6 +508,15 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
         */
        pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
 
+       /* enable down-spreading, if possible */
+       if (headerlen >= 16) {
+               u16 script = ROM16(bios[14]);
+               if (nv_encoder->dp.dpcd[3] & 1)
+                       script = ROM16(bios[12]);
+
+               nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc);
+       }
+
        /* execute pre-train script from vbios */
        nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc);
 
@@ -575,17 +564,20 @@ nouveau_dp_detect(struct drm_encoder *encoder)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct drm_device *dev = encoder->dev;
-       uint8_t dpcd[4];
+       struct nouveau_i2c_chan *auxch;
+       u8 *dpcd = nv_encoder->dp.dpcd;
        int ret;
 
-       ret = auxch_rd(encoder, 0x0000, dpcd, 4);
+       auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+       if (!auxch)
+               return false;
+
+       ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
        if (ret)
                return false;
 
-       nv_encoder->dp.dpcd_version = dpcd[0];
        nv_encoder->dp.link_bw = 27000 * dpcd[1];
        nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
-       nv_encoder->dp.enhanced_frame = dpcd[2] & DP_ENHANCED_FRAME_CAP;
 
        NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
                     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
index deafe7b1f524146c7197d48a4530b2ef8135f1c6..e5d6e3faff3d26800e5a1cd9fdaa98ad6da2be0a 100644 (file)
@@ -49,10 +49,9 @@ struct nouveau_encoder {
 
        union {
                struct {
-                       int dpcd_version;
+                       u8  dpcd[8];
                        int link_nr;
                        int link_bw;
-                       bool enhanced_frame;
                        u32 datarate;
                } dp;
        };