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

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



 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 
 23 files changed, 2623 insertions(+), 2419 deletions(-)

New commits:
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);
-		}
+	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);
 	}
 
 	usleep(4000);
@@ -119,11 +117,9 @@ nv_load_detect(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder)
 	/* bios does something more complex for restoring, but I think this is good enough */
 	NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput);
 	NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
-	if (pNv->NVArch >= 0x17) {
-		if (regoffset == 0x68)
-			nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
-		nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
-	}
+	if (regoffset == 0x68)
+		nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
+	nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
 
 	if (present) {
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Load detected on output %c\n", '@' + ffs(nv_encoder->dcb->or));
@@ -220,9 +216,9 @@ nv_output_detect(xf86OutputPtr output)
 					"Enable", FALSE))
 			ret = XF86OutputStatusConnected;
 		/* we don't have a load det function for early cards */
-		else if (!pNv->twoHeads || pNv->NVArch == 0x11)
+		else if (!pNv->gf4_disp_arch)
 			ret = XF86OutputStatusUnknown;
-		else if (pNv->twoHeads && nv_load_detect(pScrn, det_encoder))
+		else if (nv_load_detect(pScrn, det_encoder))
 			ret = XF86OutputStatusConnected;
 	} else if ((det_encoder = find_encoder_by_type(OUTPUT_LVDS))) {
 		if (det_encoder->dcb->lvdsconf.use_straps_for_mode) {
@@ -483,7 +479,7 @@ static Atom dv_atom, sharpness_atom;
 static void nv_output_create_resources(xf86OutputPtr output)
 {
 	struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
-	int arch = NVPTR(output->scrn)->NVArch;
+	NVPtr pNv = NVPTR(output->scrn);
 
 	/* may be called before encoder is picked, resources will be created
 	 * by update_output_fields()
@@ -497,15 +493,15 @@ static void nv_output_create_resources(xf86OutputPtr output)
 		nv_output_create_prop(output, "SCALING_MODE", &scaling_mode_atom,
 				      NULL, 0, get_current_scaling_name(nv_encoder->scaling_mode), TRUE);
 	}
-	if (arch >= 0x11 && output->crtc) {
+	if (pNv->NVArch >= 0x11 && output->crtc) {
 		struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc);
-		INT32 dv_range[2] = { 0, (arch < 0x17 || arch == 0x20) ? 3 : 63 };
+		INT32 dv_range[2] = { 0, !pNv->gf4_disp_arch ? 3 : 63 };
 		/* unsure of correct condition here: blur works on my nv34, but not on my nv31 */
-		INT32 is_range[2] = { arch > 0x31 ? -32 : 0, 31 };
+		INT32 is_range[2] = { pNv->NVArch > 0x31 ? -32 : 0, 31 };
 
 		nv_output_create_prop(output, "DIGITAL_VIBRANCE", &dv_atom,
 				      dv_range, nv_crtc->saturation, NULL, FALSE);
-		if (arch >= 0x30)
+		if (pNv->NVArch >= 0x30)
 			nv_output_create_prop(output, "IMAGE_SHARPENING", &sharpness_atom,
 					      is_range, nv_crtc->sharpness, NULL, FALSE);
 	}
@@ -516,7 +512,7 @@ nv_output_set_property(xf86OutputPtr output, Atom property,
 				RRPropertyValuePtr value)
 {
 	struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
-	int arch = NVPTR(output->scrn)->NVArch;
+	NVPtr pNv = NVPTR(output->scrn);
 
 	if (property == scaling_mode_atom) {
 		int32_t ret;
@@ -554,12 +550,12 @@ nv_output_set_property(xf86OutputPtr output, Atom property,
 			return FALSE;
 
 		if (property == dv_atom) {
-			if (val < 0 || val > ((arch < 0x17 || arch == 0x20) ? 3 : 63))
+			if (val < 0 || val > (!pNv->gf4_disp_arch ? 3 : 63))


Reply to: