[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-nouveau: Changes to 'ubuntu-jaunty'



 debian/changelog      |   47 +
 debian/control        |    2 
 src/Makefile.am       |    2 
 src/drmmode_display.c |   13 
 src/nouveau_bios.h    |    4 
 src/nouveau_calc.c    |  614 ++++++++++++++++++++++++
 src/nouveau_hw.c      |  971 +++++++++++++++++++++++++++++++++++++++
 src/nouveau_hw.h      |  335 +++++++++++++
 src/nouveau_local.h   |   12 
 src/nouveau_xv.c      |    9 
 src/nv50_connector.c  |   12 
 src/nv50_crtc.c       |    2 
 src/nv50_randr.c      |    4 
 src/nv50reg.h         |    4 
 src/nv_bios.c         | 1239 +++++++++++++++++---------------------------------
 src/nv_crtc.c         |  546 ++--------------------
 src/nv_cursor.c       |    4 
 src/nv_driver.c       |    7 
 src/nv_hw.c           |  927 -------------------------------------
 src/nv_include.h      |    1 
 src/nv_output.c       |  216 +++++---
 src/nv_proto.h        |   56 --
 src/nv_setup.c        |   31 -
 src/nv_type.h         |   26 -
 src/nvreg.h           |    7 
 25 files changed, 2671 insertions(+), 2420 deletions(-)

New commits:
commit d748435ea4ea77b9e86e671041fc1da981249fa5
Author: Christopher James Halse Rogers <chris@CowboyLaputopu.(none)>
Date:   Sat Apr 4 14:40:00 2009 +1100

    New upstream snapshot.
    Rebuild against fixed libdrm-dev to pick up libdrm-nouveau1 dependency

diff --git a/debian/changelog b/debian/changelog
index 202147f..759a079 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,50 @@
+xserver-xorg-video-nouveau (1:0.0.10~git+20090404+11be9a9-0ubuntu1) jaunty; urgency=low
+
+  * New upstream snapshot.  Standing FFe is (LP: #346621).
+    - 11be9a9... nv50: fix i2c port addresses
+    - e2aa037... randr12: fall back to standard timings when finding
+      native mode (rh#492819)  
+    - 6965663... randr12: fix hw cursor for fully transparent pixels
+    - d12f70c... randr12: pre-nv17 digital fixes
+    - ea567db... randr12: fix restore for cards where CR21 is not left
+      unlocked at POST 
+    - bd263d8... randr12: make nv11 dvi work for both crtcs
+    - 52c287d... Every card since nv5 can do panels
+    - 3d371a7... randr12: enable tmds reg access on pre-nv17
+    - 1bb85c8... randr12: reorder ramdac reg access
+    - 4465fdd... randr12: remove nv30 special case
+    - 72eced5... randr12: fix/improve a load of version/feature tests
+    - 37c6916... bios: fix chips with pll limits table version 0
+    - 76c5a05... bios: xf86DrvMsg->NV_ERROR
+    - b1b9bcb... bios: support for pll limits table v3.0
+    - 8c85b4b... kms: CONNECTORn -> CONNECTOR-n
+    - 4e1c323... Restore call to NVDRIGetVersion, to ensure the dri
+      module is loaded 
+    - c973f75... Abstract logging in nv_bios.c
+    - b17bebd... nForce DIMM check is now in DRM
+    - 9c991d3... randr12: FP_TG_CONTROL 2: dpms improvements
+    - 5fb2888... randr12: FP_TG_CONTROL 1: turn off digital path when
+      using VGA encoder 
+    - 8023dc3... Split DCB 1.5 parsing from 2.0+, get closer to 80 cols
+    - ea027b3... The dcb prior to v1.5 is pretty hopeless, just add a crt.
+    - 921fbcc... randr12: avoid nv11 chip lockup when saving palette regs
+    - 9d46930... xv: oops
+    - 9213c39... xv: post damage after we draw (rh#492239)
+    - d68a052... kms: small cleanup
+    - c9cb6a6... rh#492511 has a CRTC_OWNER of 0x7 for some reason
+    - 95bff61... randr12: fix LVDS legitimately disconnected case
+    - f86e395... randr12: permit vga outputs to be force enabled in xorg.conf
+    - 8427b39... randr12: move a load of hw mode programming into nouveau_hw.c
+    - 163bdce... Turn the smaller mmio wrappers into static inline
+    - 21ee927... Put arbitration and mnp calcs in separate file
+    - 83dc890... nv50: use E-EDID when available + apply edid quirks  
+  * debian/control:
+    - Bump dependency on libdrm-dev to ensure rebuild with fixed
+      libdrm-nouveau1.symbols file.  Fixes missing Depends: on
+      libdrm-nouveau1
+
+ -- Christopher James Halse Rogers <raof@ubuntu.com>  Sat, 04 Apr 2009 14:35:12 +1100
+
 xserver-xorg-video-nouveau (1:0.0.10~git+20090327+f1907dc-0ubuntu1) jaunty; urgency=low
 
   * New upstream snapshot.  Standing FFe is (LP: #346621).
diff --git a/debian/control b/debian/control
index 8715ab1..fac9352 100644
--- a/debian/control
+++ b/debian/control
@@ -4,7 +4,7 @@ Priority: optional
 Maintainer: Ubuntu MOTU Developers <ubuntu-motu@lists.ubuntu.com>
 XSBC-Original-Maintainer: Debian X Strike Force <debian-x@lists.debian.org>
 Uploaders: Chris Lamb <lamby@debian.org>, Matthew Johnson <mjj29@debian.org>
-Build-Depends: debhelper (>= 7), pkg-config, xserver-xorg-dev (>= 2:1.2.99.902), x11proto-video-dev, x11proto-core-dev, x11proto-fonts-dev, x11proto-randr-dev (>= 1.2), x11proto-render-dev, x11proto-xext-dev, libdrm-dev (>= 2.4.4+git+20090105+a8c5480), x11proto-xf86dri-dev, x11proto-gl-dev, mesa-common-dev, automake, libtool, xutils-dev, xserver-xorg-dev, quilt
+Build-Depends: debhelper (>= 7), pkg-config, xserver-xorg-dev (>= 2:1.2.99.902), x11proto-video-dev, x11proto-core-dev, x11proto-fonts-dev, x11proto-randr-dev (>= 1.2), x11proto-render-dev, x11proto-xext-dev, libdrm-dev (>= 2.4.5-0ubuntu4), x11proto-xf86dri-dev, x11proto-gl-dev, mesa-common-dev, automake, libtool, xutils-dev, xserver-xorg-dev, quilt
 Standards-Version: 3.8.0
 Homepage: http://nouveau.freedesktop.org/wiki/
 Vcs-Git: git://git.debian.org/git/pkg-xorg/driver/xserver-xorg-video-nouveau

commit 11be9a982073d66a68cd3db2bfc611eb58d3ea81
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Fri Apr 3 12:22:04 2009 +1000

    nv50: fix i2c port addresses

diff --git a/src/nv50reg.h b/src/nv50reg.h
index b3125ce..4e21220 100644
--- a/src/nv50reg.h
+++ b/src/nv50reg.h
@@ -50,8 +50,8 @@
 #define NV50_PCONNECTOR_I2C_PORT_1			0x0000e150
 #define NV50_PCONNECTOR_I2C_PORT_2			0x0000e168
 #define NV50_PCONNECTOR_I2C_PORT_3			0x0000e180
-#define NV50_PCONNECTOR_I2C_PORT_4			0x0000e254
-#define NV50_PCONNECTOR_I2C_PORT_5			0x0000e274
+#define NV50_PCONNECTOR_I2C_PORT_4			0x0000e240
+#define NV50_PCONNECTOR_I2C_PORT_5			0x0000e258
 
 /* 0x00610024 is the state register to read, all it's bits also exist in 0x0061002C in the form of interrupt switches. */
 #define NV50_DISPLAY_SUPERVISOR		0x00610024

commit e2aa03794420324ae5a682bbc415a79a4d830f7e
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Fri Apr 3 00:57:19 2009 +0100

    randr12: fall back to standard timings when finding native mode (rh#492819)

diff --git a/src/nv_output.c b/src/nv_output.c
index 592b06a..efc2bc4 100644
--- a/src/nv_output.c
+++ b/src/nv_output.c
@@ -249,7 +249,6 @@ get_native_mode_from_edid(xf86OutputPtr output, DisplayModePtr edid_modes)
 	DisplayModePtr mode;
 
 	for (i = 0; i < DET_TIMINGS; i++) {
-		/* We only look at detailed timings atm */
 		if (nv_connector->edid->det_mon[i].type != DT)
 			continue;
 		/* Selecting only based on width ok? */
@@ -258,9 +257,15 @@ get_native_mode_from_edid(xf86OutputPtr output, DisplayModePtr edid_modes)
 			max_v_active = nv_connector->edid->det_mon[i].section.d_timings.v_active;
 		}
 	}
-	if (!(max_h_active && max_v_active)) {
+	if (!max_h_active || !max_v_active) /* what kind of a joke EDID is this? */
+		for (i = 0; i < STD_TIMINGS; i++)
+			if (nv_connector->edid->timings2[i].hsize > max_h_active) {
+				max_h_active = nv_connector->edid->timings2[i].hsize;
+				max_v_active = nv_connector->edid->timings2[i].vsize;
+			}
+	if (!max_h_active || !max_v_active) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "No EDID detailed timings available for finding native mode\n");
+			   "EDID too broken for finding native mode\n");
 		return NULL;
 	}
 

commit 6965663ddcc8dd3330842d3c4c4eb4cbf4e4fc39
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Wed Apr 1 05:38:29 2009 +0100

    randr12: fix hw cursor for fully transparent pixels
    
    ARGB8 pixels of 0x00000000 were getting bumped to 0x01000000, which was
    _just_ visible as a box around the cursor

diff --git a/src/nv_cursor.c b/src/nv_cursor.c
index 2863f2f..f807fee 100644
--- a/src/nv_cursor.c
+++ b/src/nv_cursor.c
@@ -160,8 +160,8 @@ void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
 		 * get back to NPM images, due to limits of integer precision)
 		 */
 		alpha = (*src >> 24);
-		if (alpha == 0xff)
-			/* alpha == max(r,g,b) fortunately works ok for 0xff */
+		if (!alpha || alpha == 0xff)
+			/* alpha == max(r,g,b) works ok for 0x0 and 0xff */
 			tmp = *src;
 		else
 			tmp = ((alpha + 1) << 24) | (*src & 0xffffff);

commit d12f70cedb0ba598234bbfc26dd6beed23e3dfe7
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Sun Mar 29 00:51:05 2009 +0000

    randr12: pre-nv17 digital fixes
    
    1) set panel regs better (don't do min_front_porch adjustment)
    2) scaler programming - nv11 and nv20 don't need / 2 for aspect scaling

diff --git a/src/nv_crtc.c b/src/nv_crtc.c
index 8fb22aa..0dc3e32 100644
--- a/src/nv_crtc.c
+++ b/src/nv_crtc.c
@@ -623,7 +623,9 @@ nv_crtc_mode_set_fp_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr a
 
 	regp->fp_horiz_regs[FP_DISPLAY_END] = adjusted_mode->HDisplay - 1;
 	regp->fp_horiz_regs[FP_TOTAL] = adjusted_mode->HTotal - 1;
-	if ((adjusted_mode->HSyncStart - adjusted_mode->HDisplay) >= pNv->vbios->digital_min_front_porch)
+	if (!pNv->gf4_disp_arch ||
+	    (adjusted_mode->HSyncStart - adjusted_mode->HDisplay) >=
+					pNv->vbios->digital_min_front_porch)
 		regp->fp_horiz_regs[FP_CRTC] = adjusted_mode->HDisplay;
 	else
 		regp->fp_horiz_regs[FP_CRTC] = adjusted_mode->HSyncStart - pNv->vbios->digital_min_front_porch - 1;
@@ -683,6 +685,7 @@ nv_crtc_mode_set_fp_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr a
 	 * get treated the same as SCALE_FULLSCREEN */
 	if (nv_encoder->scaling_mode == SCALE_ASPECT && mode_ratio != panel_ratio) {
 		uint32_t diff, scale;
+		bool divide_by_2 = pNv->gf4_disp_arch;
 
 		if (mode_ratio < panel_ratio) {
 			/* vertical needs to expand to glass size (automatic)
@@ -691,7 +694,7 @@ nv_crtc_mode_set_fp_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr a
 
 			scale = (1 << 12) * mode->VDisplay / adjusted_mode->VDisplay;
 			regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE |
-					   XLATE(scale, 1, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE);
+					   XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE);
 
 			/* restrict area of screen used, horizontally */
 			diff = adjusted_mode->HDisplay -
@@ -707,7 +710,7 @@ nv_crtc_mode_set_fp_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr a
 
 			scale = (1 << 12) * mode->HDisplay / adjusted_mode->HDisplay;
 			regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE |
-					   XLATE(scale, 1, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE);
+					   XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE);
 
 			/* restrict area of screen used, vertically */
 			diff = adjusted_mode->VDisplay -

commit ea567dbc7bc9c8d2ee5d7d9e0dcd33b03c638edb
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Sat Mar 28 01:58:09 2009 +0000

    randr12: fix restore for cards where CR21 is not left unlocked at POST
    
    More nv11 inspired fun.  If CR21 is left without a 0xfa mask after boot,
    we'd restore the old CR21 value and the subsequent restoration of VGA
    CRTC values wouldn't get through.
    
    RE'd doc of CR21 behaviour included

diff --git a/src/nouveau_hw.c b/src/nouveau_hw.c
index 6f7868f..11bae7c 100644
--- a/src/nouveau_hw.c
+++ b/src/nouveau_hw.c
@@ -845,7 +845,6 @@ static void nv_load_state_ext(NVPtr pNv, int head, struct nouveau_mode_state *st
 		nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(1), pNv->VRAMPhysicalSize - 1);
 		nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, 0);
 
-		wr_cio_state(pNv, head, regp, NV_CIO_CRE_21);
 		NVWriteCRTC(pNv, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg);
 		NVWriteCRTC(pNv, head, NV_PCRTC_830, regp->crtc_830);
 		NVWriteCRTC(pNv, head, NV_PCRTC_834, regp->crtc_834);
diff --git a/src/nouveau_hw.h b/src/nouveau_hw.h
index 93872d8..b1e273f 100644
--- a/src/nouveau_hw.h
+++ b/src/nouveau_hw.h
@@ -248,6 +248,27 @@ static inline bool nv_lock_vga_crtc_base(NVPtr pNv, int head, bool lock)
 	return waslocked;
 }
 
