drm/nv50: preserve an unknown SOR_MODECTRL value for DP encoders
authorBen Skeggs <bskeggs@redhat.com>
Mon, 29 Mar 2010 00:06:09 +0000 (10:06 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 9 Apr 2010 00:15:38 +0000 (10:15 +1000)
This value interacts with some registers we don't currently know how to
program properly ourselves.  The default of 5 that we were using matches
what the VBIOS on early DP cards do, but later ones use 6, which would
cause nouveau to program an incorrect mode on these chips.

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

index bc4a24029ed12a4ee5a59857975791a867699054..9f28b94e479bd1c7e7ba1f68bb59f29975559dbf 100644 (file)
@@ -47,6 +47,7 @@ struct nouveau_encoder {
 
        union {
                struct {
+                       int mc_unknown;
                        int dpcd_version;
                        int link_nr;
                        int link_bw;
index c2fff543b06f4a1c5269e4fa8e7cfb4b69f475d2..e31ba312c2ff5414894ff8f4f61954485bd7164c 100644 (file)
@@ -211,7 +211,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                        mode_ctl = 0x0200;
                break;
        case OUTPUT_DP:
-               mode_ctl |= 0x00050000;
+               mode_ctl |= (nv_encoder->dp.mc_unknown << 16);
                if (nv_encoder->dcb->sorconf.link & 1)
                        mode_ctl |= 0x00000800;
                else
@@ -274,6 +274,7 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
 int
 nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_encoder *nv_encoder = NULL;
        struct drm_encoder *encoder;
        bool dum;
@@ -319,5 +320,24 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
        encoder->possible_crtcs = entry->heads;
        encoder->possible_clones = 0;
 
+       if (nv_encoder->dcb->type == OUTPUT_DP) {
+               uint32_t mc, or = nv_encoder->or;
+
+               if (dev_priv->chipset < 0x90 ||
+                   dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
+                       mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
+               else
+                       mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
+
+               switch ((mc & 0x00000f00) >> 8) {
+               case 8:
+               case 9:
+                       nv_encoder->dp.mc_unknown = (mc & 0x000f0000) >> 16;
+                       break;
+               default:
+                       break;
+               }
+       }
+
        return 0;
 }