Browse Source

drm/nvd0/disp: calculate U script id in supervisor interrupt

This is like we do on nv50:nvd9 already.  There's been no problems seen
yet with using this *seemingly* scratch register to store the value, but
we won't be able to do this anymore once nv50's code is merged.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Ben Skeggs 12 years ago
parent
commit
4a230fa618

+ 1 - 0
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c

@@ -656,6 +656,7 @@ nv50_disp_base_ofuncs = {
 static struct nouveau_omthds
 nv50_disp_base_omthds[] = {
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
+	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
 	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
 	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
 	{},

+ 1 - 0
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h

@@ -35,6 +35,7 @@ struct nv50_disp_priv {
 		int (*dp_drvctl)(struct nv50_disp_priv *, int sor, int link,
 				 int lane, u16 type, u16 mask, u32 data,
 				 struct dcb_output *);
+		u32 lvdsconf;
 	} sor;
 };
 

+ 1 - 0
drivers/gpu/drm/nouveau/core/engine/disp/nv84.c

@@ -43,6 +43,7 @@ struct nouveau_omthds
 nv84_disp_base_omthds[] = {
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
 	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
+	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
 	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
 	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
 	{},

+ 1 - 0
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c

@@ -43,6 +43,7 @@ static struct nouveau_omthds
 nv94_disp_base_omthds[] = {
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
 	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
+	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
 	{ SOR_MTHD(NV94_DISP_SOR_DP_TRAIN)    , nv50_sor_mthd },
 	{ SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL)   , nv50_sor_mthd },
 	{ SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },

+ 1 - 0
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c

@@ -44,6 +44,7 @@ nva3_disp_base_omthds[] = {
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
 	{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD)     , nv50_sor_mthd },
 	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
+	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
 	{ SOR_MTHD(NV94_DISP_SOR_DP_TRAIN)    , nv50_sor_mthd },
 	{ SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL)   , nv50_sor_mthd },
 	{ SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },

+ 42 - 23
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c

@@ -634,38 +634,59 @@ exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id)
 	return false;
 }
 
-static bool
+static u32
 exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp,
-	    u32 ctrl, u32 conf, int id, u32 pclk)
+	    u32 ctrl, int id, u32 pclk)
 {
 	struct nouveau_bios *bios = nouveau_bios(priv);
 	struct nvbios_outp info1;
 	struct nvbios_ocfg info2;
 	struct dcb_output dcb;
 	u8  ver, hdr, cnt, len;
-	u16 data;
+	u16 data, conf;
 
 	data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info1);
+	if (data == 0x0000)
+		return false;
+
+	switch (dcb.type) {
+	case DCB_OUTPUT_TMDS:
+		conf = (ctrl & 0x00000f00) >> 8;
+		if (pclk >= 165000)
+			conf |= 0x0100;
+		break;
+	case DCB_OUTPUT_LVDS:
+		conf = priv->sor.lvdsconf;
+		break;
+	case DCB_OUTPUT_DP:
+		conf = (ctrl & 0x00000f00) >> 8;
+		break;
+	case DCB_OUTPUT_ANALOG:
+	default:
+		conf = 0x00ff;
+		break;
+	}
+
+	data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
 	if (data) {
-		data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
+		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
 		if (data) {
-			data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
-			if (data) {
-				struct nvbios_init init = {
-					.subdev = nv_subdev(priv),
-					.bios = bios,
-					.offset = data,
-					.outp = &dcb,
-					.crtc = head,
-					.execute = 1,
-				};
-
-				return nvbios_exec(&init) == 0;
-			}
+			struct nvbios_init init = {
+				.subdev = nv_subdev(priv),
+				.bios = bios,
+				.offset = data,
+				.outp = &dcb,
+				.crtc = head,
+				.execute = 1,
+			};
+
+			if (nvbios_exec(&init))
+				return 0x0000;
+			return conf;
 		}
 	}
 
-	return false;
+	return 0x0000;
 }
 
 static void