+static inline void nv_lock_vga_crtc_shadow(NVPtr pNv, int head, int lock)
+{
+	/* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs
+         * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB
+         * bit6: seems to have some effect on CR09 (double scan, VBS_9)
+         * bit5: unlocks HDE
+         * bit4: unlocks VDE
+         * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR
+         * bit2: same as bit 1 of 0x60?804
+         * bit0: same as bit 0 of 0x60?804
+         */
+
+	uint8_t cr21 = lock;
+
+	if (lock < 0)
+		/* 0xfa is generic "unlock all" mask */
+		cr21 = NVReadVgaCrtc(pNv, head, NV_CIO_CRE_21) | 0xfa;
+
+	NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_21, cr21);
+}
+
 /* renders the extended crtc regs (cr19+) on all crtcs impervious:
  * immutable and unreadable
  */
diff --git a/src/nv_crtc.c b/src/nv_crtc.c
index ba50730..8fb22aa 100644
--- a/src/nv_crtc.c
+++ b/src/nv_crtc.c
@@ -469,10 +469,6 @@ nv_crtc_mode_set_regs(xf86CrtcPtr crtc, DisplayModePtr mode)
 
 	/* Registers not directly related to the (s)vga mode */
 
-	/* bit2 = 0 -> fine pitched crtc granularity */
-	/* The rest disables double buffering on CRTC access */
-	regp->CRTC[NV_CIO_CRE_21] = 0xfa;
-
 	/* the blob sometimes sets |= 0x10 (which is the same as setting |=
 	 * 1 << 30 on 0x60.830), for no apparent reason */
 	regp->CRTC[NV_CIO_CRE_59] = 0x0;
