浏览代码

drm/nv50: preserve an unknown SOR_MODECTRL value for DP encoders

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>
Ben Skeggs 15 年之前
父节点
当前提交
6f335a7afa
共有 2 个文件被更改,包括 22 次插入1 次删除
  1. 1 0
      drivers/gpu/drm/nouveau/nouveau_encoder.h
  2. 21 1
      drivers/gpu/drm/nouveau/nv50_sor.c

+ 1 - 0
drivers/gpu/drm/nouveau/nouveau_encoder.h

@@ -47,6 +47,7 @@ struct nouveau_encoder {
 
 
 	union {
 	union {
 		struct {
 		struct {
+			int mc_unknown;
 			int dpcd_version;
 			int dpcd_version;
 			int link_nr;
 			int link_nr;
 			int link_bw;
 			int link_bw;

+ 21 - 1
drivers/gpu/drm/nouveau/nv50_sor.c

@@ -211,7 +211,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 			mode_ctl = 0x0200;
 			mode_ctl = 0x0200;
 		break;
 		break;
 	case OUTPUT_DP:
 	case OUTPUT_DP:
-		mode_ctl |= 0x00050000;
+		mode_ctl |= (nv_encoder->dp.mc_unknown << 16);
 		if (nv_encoder->dcb->sorconf.link & 1)
 		if (nv_encoder->dcb->sorconf.link & 1)
 			mode_ctl |= 0x00000800;
 			mode_ctl |= 0x00000800;
 		else
 		else
@@ -274,6 +274,7 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
 int
 int
 nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
 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 nouveau_encoder *nv_encoder = NULL;
 	struct drm_encoder *encoder;
 	struct drm_encoder *encoder;
 	bool dum;
 	bool dum;
@@ -319,5 +320,24 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
 	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;
 	return 0;
 }
 }