@@ -747,10 +768,9 @@ nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
 	nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000);
 
 	for (i = 0; mask && i < 8; i++) {
-		u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20));
-		u32 cfg = nv_rd32(priv, 0x660184 + (i * 0x20));
+		u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)), cfg;
 		if (mcp & (1 << head)) {
-			if (exec_clkcmp(priv, head, i, mcp, cfg, 0, pclk)) {
+			if ((cfg = exec_clkcmp(priv, head, i, mcp, 0, pclk))) {
 				u32 addr, mask, data = 0x00000000;
 				if (i < 4) {
 					addr = 0x612280 + ((i - 0) * 0x800);
@@ -790,9 +810,8 @@ nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
 
 	for (i = 0; mask && i < 8; i++) {
 		u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20));
-		u32 cfg = nv_rd32(priv, 0x660184 + (i * 0x20));
 		if (mcp & (1 << head))
-			exec_clkcmp(priv, head, i, mcp, cfg, 1, pclk);
+			exec_clkcmp(priv, head, i, mcp, 1, pclk);
 	}
 
 	nv_wr32(priv, 0x6101d4, 0x00000000);

+ 4 - 0
drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c

@@ -75,6 +75,10 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
 	case NV84_DISP_SOR_HDMI_PWR:
 		ret = priv->sor.hdmi(priv, head, or, data);
 		break;
+	case NV50_DISP_SOR_LVDS_SCRIPT:
+		priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
+		ret = 0;
+		break;
 	case NV94_DISP_SOR_DP_TRAIN:
 		ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
 		break;

+ 2 - 0
drivers/gpu/drm/nouveau/core/include/core/class.h

@@ -188,6 +188,8 @@ struct nve0_channel_ind_class {
 #define NV84_DISP_SOR_HDMI_PWR_STATE_ON                              0x40000000
 #define NV84_DISP_SOR_HDMI_PWR_MAX_AC_PACKET                         0x001f0000
 #define NV84_DISP_SOR_HDMI_PWR_REKEY                                 0x0000007f
+#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_PATTERN                               0x00000003
 #define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED                      0x00000000

+ 6 - 11
drivers/gpu/drm/nouveau/nvd0_display.c

@@ -1139,9 +1139,8 @@ nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
 		evo_data(push, syncs);
 		evo_data(push, magic);
-		evo_mthd(push, 0x0180 + (nv_encoder->or * 0x020), 2);
+		evo_mthd(push, 0x0180 + (nv_encoder->or * 0x020), 1);
 		evo_data(push, 1 << nv_crtc->index);
-		evo_data(push, 0x00ff);
 		evo_kick(push, nvd0_mast(encoder->dev));
 	}
 
@@ -1440,12 +1439,14 @@ static void
 nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
 		  struct drm_display_mode *mode)
 {
+	struct nvd0_disp *disp = nvd0_disp(encoder->dev);
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
 	struct nouveau_connector *nv_connector;
 	struct nvbios *bios = &drm->vbios;
+	int or = nv_encoder->or;
 	u32 mode_ctrl = (1 << nv_crtc->index);
 	u32 syncs, magic, *push;
 	u32 or_config;
@@ -1472,10 +1473,6 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
 			mode_ctrl |= 0x00000200;
 		}
 
-		or_config = (mode_ctrl & 0x00000f00) >> 8;
-		if (mode->clock >= 165000)
-			or_config |= 0x0100;
-
 		nvd0_hdmi_mode_set(encoder, mode);
 		break;
 	case DCB_OUTPUT_LVDS:
@@ -1504,8 +1501,9 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
 
 			if (nv_connector->base.display_info.bpc == 8)
 				or_config |= 0x0200;
-
 		}
+
+		nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + or, or_config);
 		break;
 	case DCB_OUTPUT_DP:
 		if (nv_connector->base.display_info.bpc == 6) {
@@ -1520,8 +1518,6 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
 			mode_ctrl |= 0x00000800;
 		else
 			mode_ctrl |= 0x00000900;
-
-		or_config = (mode_ctrl & 0x00000f00) >> 8;
 		break;
 	default:
 		BUG_ON(1);
@@ -1535,9 +1531,8 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
 		evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
 		evo_data(push, syncs);
 		evo_data(push, magic);
-		evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 2);
+		evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 1);
 		evo_data(push, mode_ctrl);
-		evo_data(push, or_config);
 		evo_kick(push, nvd0_mast(dev));
 	}