@@ -810,11 +806,14 @@ static void nv_crtc_restore(xf86CrtcPtr crtc)
 {
 	struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
 	NVPtr pNv = NVPTR(crtc->scrn);
+	int head = nv_crtc->head;
+	uint8_t saved_cr21 = pNv->SavedReg.crtc_reg[head].CRTC[NV_CIO_CRE_21];
 
 	if (pNv->twoHeads)
-		NVSetOwner(pNv, nv_crtc->head);
+		NVSetOwner(pNv, head);
 
-	nouveau_hw_load_state(crtc->scrn, nv_crtc->head, &pNv->SavedReg);
+	nouveau_hw_load_state(crtc->scrn, head, &pNv->SavedReg);
+	nv_lock_vga_crtc_shadow(pNv, head, saved_cr21);
 
 	nv_crtc->last_dpms = NV_DPMS_CLEARED;
 }
@@ -839,6 +838,7 @@ static void nv_crtc_prepare(xf86CrtcPtr crtc)
 	NVBlankScreen(pNv, nv_crtc->head, true);
 
 	/* Some more preperation. */
+	nv_lock_vga_crtc_shadow(pNv, nv_crtc->head, -1);
 	NVWriteCRTC(pNv, nv_crtc->head, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA);
 	if (pNv->Architecture == NV_ARCH_40) {
 		uint32_t reg900 = NVReadRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_900);
diff --git a/src/nvreg.h b/src/nvreg.h
index 891c7e5..ff5662e 100644
--- a/src/nvreg.h
+++ b/src/nvreg.h
@@ -247,7 +247,7 @@
 #		define NV_CIO_SR_UNLOCK_RW_VALUE	0x57
 #		define NV_CIO_SR_LOCK_VALUE		0x99
 #	define NV_CIO_CRE_FFLWM__INDEX		0x20	/* fifo low water mark */
-#	define NV_CIO_CRE_21			0x21	/* referred to by some .scp as `shadow lock' */
+#	define NV_CIO_CRE_21			0x21	/* vga shadow crtc lock */
 #	define NV_CIO_CRE_LSR_INDEX		0x25	/* ? */
 #		define NV_CIO_CRE_LSR_VDT_10		0:0
 #		define NV_CIO_CRE_LSR_VDE_10		1:1

commit bd263d83139fcc93b967c71c99fd5e63e1ba6315
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Fri Mar 27 18:27:18 2009 +0000

    randr12: make nv11 dvi work for both crtcs

diff --git a/src/nv_output.c b/src/nv_output.c
index 7b3b2dd..592b06a 100644
--- a/src/nv_output.c
+++ b/src/nv_output.c
@@ -691,8 +691,15 @@ nv_output_prepare(xf86OutputPtr output)
 			*lcdi = 0x3;
 			if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP)
 				*lcdi |= head ? 0x0 : 0x8;
-			else
+			else if (pNv->gf4_disp_arch)
 				*lcdi |= (nv_encoder->dcb->or << 4) & 0x30;
+			else if (pNv->twoHeads)
+				/* the guess here is that 0x10 gets set when
+				 * the output is not on its "natural" crtc
+				 * (lvds naturally on head b, tmds head a)
+				 */
+				*lcdi |= (head + 1 != nv_encoder->dcb->or) ?
+					 0x10 : 0x00;
 		}
 	}
 }
@@ -864,18 +871,22 @@ tmds_encoder_dpms(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86Crt
 
 	dpms_update_fp_control(pScrn, nv_encoder, crtc, mode);
 
-	if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP) {
-		struct nouveau_crtc *nv_crtc;
-		int i;
-
+	if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && pNv->twoHeads) {
 		if (mode == DPMSModeOn) {
-			nv_crtc = to_nouveau_crtc(crtc);
-			NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_LCD__INDEX,
-				       pNv->ModeReg.crtc_reg[nv_crtc->head].CRTC[NV_CIO_CRE_LCD__INDEX]);
-		} else
-			for (i = 0; i <= pNv->twoHeads; i++)
+			int head = to_nouveau_crtc(crtc)->head;
+
+			NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_LCD__INDEX,
+				       pNv->ModeReg.crtc_reg[head].CRTC[NV_CIO_CRE_LCD__INDEX]);
+		} else {
+			int i;
+			uint8_t mask = pNv->gf4_disp_arch ?
+				       ~((nv_encoder->dcb->or << 4) & 0x30) :
+				       ~0x10;
+
+			for (i = 0; i < 2; i++)
 				NVWriteVgaCrtc(pNv, i, NV_CIO_CRE_LCD__INDEX,
-					       NVReadVgaCrtc(pNv, i, NV_CIO_CRE_LCD__INDEX) & ~((nv_encoder->dcb->or << 4) & 0x30));
+					       NVReadVgaCrtc(pNv, i, NV_CIO_CRE_LCD__INDEX) & mask);
+		}
 	}
 }
 

commit 52c287dc64a97a750eb953ac5f725d794cbf0c64
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Fri Mar 27 00:23:04 2009 +0000

    Every card since nv5 can do panels
    
    We'll only try to do ones using scripts atm though
    
    Note that as we don't have a load detect function for pre-nv17 you'll
    likely get a 1024x768 mode set up on VGA-0 even if only the DVI output
    is plugged.  Unclear if this is a bug or feature :)

diff --git a/src/nv_bios.c b/src/nv_bios.c
index dda246d..7da48d2 100644
--- a/src/nv_bios.c
+++ b/src/nv_bios.c
@@ -36,6 +36,7 @@
 #define NV_CIO_CRE_44_HEADB 0x3
 #define FEATURE_MOBILE 0x10	/* also FEATURE_QUADRO for BMP */
 #define LEGACY_I2C_CRT 0x80
+#define LEGACY_I2C_PANEL 0x81
 
 #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip, fmt, ##arg)
 #define LOG_OLD_VALUE(x) //x
@@ -3039,10 +3040,13 @@ int run_tmds_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, int px
 
 	NVPtr pNv = NVPTR(pScrn);
 	struct nvbios *bios = &pNv->VBIOS;
+	int cv = bios->pub.chip_version;
 	uint16_t clktable = 0, scriptptr;
 	uint32_t sel_clk_binding, sel_clk;
 
-	if (dcbent->location != DCB_LOC_ON_CHIP)
+	/* pre-nv17 off-chip tmds uses scripts, post nv17 doesn't */
+	if (cv >= 0x17 && cv != 0x1a && cv != 0x20 &&
+	    dcbent->location != DCB_LOC_ON_CHIP)
 		return 0;
 
 	switch (ffs(dcbent->or)) {
@@ -4025,6 +4029,32 @@ static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads)
 	/* "or" mostly unused in early gen crt modesetting, 0 is fine */
 }
 
+static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
+{
+	struct dcb_entry *entry = new_dcb_entry(dcb);
+
+	entry->type = 2;
+	entry->i2c_index = LEGACY_I2C_PANEL;
+	entry->heads = twoHeads ? 3 : 1;
+	entry->location = !DCB_LOC_ON_CHIP;	/* ie OFF CHIP */
+	entry->or = 1;	/* naturally on head A; see setting of CRE_LCD__INDEX */
+	entry->duallink_possible = false; /* SiI164 and co. are single link */
+
+#if 0
+	/* for dvi-a either crtc probably works, but my card appears to only
+	 * support dvi-d.  "nvidia" still attempts to program it for dvi-a,
+	 * doing the full fp output setup (program 0x6808.. fp dimension regs,
+	 * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880);
+	 * the monitor picks up the mode res ok and lights up, but no pixel
+	 * data appears, so the board manufacturer probably connected up the
+	 * sync lines, but missed the video traces / components
+	 *
+	 * with this introduction, dvi-a left as an exercise for the reader.
+	 */
+	fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads);
+#endif
+}
+
 static bool
 parse_dcb20_entry(ScrnInfoPtr pScrn, struct bios_parsed_dcb *bdcb,
 		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
@@ -4219,7 +4249,7 @@ void merge_like_dcb_entries(ScrnInfoPtr pScrn, struct parsed_dcb *dcb)
 	dcb->entries = newentries;
 }
 
-static int parse_dcb_table(ScrnInfoPtr pScrn, struct nvbios *bios)
+static int parse_dcb_table(ScrnInfoPtr pScrn, struct nvbios *bios, bool twoHeads)
 {
 	struct bios_parsed_dcb *bdcb = &bios->bdcb;
 	struct parsed_dcb *dcb;
@@ -4299,8 +4329,11 @@ static int parse_dcb_table(ScrnInfoPtr pScrn, struct nvbios *bios)
 		 * v1.1 (NV5+, maybe some NV4) is entirely unhelpful
 		 */
 		NV_TRACEWARN(pScrn, "No useful information in BIOS output table; "
-				    "assuming a CRT output exists\n");
+				    "adding all possible outputs\n");
 		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
+		if (bios->tmds.output0_script_ptr ||
+		    bios->tmds.output1_script_ptr)
+			fabricate_dvi_i_output(dcb, twoHeads);
 		return 0;
 	}
 
@@ -4349,9 +4382,12 @@ static void fixup_legacy_i2c(struct nvbios *bios)
 	struct parsed_dcb *dcb = &bios->bdcb.dcb;
 	int i;
 
-	for (i = 0; i < dcb->entries; i++)
+	for (i = 0; i < dcb->entries; i++) {
 		if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT)
 			dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt;
+		if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL)
+			dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel;
+	}
 }
 
 static int load_nv17_hwsq_ucode_entry(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t hwsq_offset, int entry)
@@ -4523,7 +4559,7 @@ int NVParseBios(ScrnInfoPtr pScrn)
 		return -ENODEV;
 	if ((ret = nouveau_parse_vbios_struct(pScrn)))
 		return ret;
-	if ((ret = parse_dcb_table(pScrn, bios)))
+	if ((ret = parse_dcb_table(pScrn, bios, pNv->twoHeads)))
 		return ret;
 	fixup_legacy_i2c(bios);
 

commit 3d371a78bc9522e9a1b2c967957a090bb527a30c
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Thu Mar 26 22:21:57 2009 +0000

    randr12: enable tmds reg access on pre-nv17
    
    I think this nv11 hates me

diff --git a/src/nouveau_hw.c b/src/nouveau_hw.c
index d96ebb4..6f7868f 100644
--- a/src/nouveau_hw.c
+++ b/src/nouveau_hw.c
@@ -647,6 +647,11 @@ nv_save_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *sta
 
 	regp->fp_control = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL);
 	regp->fp_debug_0 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0);
+	if (!pNv->gf4_disp_arch && head == 0)
+		/* early chips don't allow access to PRAMDAC_TMDS_* without
+		 * the head A FPCLK on (nv11 even locks up) */
+		NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0 &
+					~NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK);
 	regp->fp_debug_1 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1);
 	regp->fp_debug_2 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2);
 
diff --git a/src/nvreg.h b/src/nvreg.h
index 76ceda1..891c7e5 100644
--- a/src/nvreg.h
+++ b/src/nvreg.h
@@ -387,6 +387,7 @@
 #	define NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR		(1 << 12)
 #	define NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND		(1 << 20)
 #	define NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND		(1 << 24)
+#	define NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK		(1 << 28)
 #define NV_PRAMDAC_FP_DEBUG_1				0x00680884
 #	define NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE		11:0
 #	define NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE	(1 << 12)

commit 1bb85c8020802719e82c1335a18df9367215a8ff
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Wed Apr 1 04:09:09 2009 +0100

    randr12: reorder ramdac reg access

diff --git a/src/nouveau_hw.c b/src/nouveau_hw.c
index 38bf942..d96ebb4 100644
--- a/src/nouveau_hw.c
+++ b/src/nouveau_hw.c
@@ -613,10 +613,15 @@ nv_save_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *sta
 	NVCrtcRegPtr regp = &state->crtc_reg[head];
 	int i;
 
+	if (pNv->Architecture >= NV_ARCH_10)
+		regp->nv10_cursync = NVReadRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC);
+
 	nouveau_hw_get_pllvals(pScrn, head ? VPLL2 : VPLL1, &regp->pllvals);
+	state->pllsel = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_PLL_COEFF_SELECT);
 	if (pNv->twoHeads)
 		state->sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK);
-	state->pllsel = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_PLL_COEFF_SELECT);
+	if (pNv->NVArch == 0x11)
+		regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11);
 
 	regp->ramdac_gen_ctrl = NVReadRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL);
 
@@ -625,19 +630,13 @@ nv_save_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *sta
 	if (pNv->NVArch >= 0x30)
 		regp->ramdac_634 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_634);
 
-		regp->fp_control = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL);
-		regp->fp_debug_0 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0);
-		regp->fp_debug_1 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1);
-		regp->fp_debug_2 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2);
+	for (i = 0; i < 7; i++) {
+		uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
 
-	if (pNv->Architecture == NV_ARCH_40) {
-		regp->ramdac_a20 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A20);
-		regp->ramdac_a24 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A24);
-		regp->ramdac_a34 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A34);
+		regp->fp_vert_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg);
+		regp->fp_horiz_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg + 0x20);
 	}
 
-	if (pNv->NVArch == 0x11)
-		regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11);
 	if (pNv->gf4_disp_arch) {
 		regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER);
 		for (i = 0; i < 3; i++) {
@@ -645,19 +644,16 @@ nv_save_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *sta
 			regp->dither_regs[i + 3] = NVReadRAMDAC(pNv, head, NV_PRAMDAC_85C + i * 4);
 		}
 	}
-	if (pNv->Architecture >= NV_ARCH_10)
-		regp->nv10_cursync = NVReadRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC);
-
-	/* The regs below are 0 for non-flatpanels, so you can load and save them */
 
-	for (i = 0; i < 7; i++) {
-		uint32_t ramdac_reg = NV_PRAMDAC_FP_HDISPLAY_END + (i * 4);
-		regp->fp_horiz_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg);
-	}
+	regp->fp_control = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL);
+	regp->fp_debug_0 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0);
+	regp->fp_debug_1 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1);
+	regp->fp_debug_2 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2);
 
-	for (i = 0; i < 7; i++) {
-		uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
-		regp->fp_vert_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg);
+	if (pNv->Architecture == NV_ARCH_40) {
+		regp->ramdac_a20 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A20);
+		regp->ramdac_a24 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A24);
+		regp->ramdac_a34 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A34);
 	}
 }
 
@@ -668,12 +664,15 @@ static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mod
 	uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
 	int i;
 
-	/* This sequence is important, the NV28 is very sensitive in this area. */
-	/* Keep pllsel last and sel_clk first. */
-	if (pNv->twoHeads)
-		NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk);
+	if (pNv->Architecture >= NV_ARCH_10)
+		NVWriteRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
+
 	nouveau_hw_setpll(pScrn, pllreg, &regp->pllvals);
 	NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
+	if (pNv->twoHeads)
+		NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk);
+	if (pNv->NVArch == 0x11)
+		NVWriteRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11, regp->dither);
 
 	NVWriteRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl);
 
@@ -681,19 +680,14 @@ static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mod
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_630, regp->ramdac_630);
 	if (pNv->NVArch >= 0x30)
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_634, regp->ramdac_634);
-		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL, regp->fp_control);
-		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0);
-		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1);
-		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2, regp->fp_debug_2);
 
-	if (pNv->Architecture == NV_ARCH_40) {
-		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A20, regp->ramdac_a20);
-		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A24, regp->ramdac_a24);
-		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A34, regp->ramdac_a34);
+	for (i = 0; i < 7; i++) {
+		uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
+
+		NVWriteRAMDAC(pNv, head, ramdac_reg, regp->fp_vert_regs[i]);
+		NVWriteRAMDAC(pNv, head, ramdac_reg + 0x20, regp->fp_horiz_regs[i]);
 	}
 
-	if (pNv->NVArch == 0x11)
-		NVWriteRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11, regp->dither);
 	if (pNv->gf4_disp_arch) {
 		NVWriteRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER, regp->dither);
 		for (i = 0; i < 3; i++) {
@@ -701,19 +695,16 @@ static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mod
 			NVWriteRAMDAC(pNv, head, NV_PRAMDAC_85C + i * 4, regp->dither_regs[i + 3]);
 		}
 	}
-	if (pNv->Architecture >= NV_ARCH_10)
-		NVWriteRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
 
-	/* The regs below are 0 for non-flatpanels, so you can load and save them */
-
-	for (i = 0; i < 7; i++) {
-		uint32_t ramdac_reg = NV_PRAMDAC_FP_HDISPLAY_END + (i * 4);
-		NVWriteRAMDAC(pNv, head, ramdac_reg, regp->fp_horiz_regs[i]);
-	}
+	NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL, regp->fp_control);
+	NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0);
+	NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1);
+	NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2, regp->fp_debug_2);
 
-	for (i = 0; i < 7; i++) {
-		uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
-		NVWriteRAMDAC(pNv, head, ramdac_reg, regp->fp_vert_regs[i]);
+	if (pNv->Architecture == NV_ARCH_40) {
+		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A20, regp->ramdac_a20);
+		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A24, regp->ramdac_a24);
+		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A34, regp->ramdac_a34);
 	}
 }
 

commit 4465fddb2467ad9d923120a2fd2c648222603771
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Wed Apr 1 04:10:18 2009 +0100

    randr12: remove nv30 special case
    
    0x68?89? are just an alternative way to set scaling (set | 0x40 on 0x68.880,
    then horiz scaling in 0x68.898, vert in 0x68.89c) and afaict don't have any
    special significance on nv30

diff --git a/src/nouveau_hw.c b/src/nouveau_hw.c
index 70f4c8c..38bf942 100644
--- a/src/nouveau_hw.c
+++ b/src/nouveau_hw.c
@@ -685,10 +685,6 @@ static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mod
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0);
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1);
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2, regp->fp_debug_2);
-		if (pNv->NVArch == 0x30) { /* For unknown purposes. */
-			uint32_t reg890 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_890);
-			NVWriteRAMDAC(pNv, head, NV_PRAMDAC_89C, reg890);
-		}
 
 	if (pNv->Architecture == NV_ARCH_40) {
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A20, regp->ramdac_a20);
diff --git a/src/nvreg.h b/src/nvreg.h
index 6f142b3..76ceda1 100644
--- a/src/nvreg.h
+++ b/src/nvreg.h
@@ -395,10 +395,6 @@
 #define NV_PRAMDAC_FP_DEBUG_2				0x00680888
 #define NV_PRAMDAC_FP_DEBUG_3				0x0068088C
 
-/* Some unknown regs, purely for NV30 it seems. */
-#define NV_PRAMDAC_890					0x00680890
-#define NV_PRAMDAC_89C					0x0068089C
-
 /* see NV_PRAMDAC_INDIR_TMDS in rules.xml */
 #define NV_PRAMDAC_FP_TMDS_CONTROL			0x006808b0
 #	define NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE		(1 << 16)

commit 72eced5eeeef438979dff06b6c1cbaa120738cfe
Author: Stuart Bennett <stuart@freedesktop.org>
Date:   Wed Apr 1 03:12:30 2009 +0100

    randr12: fix/improve a load of version/feature tests
    
    Main improvement is introduction of flag for nv17+ display architecture
    
    Other version fixes include:
    * allow access of fp control regs on all cards (defined since nv4)
    * only read crtc_850 and gpio_ext on nv40+, since only written on nv40+
    * set dither state on all versions (only written out on relevant cards)
    * PRAMDAC_DACCLK is only defined/usable on nv17+
    * no point saving the lvds/tmds head for restore if there's only one head
    * fix a bunch of places the nforce (0x1a) case had been missed

diff --git a/src/nouveau_calc.c b/src/nouveau_calc.c
index 9173e90..e060915 100644
--- a/src/nouveau_calc.c
+++ b/src/nouveau_calc.c
@@ -415,7 +415,7 @@ static int getMNP_single(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk,
 	 * returns calculated clock
 	 */
 
-	int chip_version = NVPTR(pScrn)->vbios->chip_version;
+	int cv = NVPTR(pScrn)->vbios->chip_version;
 	int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq;
 	int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m;
 	int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n;
@@ -429,13 +429,13 @@ static int getMNP_single(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk,
 
 	/* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */
 	/* possibly correlated with introduction of 27MHz crystal */
-	if (chip_version <= 0x16 || chip_version == 0x20) {
+	if (cv < 0x17 || cv == 0x1a || cv == 0x20) {
 		if (clk > 250000)
 			maxM = 6;
 		if (clk > 340000)
 			maxM = 2;
 		maxlog2P = 4;
-	} else if (chip_version < 0x40) {
+	} else if (cv < 0x40) {
 		if (clk > 150000)
 			maxM = 6;
 		if (clk > 200000)
diff --git a/src/nouveau_hw.c b/src/nouveau_hw.c
index 067e3dc..70f4c8c 100644
--- a/src/nouveau_hw.c
+++ b/src/nouveau_hw.c
@@ -107,7 +107,7 @@ static int powerctrl_1_shift(int chip_version, int reg)
 {
 	int shift = -4;
 
-	if (chip_version < 0x17 || chip_version == 0x20)
+	if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20)
 		return shift;
 
 	switch (reg) {
@@ -620,25 +620,25 @@ nv_save_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *sta
 
 	regp->ramdac_gen_ctrl = NVReadRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL);
 
-	if (pNv->twoHeads) {
-		if (pNv->NVArch >= 0x17)
-			regp->ramdac_630 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_630);
-		if (pNv->NVArch >= 0x30)
-			regp->ramdac_634 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_634);
+	if (pNv->gf4_disp_arch)
+		regp->ramdac_630 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_630);
+	if (pNv->NVArch >= 0x30)
+		regp->ramdac_634 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_634);
 
 		regp->fp_control = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL);
 		regp->fp_debug_0 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0);
 		regp->fp_debug_1 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1);
 		regp->fp_debug_2 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2);
 
+	if (pNv->Architecture == NV_ARCH_40) {
 		regp->ramdac_a20 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A20);
 		regp->ramdac_a24 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A24);
 		regp->ramdac_a34 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A34);
 	}
 
-	if (pNv->NVArch == 0x11) {
+	if (pNv->NVArch == 0x11)
 		regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11);
-	} else if (pNv->twoHeads) {
+	if (pNv->gf4_disp_arch) {
 		regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER);
 		for (i = 0; i < 3; i++) {
 			regp->dither_regs[i] = NVReadRAMDAC(pNv, head, NV_PRAMDAC_850 + i * 4);
@@ -677,11 +677,10 @@ static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mod
 
 	NVWriteRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl);
 
-	if (pNv->twoHeads) {
-		if (pNv->NVArch >= 0x17)
-			NVWriteRAMDAC(pNv, head, NV_PRAMDAC_630, regp->ramdac_630);
-		if (pNv->NVArch >= 0x30)
-			NVWriteRAMDAC(pNv, head, NV_PRAMDAC_634, regp->ramdac_634);
+	if (pNv->gf4_disp_arch)
+		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_630, regp->ramdac_630);
+	if (pNv->NVArch >= 0x30)
+		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_634, regp->ramdac_634);
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL, regp->fp_control);
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0);
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1);
@@ -691,6 +690,7 @@ static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mod
 			NVWriteRAMDAC(pNv, head, NV_PRAMDAC_89C, reg890);
 		}
 
+	if (pNv->Architecture == NV_ARCH_40) {
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A20, regp->ramdac_a20);
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A24, regp->ramdac_a24);
 		NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A34, regp->ramdac_a34);
@@ -698,7 +698,7 @@ static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mod
 
 	if (pNv->NVArch == 0x11)
 		NVWriteRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11, regp->dither);
-	else if (pNv->twoHeads) {
+	if (pNv->gf4_disp_arch) {
 		NVWriteRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER, regp->dither);
 		for (i = 0; i < 3; i++) {
 			NVWriteRAMDAC(pNv, head, NV_PRAMDAC_850 + i * 4, regp->dither_regs[i]);
@@ -814,8 +814,7 @@ nv_save_state_ext(NVPtr pNv, int head, struct nouveau_mode_state *state)
 		rd_cio_state(pNv, head, regp, NV_CIO_CRE_4B);
 		rd_cio_state(pNv, head, regp, NV_CIO_CRE_TVOUT_LATENCY);
 	}
-	/* NV11 and NV20 don't have this, they stop at 0x52. */
-	if (pNv->NVArch >= 0x17 && pNv->twoHeads) {
+	if (pNv->gf4_disp_arch) {
 		rd_cio_state(pNv, head, regp, NV_CIO_CRE_53);
 		rd_cio_state(pNv, head, regp, NV_CIO_CRE_54);
 
@@ -901,8 +900,7 @@ static void nv_load_state_ext(NVPtr pNv, int head, struct nouveau_mode_state *st
 		wr_cio_state(pNv, head, regp, NV_CIO_CRE_4B);
 		wr_cio_state(pNv, head, regp, NV_CIO_CRE_TVOUT_LATENCY);
 	}
-	/* NV11 and NV20 stop at 0x52. */
-	if (pNv->NVArch >= 0x17 && pNv->twoHeads) {
+	if (pNv->gf4_disp_arch) {
 		wr_cio_state(pNv, head, regp, NV_CIO_CRE_53);
 		wr_cio_state(pNv, head, regp, NV_CIO_CRE_54);
 
diff --git a/src/nv_crtc.c b/src/nv_crtc.c
index 8d2bec5..ba50730 100644
--- a/src/nv_crtc.c
+++ b/src/nv_crtc.c
@@ -39,7 +39,7 @@ void nv_crtc_set_digital_vibrance(xf86CrtcPtr crtc, int level)
 	NVCrtcRegPtr regp = &pNv->ModeReg.crtc_reg[nv_crtc->head];
 
 	regp->CRTC[NV_CIO_CRE_CSB] = nv_crtc->saturation = level;
-	if (nv_crtc->saturation && pNv->NVArch >= 0x17 && pNv->NVArch != 0x20) {
+	if (nv_crtc->saturation && pNv->gf4_disp_arch) {
 		regp->CRTC[NV_CIO_CRE_CSB] = 0x80;
 		regp->CRTC[NV_CIO_CRE_5B] = nv_crtc->saturation << 2;
 		crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_5B);
@@ -538,11 +538,11 @@ nv_crtc_mode_set_regs(xf86CrtcPtr crtc, DisplayModePtr mode)
 	regp->crtc_830 = mode->CrtcVDisplay - 3;
 	regp->crtc_834 = mode->CrtcVDisplay - 1;
 
-	if (pNv->twoHeads)
+	if (pNv->Architecture == NV_ARCH_40)
 		/* This is what the blob does */
 		regp->crtc_850 = NVReadCRTC(pNv, 0, NV_PCRTC_850);
 
-	if (pNv->twoHeads)
+	if (pNv->Architecture == NV_ARCH_40)
 		regp->gpio_ext = NVReadCRTC(pNv, 0, NV_PCRTC_GPIO_EXT);
 
 	regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC;
@@ -721,33 +721,29 @@ nv_crtc_mode_set_fp_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr a
 		}
 	}
 
-	/* Flatpanel support needs at least a NV10 */
-	if (pNv->twoHeads) {
-		/* Output property. */
-		if (nv_encoder && nv_encoder->dithering) {
-			if (pNv->NVArch == 0x11)
-				regp->dither = savep->dither | 0x00010000;
-			else {
-				int i;
-				regp->dither = savep->dither | 0x00000001;
-				for (i = 0; i < 3; i++) {
-					regp->dither_regs[i] = 0xe4e4e4e4;
-					regp->dither_regs[i + 3] = 0x44444444;
-				}
+	/* Output property. */
+	if (nv_encoder && nv_encoder->dithering) {
+		if (pNv->NVArch == 0x11)
+			regp->dither = savep->dither | 0x00010000;
+		else {
+			int i;
+			regp->dither = savep->dither | 0x00000001;
+			for (i = 0; i < 3; i++) {
+				regp->dither_regs[i] = 0xe4e4e4e4;
+				regp->dither_regs[i + 3] = 0x44444444;
 			}
-		} else {
-			if (pNv->NVArch != 0x11) {
-				/* reset them */
-				int i;
-				for (i = 0; i < 3; i++) {
-					regp->dither_regs[i] = savep->dither_regs[i];
-					regp->dither_regs[i + 3] = savep->dither_regs[i + 3];
-				}
+		}
+	} else {
+		if (pNv->NVArch != 0x11) {
+			/* reset them */
+			int i;
+			for (i = 0; i < 3; i++) {
+				regp->dither_regs[i] = savep->dither_regs[i];
+				regp->dither_regs[i + 3] = savep->dither_regs[i + 3];
 			}
-			regp->dither = savep->dither;
 		}
-	} else
 		regp->dither = savep->dither;
+	}
 }
 
 /**
diff --git a/src/nv_output.c b/src/nv_output.c
index 49ac1eb..7b3b2dd 100644
--- a/src/nv_output.c
+++ b/src/nv_output.c
@@ -75,14 +75,12 @@ nv_load_detect(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder)
 	NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset,
 		      saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
 
-	if (pNv->NVArch >= 0x17) {
-		saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2);
+	saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2);
 
-		nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
-		if (regoffset == 0x68) {
-			saved_powerctrl_4 = nvReadMC(pNv, NV_PBUS_POWERCTRL_4);
-			nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
-		}


Reply to: