xf86-video-ati: Branch 'master' - 5 commits

Alex Deucher agd5f at kemper.freedesktop.org
Fri Dec 21 13:35:48 PST 2007


 src/Makefile.am      |    3 
 src/legacy_crtc.c    | 1847 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/legacy_output.c  | 1736 +++++++++++++++++++++++++++++++++++++++++++++++
 src/radeon.h         |    5 
 src/radeon_accel.c   |  337 +++++++++
 src/radeon_crtc.c    |  916 +------------------------
 src/radeon_display.c |  878 ------------------------
 src/radeon_driver.c  | 1461 ----------------------------------------
 src/radeon_output.c  | 1252 +---------------------------------
 src/radeon_tv.c      |  395 ++++++++++
 10 files changed, 4426 insertions(+), 4404 deletions(-)

New commits:
commit 8c761afdcb9baf1649b93449692fb9ab67bc2c80
Author: Alex Deucher <alex at botch2.(none)>
Date:   Fri Dec 21 16:24:49 2007 -0500

    RADEON: more re-org
    
    move save/restore routines into legacy_crtc/output

diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
index f1bf9be..4a7071a 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -53,6 +53,585 @@
 #include "sarea.h"
 #endif
 
+/* Write common registers */
+void
+RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
+			     RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    if (info->IsSecondary)
+      return;
+
+    OUTREG(RADEON_OVR_CLR,            restore->ovr_clr);
+    OUTREG(RADEON_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right);
+    OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom);
+    OUTREG(RADEON_OV0_SCALE_CNTL,     restore->ov0_scale_cntl);
+    OUTREG(RADEON_SUBPIC_CNTL,        restore->subpic_cntl);
+    OUTREG(RADEON_VIPH_CONTROL,       restore->viph_control);
+    OUTREG(RADEON_I2C_CNTL_1,         restore->i2c_cntl_1);
+    OUTREG(RADEON_GEN_INT_CNTL,       restore->gen_int_cntl);
+    OUTREG(RADEON_CAP0_TRIG_CNTL,     restore->cap0_trig_cntl);
+    OUTREG(RADEON_CAP1_TRIG_CNTL,     restore->cap1_trig_cntl);
+    OUTREG(RADEON_BUS_CNTL,           restore->bus_cntl);
+    OUTREG(RADEON_SURFACE_CNTL,       restore->surface_cntl);
+
+    /* Workaround for the VT switching problem in dual-head mode.  This
+     * problem only occurs on RV style chips, typically when a FP and
+     * CRT are connected.
+     */
+    if (pRADEONEnt->HasCRTC2 &&
+	info->ChipFamily != CHIP_FAMILY_R200 &&
+	!IS_R300_VARIANT) {
+	CARD32        tmp;
+
+	tmp = INREG(RADEON_DAC_CNTL2);
+	OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL);
+	usleep(100000);
+    }
+}
+
+
+/* Write CRTC registers */
+void
+RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
+			   RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Programming CRTC1, offset: 0x%08x\n",
+		   (unsigned)restore->crtc_offset);
+
+    /* We prevent the CRTC from hitting the memory controller until
+     * fully programmed
+     */
+    OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl |
+	   RADEON_CRTC_DISP_REQ_EN_B);
+
+    OUTREGP(RADEON_CRTC_EXT_CNTL,
+	    restore->crtc_ext_cntl,
+	    RADEON_CRTC_VSYNC_DIS |
+	    RADEON_CRTC_HSYNC_DIS |
+	    RADEON_CRTC_DISPLAY_DIS);
+
+    OUTREG(RADEON_CRTC_H_TOTAL_DISP,    restore->crtc_h_total_disp);
+    OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
+    OUTREG(RADEON_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
+    OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
+
+    OUTREG(RADEON_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
+    OUTREG(RADEON_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
+    OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
+    OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
+
+    if (IS_R300_VARIANT)
+	OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0);
+    OUTREG(RADEON_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
+    OUTREG(RADEON_CRTC_OFFSET,          restore->crtc_offset);
+
+    OUTREG(RADEON_CRTC_PITCH,           restore->crtc_pitch);
+    OUTREG(RADEON_DISP_MERGE_CNTL,      restore->disp_merge_cntl);
+    OUTREG(RADEON_CRTC_MORE_CNTL,       restore->crtc_more_cntl);
+
+    if (info->IsDellServer) {
+	OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
+	OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
+	OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
+	OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
+    }
+
+    OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl);
+}
+
+/* Write CRTC2 registers */
+void
+RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
+			    RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    /*    CARD32	   crtc2_gen_cntl;*/
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Programming CRTC2, offset: 0x%08x\n",
+		   (unsigned)restore->crtc2_offset);
+
+    /* We prevent the CRTC from hitting the memory controller until
+     * fully programmed
+     */
+    OUTREG(RADEON_CRTC2_GEN_CNTL,
+	   restore->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS |
+	   RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS |
+	   RADEON_CRTC2_DISP_REQ_EN_B);
+
+    OUTREG(RADEON_CRTC2_H_TOTAL_DISP,    restore->crtc2_h_total_disp);
+    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
+    OUTREG(RADEON_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
+    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
+
+    OUTREG(RADEON_FP_H2_SYNC_STRT_WID,   restore->fp_h2_sync_strt_wid);
+    OUTREG(RADEON_FP_V2_SYNC_STRT_WID,   restore->fp_v2_sync_strt_wid);
+
+    if (IS_R300_VARIANT)
+	OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0);
+    OUTREG(RADEON_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
+    OUTREG(RADEON_CRTC2_OFFSET,          restore->crtc2_offset);
+
+    OUTREG(RADEON_CRTC2_PITCH,           restore->crtc2_pitch);
+    OUTREG(RADEON_DISP2_MERGE_CNTL,      restore->disp2_merge_cntl);
+
+    if (info->ChipFamily == CHIP_FAMILY_RS400) {
+	OUTREG(RADEON_RS480_UNK_e30, restore->rs480_unk_e30);
+	OUTREG(RADEON_RS480_UNK_e34, restore->rs480_unk_e34);
+	OUTREG(RADEON_RS480_UNK_e38, restore->rs480_unk_e38);
+	OUTREG(RADEON_RS480_UNK_e3c, restore->rs480_unk_e3c);
+    }
+    OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
+
+}
+
+static void
+RADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
+{
+    int i = 0;
+
+    /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
+       the cause yet, but this workaround will mask the problem for now.
+       Other chips usually will pass at the very first test, so the
+       workaround shouldn't have any effect on them. */
+    for (i = 0;
+	 (i < 10000 &&
+	  INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
+	 i++);
+}
+
+static void
+RADEONPLLWriteUpdate(ScrnInfoPtr pScrn)
+{
+    while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
+
+    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+	    RADEON_PPLL_ATOMIC_UPDATE_W,
+	    ~(RADEON_PPLL_ATOMIC_UPDATE_W));
+}
+
+static void
+RADEONPLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
+{
+    int i = 0;
+
+    /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
+       the cause yet, but this workaround will mask the problem for now.
+       Other chips usually will pass at the very first test, so the
+       workaround shouldn't have any effect on them. */
+    for (i = 0;
+	 (i < 10000 &&
+	  INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
+	 i++);
+}
+
+static void
+RADEONPLL2WriteUpdate(ScrnInfoPtr pScrn)
+{
+    while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
+
+    OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
+	    RADEON_P2PLL_ATOMIC_UPDATE_W,
+	    ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
+}
+
+static CARD8
+RADEONComputePLLGain(CARD16 reference_freq, CARD16 ref_div,
+		     CARD16 fb_div)
+{
+    unsigned vcoFreq;
+
+    if (!ref_div)
+	return 1;
+
+    vcoFreq = ((unsigned)reference_freq * fb_div) / ref_div;
+
+    /*
+     * This is horribly crude: the VCO frequency range is divided into
+     * 3 parts, each part having a fixed PLL gain value.
+     */
+    if (vcoFreq >= 30000)
+	/*
+	 * [300..max] MHz : 7
+	 */
+	return 7;
+    else if (vcoFreq >= 18000)
+	/*
+	 * [180..300) MHz : 4
+	 */
+        return 4;
+    else
+	/*
+	 * [0..180) MHz : 1
+	 */
+        return 1;
+}
+
+/* Write PLL registers */
+void
+RADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
+			  RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD8 pllGain;
+
+#if defined(__powerpc__)
+    /* apparently restoring the pll causes a hang??? */
+    if (info->MacModel == RADEON_MAC_IBOOK)
+	return;
+#endif
+
+    pllGain = RADEONComputePLLGain(info->pll.reference_freq,
+				   restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
+				   restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK);
+
+    if (info->IsMobility) {
+        /* A temporal workaround for the occational blanking on certain laptop panels.
+           This appears to related to the PLL divider registers (fail to lock?).
+	   It occurs even when all dividers are the same with their old settings.
+           In this case we really don't need to fiddle with PLL registers.
+           By doing this we can avoid the blanking problem with some panels.
+        */
+        if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) &&
+	    (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) & 
+				     (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) {
+	    OUTREGP(RADEON_CLOCK_CNTL_INDEX,
+		    RADEON_PLL_DIV_SEL,
+		    ~(RADEON_PLL_DIV_SEL));
+	    RADEONPllErrataAfterIndex(info);
+	    return;
+	}
+    }
+
+    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
+	    RADEON_VCLK_SRC_SEL_CPUCLK,
+	    ~(RADEON_VCLK_SRC_SEL_MASK));
+
+    OUTPLLP(pScrn,
+	    RADEON_PPLL_CNTL,
+	    RADEON_PPLL_RESET
+	    | RADEON_PPLL_ATOMIC_UPDATE_EN
+	    | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
+	    | ((CARD32)pllGain << RADEON_PPLL_PVG_SHIFT),
+	    ~(RADEON_PPLL_RESET
+	      | RADEON_PPLL_ATOMIC_UPDATE_EN
+	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
+	      | RADEON_PPLL_PVG_MASK));
+
+    OUTREGP(RADEON_CLOCK_CNTL_INDEX,
+	    RADEON_PLL_DIV_SEL,
+	    ~(RADEON_PLL_DIV_SEL));
+    RADEONPllErrataAfterIndex(info);
+
+    if (IS_R300_VARIANT ||
+	(info->ChipFamily == CHIP_FAMILY_RS300) ||
+	(info->ChipFamily == CHIP_FAMILY_RS400)) {
+	if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
+	    /* When restoring console mode, use saved PPLL_REF_DIV
+	     * setting.
+	     */
+	    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+		    restore->ppll_ref_div,
+		    0);
+	} else {
+	    /* R300 uses ref_div_acc field as real ref divider */
+	    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+		    (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
+		    ~R300_PPLL_REF_DIV_ACC_MASK);
+	}
+    } else {
+	OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+		restore->ppll_ref_div,
+		~RADEON_PPLL_REF_DIV_MASK);
+    }
+
+    OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
+	    restore->ppll_div_3,
+	    ~RADEON_PPLL_FB3_DIV_MASK);
+
+    OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
+	    restore->ppll_div_3,
+	    ~RADEON_PPLL_POST3_DIV_MASK);
+
+    RADEONPLLWriteUpdate(pScrn);
+    RADEONPLLWaitForReadUpdateComplete(pScrn);
+
+    OUTPLL(pScrn, RADEON_HTOTAL_CNTL, restore->htotal_cntl);
+
+    OUTPLLP(pScrn, RADEON_PPLL_CNTL,
+	    0,
+	    ~(RADEON_PPLL_RESET
+	      | RADEON_PPLL_SLEEP
+	      | RADEON_PPLL_ATOMIC_UPDATE_EN
+	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
+		   restore->ppll_ref_div,
+		   restore->ppll_div_3,
+		   (unsigned)restore->htotal_cntl,
+		   INPLL(pScrn, RADEON_PPLL_CNTL));
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Wrote: rd=%d, fd=%d, pd=%d\n",
+		   restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
+		   restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
+		   (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16);
+
+    usleep(50000); /* Let the clock to lock */
+
+    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
+	    RADEON_VCLK_SRC_SEL_PPLLCLK,
+	    ~(RADEON_VCLK_SRC_SEL_MASK));
+
+    /*OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_ecp_cntl);*/
+
+    ErrorF("finished PLL1\n");
+
+}
+
+/* Write PLL2 registers */
+void
+RADEONRestorePLL2Registers(ScrnInfoPtr pScrn,
+			   RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    CARD8 pllGain;
+
+    pllGain = RADEONComputePLLGain(info->pll.reference_freq,
+                                   restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
+                                   restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK);
+
+
+    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
+	    RADEON_PIX2CLK_SRC_SEL_CPUCLK,
+	    ~(RADEON_PIX2CLK_SRC_SEL_MASK));
+
+    OUTPLLP(pScrn,
+	    RADEON_P2PLL_CNTL,
+	    RADEON_P2PLL_RESET
+	    | RADEON_P2PLL_ATOMIC_UPDATE_EN
+	    | ((CARD32)pllGain << RADEON_P2PLL_PVG_SHIFT),
+	    ~(RADEON_P2PLL_RESET
+	      | RADEON_P2PLL_ATOMIC_UPDATE_EN
+	      | RADEON_P2PLL_PVG_MASK));
+
+
+    OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
+	    restore->p2pll_ref_div,
+	    ~RADEON_P2PLL_REF_DIV_MASK);
+
+    OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
+	    restore->p2pll_div_0,
+	    ~RADEON_P2PLL_FB0_DIV_MASK);
+
+    OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
+	    restore->p2pll_div_0,
+	    ~RADEON_P2PLL_POST0_DIV_MASK);
+
+    RADEONPLL2WriteUpdate(pScrn);
+    RADEONPLL2WaitForReadUpdateComplete(pScrn);
+
+    OUTPLL(pScrn, RADEON_HTOTAL2_CNTL, restore->htotal_cntl2);
+
+    OUTPLLP(pScrn, RADEON_P2PLL_CNTL,
+	    0,
+	    ~(RADEON_P2PLL_RESET
+	      | RADEON_P2PLL_SLEEP
+	      | RADEON_P2PLL_ATOMIC_UPDATE_EN));
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
+		   (unsigned)restore->p2pll_ref_div,
+		   (unsigned)restore->p2pll_div_0,
+		   (unsigned)restore->htotal_cntl2,
+		   INPLL(pScrn, RADEON_P2PLL_CNTL));
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Wrote2: rd=%u, fd=%u, pd=%u\n",
+		   (unsigned)restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
+		   (unsigned)restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK,
+		   (unsigned)((restore->p2pll_div_0 &
+			       RADEON_P2PLL_POST0_DIV_MASK) >>16));
+
+    usleep(5000); /* Let the clock to lock */
+
+    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
+	    RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
+	    ~(RADEON_PIX2CLK_SRC_SEL_MASK));
+
+    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl);
+
+    ErrorF("finished PLL2\n");
+
+}
+
+/* Read common registers */
+void
+RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->ovr_clr            = INREG(RADEON_OVR_CLR);
+    save->ovr_wid_left_right = INREG(RADEON_OVR_WID_LEFT_RIGHT);
+    save->ovr_wid_top_bottom = INREG(RADEON_OVR_WID_TOP_BOTTOM);
+    save->ov0_scale_cntl     = INREG(RADEON_OV0_SCALE_CNTL);
+    save->subpic_cntl        = INREG(RADEON_SUBPIC_CNTL);
+    save->viph_control       = INREG(RADEON_VIPH_CONTROL);
+    save->i2c_cntl_1         = INREG(RADEON_I2C_CNTL_1);
+    save->gen_int_cntl       = INREG(RADEON_GEN_INT_CNTL);
+    save->cap0_trig_cntl     = INREG(RADEON_CAP0_TRIG_CNTL);
+    save->cap1_trig_cntl     = INREG(RADEON_CAP1_TRIG_CNTL);
+    save->bus_cntl           = INREG(RADEON_BUS_CNTL);
+    save->surface_cntl	     = INREG(RADEON_SURFACE_CNTL);
+    save->grph_buffer_cntl   = INREG(RADEON_GRPH_BUFFER_CNTL);
+    save->grph2_buffer_cntl  = INREG(RADEON_GRPH2_BUFFER_CNTL);
+}
+
+void
+RADEONSaveBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->bios_4_scratch       = INREG(RADEON_BIOS_4_SCRATCH);
+    save->bios_5_scratch       = INREG(RADEON_BIOS_5_SCRATCH);
+    save->bios_6_scratch       = INREG(RADEON_BIOS_6_SCRATCH);
+}
+
+/* Read CRTC registers */
+void
+RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->crtc_gen_cntl        = INREG(RADEON_CRTC_GEN_CNTL);
+    save->crtc_ext_cntl        = INREG(RADEON_CRTC_EXT_CNTL);
+    save->crtc_h_total_disp    = INREG(RADEON_CRTC_H_TOTAL_DISP);
+    save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID);
+    save->crtc_v_total_disp    = INREG(RADEON_CRTC_V_TOTAL_DISP);
+    save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID);
+
+    save->fp_h_sync_strt_wid   = INREG(RADEON_FP_H_SYNC_STRT_WID);
+    save->fp_v_sync_strt_wid   = INREG(RADEON_FP_V_SYNC_STRT_WID);
+    save->fp_crtc_h_total_disp = INREG(RADEON_FP_CRTC_H_TOTAL_DISP);
+    save->fp_crtc_v_total_disp = INREG(RADEON_FP_CRTC_V_TOTAL_DISP);
+
+    save->crtc_offset          = INREG(RADEON_CRTC_OFFSET);
+    save->crtc_offset_cntl     = INREG(RADEON_CRTC_OFFSET_CNTL);
+    save->crtc_pitch           = INREG(RADEON_CRTC_PITCH);
+    save->disp_merge_cntl      = INREG(RADEON_DISP_MERGE_CNTL);
+    save->crtc_more_cntl       = INREG(RADEON_CRTC_MORE_CNTL);
+
+    if (IS_R300_VARIANT)
+	save->crtc_tile_x0_y0 =  INREG(R300_CRTC_TILE_X0_Y0);
+
+    if (info->IsDellServer) {
+	save->tv_dac_cntl      = INREG(RADEON_TV_DAC_CNTL);
+	save->dac2_cntl        = INREG(RADEON_DAC_CNTL2);
+	save->disp_hw_debug    = INREG (RADEON_DISP_HW_DEBUG);
+	save->crtc2_gen_cntl   = INREG(RADEON_CRTC2_GEN_CNTL);
+    }
+
+    /* track if the crtc is enabled for text restore */
+    if (save->crtc_ext_cntl & RADEON_CRTC_DISPLAY_DIS)
+	info->crtc_on = FALSE;
+    else
+	info->crtc_on = TRUE;
+
+}
+
+/* Read CRTC2 registers */
+void
+RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->crtc2_gen_cntl        = INREG(RADEON_CRTC2_GEN_CNTL);
+    save->crtc2_h_total_disp    = INREG(RADEON_CRTC2_H_TOTAL_DISP);
+    save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
+    save->crtc2_v_total_disp    = INREG(RADEON_CRTC2_V_TOTAL_DISP);
+    save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
+    save->crtc2_offset          = INREG(RADEON_CRTC2_OFFSET);
+    save->crtc2_offset_cntl     = INREG(RADEON_CRTC2_OFFSET_CNTL);
+    save->crtc2_pitch           = INREG(RADEON_CRTC2_PITCH);
+
+    if (IS_R300_VARIANT)
+	save->crtc2_tile_x0_y0 =  INREG(R300_CRTC2_TILE_X0_Y0);
+
+    save->fp_h2_sync_strt_wid   = INREG (RADEON_FP_H2_SYNC_STRT_WID);
+    save->fp_v2_sync_strt_wid   = INREG (RADEON_FP_V2_SYNC_STRT_WID);
+
+    if (info->ChipFamily == CHIP_FAMILY_RS400) {
+	save->rs480_unk_e30 = INREG(RADEON_RS480_UNK_e30);
+	save->rs480_unk_e34 = INREG(RADEON_RS480_UNK_e34);
+	save->rs480_unk_e38 = INREG(RADEON_RS480_UNK_e38);
+	save->rs480_unk_e3c = INREG(RADEON_RS480_UNK_e3c);
+    }
+    
+    save->disp2_merge_cntl      = INREG(RADEON_DISP2_MERGE_CNTL);
+
+    /* track if the crtc is enabled for text restore */
+    if (save->crtc2_gen_cntl & RADEON_CRTC2_DISP_DIS)
+	info->crtc2_on = FALSE;
+    else
+	info->crtc2_on = TRUE;
+
+}
+
+/* Read PLL registers */
+void
+RADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV);
+    save->ppll_div_3   = INPLL(pScrn, RADEON_PPLL_DIV_3);
+    save->htotal_cntl  = INPLL(pScrn, RADEON_HTOTAL_CNTL);
+    save->vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Read: 0x%08x 0x%08x 0x%08x\n",
+		   save->ppll_ref_div,
+		   save->ppll_div_3,
+		   (unsigned)save->htotal_cntl);
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Read: rd=%d, fd=%d, pd=%d\n",
+		   save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
+		   save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
+		   (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16);
+}
+
+/* Read PLL registers */
+void
+RADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    save->p2pll_ref_div = INPLL(pScrn, RADEON_P2PLL_REF_DIV);
+    save->p2pll_div_0   = INPLL(pScrn, RADEON_P2PLL_DIV_0);
+    save->htotal_cntl2  = INPLL(pScrn, RADEON_HTOTAL2_CNTL);
+    save->pixclks_cntl  = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Read: 0x%08x 0x%08x 0x%08x\n",
+		   (unsigned)save->p2pll_ref_div,
+		   (unsigned)save->p2pll_div_0,
+		   (unsigned)save->htotal_cntl2);
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Read: rd=%u, fd=%u, pd=%u\n",
+		   (unsigned)(save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK),
+		   (unsigned)(save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK),
+		   (unsigned)((save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK)
+			      >> 16));
+}
 
 void
 legacy_crtc_dpms(xf86CrtcPtr crtc, int mode)
diff --git a/src/legacy_output.c b/src/legacy_output.c
index 6f55ae2..799aa2e 100644
--- a/src/legacy_output.c
+++ b/src/legacy_output.c
@@ -53,6 +53,165 @@ static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color
 static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color);
 static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn);
 
+void
+RADEONRestoreDACRegisters(ScrnInfoPtr pScrn,
+			  RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    if (IS_R300_VARIANT)
+	OUTREGP(RADEON_GPIOPAD_A, restore->gpiopad_a, ~1);
+
+    OUTREGP(RADEON_DAC_CNTL,
+	    restore->dac_cntl,
+	    RADEON_DAC_RANGE_CNTL |
+	    RADEON_DAC_BLANKING);
+
+    OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
+
+    if ((info->ChipFamily != CHIP_FAMILY_RADEON) &&
+    	(info->ChipFamily != CHIP_FAMILY_R200)) 
+    OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
+
+    OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl);
+
+    if ((info->ChipFamily == CHIP_FAMILY_R200) ||
+	IS_R300_VARIANT) {
+	OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl);
+    } else {
+	OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
+    }
+
+    OUTREG(RADEON_DAC_MACRO_CNTL, restore->dac_macro_cntl);
+
+    /* R200 DAC connected via DVO */
+    if (info->ChipFamily == CHIP_FAMILY_R200)
+	OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl);
+}
+
+
+/* Write TMDS registers */
+void
+RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    OUTREG(RADEON_TMDS_PLL_CNTL,        restore->tmds_pll_cntl);
+    OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl);
+    OUTREG(RADEON_FP_GEN_CNTL,          restore->fp_gen_cntl);
+
+    /* old AIW Radeon has some BIOS initialization problem
+     * with display buffer underflow, only occurs to DFP
+     */
+    if (!pRADEONEnt->HasCRTC2)
+	OUTREG(RADEON_GRPH_BUFFER_CNTL,
+	       INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
+
+}
+
+/* Write FP2 registers */
+void
+RADEONRestoreFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    OUTREG(RADEON_FP2_GEN_CNTL,         restore->fp2_gen_cntl);
+
+}
+
+/* Write RMX registers */
+void
+RADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    OUTREG(RADEON_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
+    OUTREG(RADEON_FP_VERT_STRETCH,      restore->fp_vert_stretch);
+
+}
+
+/* Write LVDS registers */
+void
+RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    if (info->IsMobility) {
+	OUTREG(RADEON_LVDS_GEN_CNTL,  restore->lvds_gen_cntl);
+	OUTREG(RADEON_LVDS_PLL_CNTL,  restore->lvds_pll_cntl);
+
+	if (info->ChipFamily == CHIP_FAMILY_RV410) {
+	    OUTREG(RADEON_CLOCK_CNTL_INDEX, 0);
+	}
+    }
+
+}
+
+void
+RADEONRestoreBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH);
+    CARD32 bios_6_scratch = INREG(RADEON_BIOS_6_SCRATCH);
+
+    OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch);
+    bios_5_scratch &= 0xF;
+    bios_5_scratch |= (restore->bios_5_scratch & ~0xF);
+    OUTREG(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+    if (restore->bios_6_scratch & 0x40000000)
+	bios_6_scratch |= 0x40000000;
+    else
+	bios_6_scratch &= ~0x40000000;
+    OUTREG(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+
+}
+
+void
+RADEONSaveDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->dac_cntl              = INREG(RADEON_DAC_CNTL);
+    save->dac2_cntl             = INREG(RADEON_DAC_CNTL2);
+    save->tv_dac_cntl           = INREG(RADEON_TV_DAC_CNTL);
+    save->disp_output_cntl      = INREG(RADEON_DISP_OUTPUT_CNTL);
+    save->disp_tv_out_cntl      = INREG(RADEON_DISP_TV_OUT_CNTL);
+    save->disp_hw_debug         = INREG(RADEON_DISP_HW_DEBUG);
+    save->dac_macro_cntl        = INREG(RADEON_DAC_MACRO_CNTL);
+    save->gpiopad_a             = INREG(RADEON_GPIOPAD_A);
+
+}
+
+/* Read flat panel registers */
+void
+RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->fp_gen_cntl          = INREG(RADEON_FP_GEN_CNTL);
+    save->fp2_gen_cntl          = INREG (RADEON_FP2_GEN_CNTL);
+    save->fp_horz_stretch      = INREG(RADEON_FP_HORZ_STRETCH);
+    save->fp_vert_stretch      = INREG(RADEON_FP_VERT_STRETCH);
+    save->lvds_gen_cntl        = INREG(RADEON_LVDS_GEN_CNTL);
+    save->lvds_pll_cntl        = INREG(RADEON_LVDS_PLL_CNTL);
+    save->tmds_pll_cntl        = INREG(RADEON_TMDS_PLL_CNTL);
+    save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL);
+
+    if (info->ChipFamily == CHIP_FAMILY_RV280) {
+	/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
+	save->tmds_pll_cntl ^= (1 << 22);
+    }
+}
+
 
 Bool
 RADEONDVOReadByte(I2CDevPtr dvo, int addr, CARD8 *ch)
diff --git a/src/radeon.h b/src/radeon.h
index 47e1b89..5c15888 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -902,8 +902,6 @@ extern void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save,
                                   DisplayModePtr mode, BOOL IsPrimary);
 
 extern void RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore);
-extern void RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore);
-extern void RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore);
 
 #ifdef XF86DRI
 #ifdef USE_XAA
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 7b9cd85..1662e04 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -125,11 +125,9 @@ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
 static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
 #endif
 
-DisplayModePtr
+extern DisplayModePtr
 RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode);
 
-static void RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests,
-                              unsigned nWaitLoops, unsigned cntThreshold);
 
 static const OptionInfoRec RADEONOptions[] = {
     { OPTION_NOACCEL,        "NoAccel",          OPTV_BOOLEAN, {0}, FALSE },
@@ -3910,820 +3908,6 @@ static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
 }
 #endif
 
-/* Write common registers */
-void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
-					 RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    if (info->IsSecondary)
-      return;
-
-    OUTREG(RADEON_OVR_CLR,            restore->ovr_clr);
-    OUTREG(RADEON_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right);
-    OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom);
-    OUTREG(RADEON_OV0_SCALE_CNTL,     restore->ov0_scale_cntl);
-    OUTREG(RADEON_SUBPIC_CNTL,        restore->subpic_cntl);
-    OUTREG(RADEON_VIPH_CONTROL,       restore->viph_control);
-    OUTREG(RADEON_I2C_CNTL_1,         restore->i2c_cntl_1);
-    OUTREG(RADEON_GEN_INT_CNTL,       restore->gen_int_cntl);
-    OUTREG(RADEON_CAP0_TRIG_CNTL,     restore->cap0_trig_cntl);
-    OUTREG(RADEON_CAP1_TRIG_CNTL,     restore->cap1_trig_cntl);
-    OUTREG(RADEON_BUS_CNTL,           restore->bus_cntl);
-    OUTREG(RADEON_SURFACE_CNTL,       restore->surface_cntl);
-
-    /* Workaround for the VT switching problem in dual-head mode.  This
-     * problem only occurs on RV style chips, typically when a FP and
-     * CRT are connected.
-     */
-    if (pRADEONEnt->HasCRTC2 &&
-	info->ChipFamily != CHIP_FAMILY_R200 &&
-	!IS_R300_VARIANT) {
-	CARD32        tmp;
-
-	tmp = INREG(RADEON_DAC_CNTL2);
-	OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL);
-	usleep(100000);
-    }
-}
-
-void RADEONRestoreDACRegisters(ScrnInfoPtr pScrn,
-				       RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    if (IS_R300_VARIANT)
-	OUTREGP(RADEON_GPIOPAD_A, restore->gpiopad_a, ~1);
-
-    OUTREGP(RADEON_DAC_CNTL,
-	    restore->dac_cntl,
-	    RADEON_DAC_RANGE_CNTL |
-	    RADEON_DAC_BLANKING);
-
-    OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
-
-    if ((info->ChipFamily != CHIP_FAMILY_RADEON) &&
-    	(info->ChipFamily != CHIP_FAMILY_R200)) 
-    OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
-
-    OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl);
-
-    if ((info->ChipFamily == CHIP_FAMILY_R200) ||
-	IS_R300_VARIANT) {
-	OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl);
-    } else {
-	OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
-    }
-
-    OUTREG(RADEON_DAC_MACRO_CNTL, restore->dac_macro_cntl);
-
-    /* R200 DAC connected via DVO */
-    if (info->ChipFamily == CHIP_FAMILY_R200)
-	OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl);
-}
-
-/* Write CRTC registers */
-void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
-				       RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Programming CRTC1, offset: 0x%08x\n",
-		   (unsigned)restore->crtc_offset);
-
-    /* We prevent the CRTC from hitting the memory controller until
-     * fully programmed
-     */
-    OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl |
-	   RADEON_CRTC_DISP_REQ_EN_B);
-
-    OUTREGP(RADEON_CRTC_EXT_CNTL,
-	    restore->crtc_ext_cntl,
-	    RADEON_CRTC_VSYNC_DIS |
-	    RADEON_CRTC_HSYNC_DIS |
-	    RADEON_CRTC_DISPLAY_DIS);
-
-    OUTREG(RADEON_CRTC_H_TOTAL_DISP,    restore->crtc_h_total_disp);
-    OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
-    OUTREG(RADEON_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
-    OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
-
-    OUTREG(RADEON_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
-    OUTREG(RADEON_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
-    OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
-    OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
-
-    if (IS_R300_VARIANT)
-	OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0);
-    OUTREG(RADEON_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
-    OUTREG(RADEON_CRTC_OFFSET,          restore->crtc_offset);
-
-    OUTREG(RADEON_CRTC_PITCH,           restore->crtc_pitch);
-    OUTREG(RADEON_DISP_MERGE_CNTL,      restore->disp_merge_cntl);
-    OUTREG(RADEON_CRTC_MORE_CNTL,       restore->crtc_more_cntl);
-
-    if (info->IsDellServer) {
-	OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
-	OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
-	OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
-	OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
-    }
-
-    OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl);
-}
-
-/* Write CRTC2 registers */
-void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
-					RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    /*    CARD32	   crtc2_gen_cntl;*/
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Programming CRTC2, offset: 0x%08x\n",
-		   (unsigned)restore->crtc2_offset);
-
-    /* We prevent the CRTC from hitting the memory controller until
-     * fully programmed
-     */
-    OUTREG(RADEON_CRTC2_GEN_CNTL,
-	   restore->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS |
-	   RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS |
-	   RADEON_CRTC2_DISP_REQ_EN_B);
-
-    OUTREG(RADEON_CRTC2_H_TOTAL_DISP,    restore->crtc2_h_total_disp);
-    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
-    OUTREG(RADEON_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
-    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
-
-    OUTREG(RADEON_FP_H2_SYNC_STRT_WID,   restore->fp_h2_sync_strt_wid);
-    OUTREG(RADEON_FP_V2_SYNC_STRT_WID,   restore->fp_v2_sync_strt_wid);
-
-    if (IS_R300_VARIANT)
-	OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0);
-    OUTREG(RADEON_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
-    OUTREG(RADEON_CRTC2_OFFSET,          restore->crtc2_offset);
-
-    OUTREG(RADEON_CRTC2_PITCH,           restore->crtc2_pitch);
-    OUTREG(RADEON_DISP2_MERGE_CNTL,      restore->disp2_merge_cntl);
-
-    if (info->ChipFamily == CHIP_FAMILY_RS400) {
-	OUTREG(RADEON_RS480_UNK_e30, restore->rs480_unk_e30);
-	OUTREG(RADEON_RS480_UNK_e34, restore->rs480_unk_e34);
-	OUTREG(RADEON_RS480_UNK_e38, restore->rs480_unk_e38);
-	OUTREG(RADEON_RS480_UNK_e3c, restore->rs480_unk_e3c);
-    }
-    OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
-
-}
-
-/* Write TMDS registers */
-void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    OUTREG(RADEON_TMDS_PLL_CNTL,        restore->tmds_pll_cntl);
-    OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl);
-    OUTREG(RADEON_FP_GEN_CNTL,          restore->fp_gen_cntl);
-
-    /* old AIW Radeon has some BIOS initialization problem
-     * with display buffer underflow, only occurs to DFP
-     */
-    if (!pRADEONEnt->HasCRTC2)
-	OUTREG(RADEON_GRPH_BUFFER_CNTL,
-	       INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
-
-}
-
-/* Write FP2 registers */
-void RADEONRestoreFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    OUTREG(RADEON_FP2_GEN_CNTL,         restore->fp2_gen_cntl);
-
-}
-
-/* Write RMX registers */
-void RADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    OUTREG(RADEON_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
-    OUTREG(RADEON_FP_VERT_STRETCH,      restore->fp_vert_stretch);
-
-}
-
-/* Write LVDS registers */
-void RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    if (info->IsMobility) {
-	OUTREG(RADEON_LVDS_GEN_CNTL,  restore->lvds_gen_cntl);
-	OUTREG(RADEON_LVDS_PLL_CNTL,  restore->lvds_pll_cntl);
-
-	if (info->ChipFamily == CHIP_FAMILY_RV410) {
-	    OUTREG(RADEON_CLOCK_CNTL_INDEX, 0);
-	}
-    }
-
-}
-
-void RADEONRestoreBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH);
-    CARD32 bios_6_scratch = INREG(RADEON_BIOS_6_SCRATCH);
-
-    OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch);
-    bios_5_scratch &= 0xF;
-    bios_5_scratch |= (restore->bios_5_scratch & ~0xF);
-    OUTREG(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
-    if (restore->bios_6_scratch & 0x40000000)
-	bios_6_scratch |= 0x40000000;
-    else
-	bios_6_scratch &= ~0x40000000;
-    OUTREG(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
-
-}
-
-/* Write to TV FIFO RAM */
-static void RADEONWriteTVFIFO(ScrnInfoPtr pScrn, CARD16 addr,
-			      CARD32 value)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 tmp;
-    int i = 0;
-
-    OUTREG(RADEON_TV_HOST_WRITE_DATA, value);
-
-    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr);
-    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
-
-    do {
-	tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL);
-	if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
-	    break;
-	i++;
-    }
-    while (i < 10000);
-    /*while ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0);*/
-
-    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0);
-}
-
-/* Read from TV FIFO RAM */
-static CARD32 RADEONReadTVFIFO(ScrnInfoPtr pScrn, CARD16 addr)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 tmp;
-    int i = 0;
-  
-    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr);
-    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
-
-    do {
-	tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL);
-	if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
-	    break;
-	i++;
-    }
-    while (i < 10000);
-    /*while ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0);*/
-
-    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0);
-
-    return INREG(RADEON_TV_HOST_READ_DATA);
-}
-
-/* Get FIFO addresses of horizontal & vertical code timing tables from
- * settings of uv_adr register. 
- */
-static CARD16 RADEONGetHTimingTablesAddr(CARD32 tv_uv_adr)
-{
-    CARD16 hTable;
-
-    switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
-    case 0:
-	hTable = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
-	break;
-    case 1:
-	hTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
-	break;
-    case 2:
-	hTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
-	break;
-    default:
-	/* Of course, this should never happen */
-	hTable = 0;
-	break;
-    }
-    return hTable;
-}
-
-static CARD16 RADEONGetVTimingTablesAddr(CARD32 tv_uv_adr)
-{
-    CARD16 vTable;
-
-    switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
-    case 0:
-	vTable = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
-	break;
-    case 1:
-	vTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
-	break;
-    case 2:
-	vTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
-	break;
-    default:
-	/* Of course, this should never happen */
-	vTable = 0;
-	break;
-    }
-    return vTable;
-}
-
-/* Restore horizontal/vertical timing code tables */
-void RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD16 hTable;
-    CARD16 vTable;
-    CARD32 tmp;
-    unsigned i;
-
-    OUTREG(RADEON_TV_UV_ADR, restore->tv_uv_adr);
-    hTable = RADEONGetHTimingTablesAddr(restore->tv_uv_adr);
-    vTable = RADEONGetVTimingTablesAddr(restore->tv_uv_adr);
-
-    for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, hTable--) {
-	tmp = ((CARD32)restore->h_code_timing[ i ] << 14) | ((CARD32)restore->h_code_timing[ i + 1 ]);
-	RADEONWriteTVFIFO(pScrn, hTable, tmp);
-	if (restore->h_code_timing[ i ] == 0 || restore->h_code_timing[ i + 1 ] == 0)
-	    break;
-    }
-
-    for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, vTable++) {
-	tmp = ((CARD32)restore->v_code_timing[ i + 1 ] << 14) | ((CARD32)restore->v_code_timing[ i ]);
-	RADEONWriteTVFIFO(pScrn, vTable, tmp);
-	if (restore->v_code_timing[ i ] == 0 || restore->v_code_timing[ i + 1 ] == 0)
-	    break;
-    }
-}
-
-/* restore TV PLLs */
-static void RADEONRestoreTVPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-
-    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
-    OUTPLL(pScrn, RADEON_TV_PLL_CNTL, restore->tv_pll_cntl);
-    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
-
-    RADEONWaitPLLLock(pScrn, 200, 800, 135);
-  
-    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
-
-    RADEONWaitPLLLock(pScrn, 300, 160, 27);
-    RADEONWaitPLLLock(pScrn, 200, 800, 135);
-  
-    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~0xf);
-    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
-  
-    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
-    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
-}
-
-/* Restore TV horizontal/vertical settings */
-static void RADEONRestoreTVHVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    OUTREG(RADEON_TV_RGB_CNTL, restore->tv_rgb_cntl);
-
-    OUTREG(RADEON_TV_HTOTAL, restore->tv_htotal);
-    OUTREG(RADEON_TV_HDISP, restore->tv_hdisp);
-    OUTREG(RADEON_TV_HSTART, restore->tv_hstart);
-
-    OUTREG(RADEON_TV_VTOTAL, restore->tv_vtotal);
-    OUTREG(RADEON_TV_VDISP, restore->tv_vdisp);
-
-    OUTREG(RADEON_TV_FTOTAL, restore->tv_ftotal);
-
-    OUTREG(RADEON_TV_VSCALER_CNTL1, restore->tv_vscaler_cntl1);
-    OUTREG(RADEON_TV_VSCALER_CNTL2, restore->tv_vscaler_cntl2);
-
-    OUTREG(RADEON_TV_Y_FALL_CNTL, restore->tv_y_fall_cntl);
-    OUTREG(RADEON_TV_Y_RISE_CNTL, restore->tv_y_rise_cntl);
-    OUTREG(RADEON_TV_Y_SAW_TOOTH_CNTL, restore->tv_y_saw_tooth_cntl);
-}
-
-/* restore TV RESTART registers */
-void RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    OUTREG(RADEON_TV_FRESTART, restore->tv_frestart);
-    OUTREG(RADEON_TV_HRESTART, restore->tv_hrestart);
-    OUTREG(RADEON_TV_VRESTART, restore->tv_vrestart);
-}
-
-/* restore tv standard & output muxes */
-static void RADEONRestoreTVOutputStd(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    OUTREG(RADEON_TV_SYNC_CNTL, restore->tv_sync_cntl);
-  
-    OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl);
-
-    OUTREG(RADEON_TV_MODULATOR_CNTL1, restore->tv_modulator_cntl1);
-    OUTREG(RADEON_TV_MODULATOR_CNTL2, restore->tv_modulator_cntl2);
- 
-    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, restore->tv_pre_dac_mux_cntl);
-
-    OUTREG(RADEON_TV_CRC_CNTL, restore->tv_crc_cntl);
-}
-
-/* Restore TV out regs */
-void RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    ErrorF("Entering Restore TV\n");
-
-    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
-				   | RADEON_TV_ASYNC_RST
-				   | RADEON_CRT_ASYNC_RST
-				   | RADEON_TV_FIFO_ASYNC_RST));
-
-    /* Temporarily turn the TV DAC off */
-    OUTREG(RADEON_TV_DAC_CNTL, ((restore->tv_dac_cntl & ~RADEON_TV_DAC_NBLANK)
-				| RADEON_TV_DAC_BGSLEEP
-				| RADEON_TV_DAC_RDACPD
-				| RADEON_TV_DAC_GDACPD
-				| RADEON_TV_DAC_BDACPD));
-
-    ErrorF("Restore TV PLL\n");
-    RADEONRestoreTVPLLRegisters(pScrn, restore);
-
-    ErrorF("Restore TVHV\n");
-    RADEONRestoreTVHVRegisters(pScrn, restore);
-
-    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
-				   | RADEON_TV_ASYNC_RST
-				   | RADEON_CRT_ASYNC_RST));
-
-    ErrorF("Restore TV Restarts\n");
-    RADEONRestoreTVRestarts(pScrn, restore);
-  
-    ErrorF("Restore Timing Tables\n");
-    RADEONRestoreTVTimingTables(pScrn, restore);
-  
-
-    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
-				   | RADEON_TV_ASYNC_RST));
-
-    ErrorF("Restore TV standard\n");
-    RADEONRestoreTVOutputStd(pScrn, restore);
-
-    OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl);
-
-    OUTREG(RADEON_TV_GAIN_LIMIT_SETTINGS, restore->tv_gain_limit_settings);
-    OUTREG(RADEON_TV_LINEAR_GAIN_SETTINGS, restore->tv_linear_gain_settings);
-
-    OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
-
-    ErrorF("Leaving Restore TV\n");
-}
-
-static void RADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
-{
-    int i = 0;
-
-    /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
-       the cause yet, but this workaround will mask the problem for now.
-       Other chips usually will pass at the very first test, so the
-       workaround shouldn't have any effect on them. */
-    for (i = 0;
-	 (i < 10000 &&
-	  INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
-	 i++);
-}
-
-static void RADEONPLLWriteUpdate(ScrnInfoPtr pScrn)
-{
-    while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
-
-    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
-	    RADEON_PPLL_ATOMIC_UPDATE_W,
-	    ~(RADEON_PPLL_ATOMIC_UPDATE_W));
-}
-
-static void RADEONPLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
-{
-    int i = 0;
-
-    /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
-       the cause yet, but this workaround will mask the problem for now.
-       Other chips usually will pass at the very first test, so the
-       workaround shouldn't have any effect on them. */
-    for (i = 0;
-	 (i < 10000 &&
-	  INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
-	 i++);
-}
-
-static void RADEONPLL2WriteUpdate(ScrnInfoPtr pScrn)
-{
-    while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
-
-    OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
-	    RADEON_P2PLL_ATOMIC_UPDATE_W,
-	    ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
-}
-
-static CARD8 RADEONComputePLLGain(CARD16 reference_freq, CARD16 ref_div,
-				  CARD16 fb_div)
-{
-    unsigned vcoFreq;
-
-    if (!ref_div)
-	return 1;
-
-    vcoFreq = ((unsigned)reference_freq * fb_div) / ref_div;
-
-    /*
-     * This is horribly crude: the VCO frequency range is divided into
-     * 3 parts, each part having a fixed PLL gain value.
-     */
-    if (vcoFreq >= 30000)
-	/*
-	 * [300..max] MHz : 7
-	 */
-	return 7;
-    else if (vcoFreq >= 18000)
-	/*
-	 * [180..300) MHz : 4
-	 */
-        return 4;
-    else
-	/*
-	 * [0..180) MHz : 1
-	 */
-        return 1;
-}
-
-/* Wait for PLLs to lock */
-static void RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests,
-			      unsigned nWaitLoops, unsigned cntThreshold)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 savePLLTest;
-    unsigned i;
-    unsigned j;
-
-    OUTREG(RADEON_TEST_DEBUG_MUX, (INREG(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
-
-    savePLLTest = INPLL(pScrn, RADEON_PLL_TEST_CNTL);
-
-    OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest & ~RADEON_PLL_MASK_READ_B);
-
-    /* XXX: these should probably be OUTPLL to avoid various PLL errata */
-
-    OUTREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
-
-    for (i = 0; i < nTests; i++) {
-	OUTREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
-      
-	for (j = 0; j < nWaitLoops; j++)
-	    if (INREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cntThreshold)
-		break;
-    }
-
-    OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest);
-
-    OUTREG(RADEON_TEST_DEBUG_MUX, INREG(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
-}
-
-/* Write PLL registers */
-void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
-			       RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD8 pllGain;
-
-#if defined(__powerpc__)
-    /* apparently restoring the pll causes a hang??? */
-    if (info->MacModel == RADEON_MAC_IBOOK)
-	return;
-#endif
-
-    pllGain = RADEONComputePLLGain(info->pll.reference_freq,
-				   restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
-				   restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK);
-
-    if (info->IsMobility) {
-        /* A temporal workaround for the occational blanking on certain laptop panels.
-           This appears to related to the PLL divider registers (fail to lock?).
-	   It occurs even when all dividers are the same with their old settings.
-           In this case we really don't need to fiddle with PLL registers.
-           By doing this we can avoid the blanking problem with some panels.
-        */
-        if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) &&
-	    (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) & 
-				     (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) {
-	    OUTREGP(RADEON_CLOCK_CNTL_INDEX,
-		    RADEON_PLL_DIV_SEL,
-		    ~(RADEON_PLL_DIV_SEL));
-	    RADEONPllErrataAfterIndex(info);
-	    return;
-	}
-    }
-
-    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
-	    RADEON_VCLK_SRC_SEL_CPUCLK,
-	    ~(RADEON_VCLK_SRC_SEL_MASK));
-
-    OUTPLLP(pScrn,
-	    RADEON_PPLL_CNTL,
-	    RADEON_PPLL_RESET
-	    | RADEON_PPLL_ATOMIC_UPDATE_EN
-	    | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
-	    | ((CARD32)pllGain << RADEON_PPLL_PVG_SHIFT),
-	    ~(RADEON_PPLL_RESET
-	      | RADEON_PPLL_ATOMIC_UPDATE_EN
-	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
-	      | RADEON_PPLL_PVG_MASK));
-
-    OUTREGP(RADEON_CLOCK_CNTL_INDEX,
-	    RADEON_PLL_DIV_SEL,
-	    ~(RADEON_PLL_DIV_SEL));
-    RADEONPllErrataAfterIndex(info);
-
-    if (IS_R300_VARIANT ||
-	(info->ChipFamily == CHIP_FAMILY_RS300) ||
-	(info->ChipFamily == CHIP_FAMILY_RS400)) {
-	if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
-	    /* When restoring console mode, use saved PPLL_REF_DIV
-	     * setting.
-	     */
-	    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
-		    restore->ppll_ref_div,
-		    0);
-	} else {
-	    /* R300 uses ref_div_acc field as real ref divider */
-	    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
-		    (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
-		    ~R300_PPLL_REF_DIV_ACC_MASK);
-	}
-    } else {
-	OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
-		restore->ppll_ref_div,
-		~RADEON_PPLL_REF_DIV_MASK);
-    }
-
-    OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
-	    restore->ppll_div_3,
-	    ~RADEON_PPLL_FB3_DIV_MASK);
-
-    OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
-	    restore->ppll_div_3,
-	    ~RADEON_PPLL_POST3_DIV_MASK);
-
-    RADEONPLLWriteUpdate(pScrn);
-    RADEONPLLWaitForReadUpdateComplete(pScrn);
-
-    OUTPLL(pScrn, RADEON_HTOTAL_CNTL, restore->htotal_cntl);
-
-    OUTPLLP(pScrn, RADEON_PPLL_CNTL,
-	    0,
-	    ~(RADEON_PPLL_RESET
-	      | RADEON_PPLL_SLEEP
-	      | RADEON_PPLL_ATOMIC_UPDATE_EN
-	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
-		   restore->ppll_ref_div,
-		   restore->ppll_div_3,
-		   (unsigned)restore->htotal_cntl,
-		   INPLL(pScrn, RADEON_PPLL_CNTL));
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Wrote: rd=%d, fd=%d, pd=%d\n",
-		   restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
-		   restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
-		   (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16);
-
-    usleep(50000); /* Let the clock to lock */
-
-    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
-	    RADEON_VCLK_SRC_SEL_PPLLCLK,
-	    ~(RADEON_VCLK_SRC_SEL_MASK));
-
-    /*OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_ecp_cntl);*/
-
-    ErrorF("finished PLL1\n");
-
-}
-
-
-/* Write PLL2 registers */
-void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn,
-				RADEONSavePtr restore)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    CARD8 pllGain;
-
-    pllGain = RADEONComputePLLGain(info->pll.reference_freq,
-                                   restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
-                                   restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK);
-
-
-    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
-	    RADEON_PIX2CLK_SRC_SEL_CPUCLK,
-	    ~(RADEON_PIX2CLK_SRC_SEL_MASK));
-
-    OUTPLLP(pScrn,
-	    RADEON_P2PLL_CNTL,
-	    RADEON_P2PLL_RESET
-	    | RADEON_P2PLL_ATOMIC_UPDATE_EN
-	    | ((CARD32)pllGain << RADEON_P2PLL_PVG_SHIFT),
-	    ~(RADEON_P2PLL_RESET
-	      | RADEON_P2PLL_ATOMIC_UPDATE_EN
-	      | RADEON_P2PLL_PVG_MASK));
-
-
-    OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
-	    restore->p2pll_ref_div,
-	    ~RADEON_P2PLL_REF_DIV_MASK);
-
-    OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
-	    restore->p2pll_div_0,
-	    ~RADEON_P2PLL_FB0_DIV_MASK);
-
-    OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
-	    restore->p2pll_div_0,
-	    ~RADEON_P2PLL_POST0_DIV_MASK);
-
-    RADEONPLL2WriteUpdate(pScrn);
-    RADEONPLL2WaitForReadUpdateComplete(pScrn);
-
-    OUTPLL(pScrn, RADEON_HTOTAL2_CNTL, restore->htotal_cntl2);
-
-    OUTPLLP(pScrn, RADEON_P2PLL_CNTL,
-	    0,
-	    ~(RADEON_P2PLL_RESET
-	      | RADEON_P2PLL_SLEEP
-	      | RADEON_P2PLL_ATOMIC_UPDATE_EN));
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
-		   (unsigned)restore->p2pll_ref_div,
-		   (unsigned)restore->p2pll_div_0,
-		   (unsigned)restore->htotal_cntl2,
-		   INPLL(pScrn, RADEON_P2PLL_CNTL));
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Wrote2: rd=%u, fd=%u, pd=%u\n",
-		   (unsigned)restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
-		   (unsigned)restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK,
-		   (unsigned)((restore->p2pll_div_0 &
-			       RADEON_P2PLL_POST0_DIV_MASK) >>16));
-
-    usleep(5000); /* Let the clock to lock */
-
-    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
-	    RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
-	    ~(RADEON_PIX2CLK_SRC_SEL_MASK));
-
-    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl);
-
-    ErrorF("finished PLL2\n");
-
-}
-
-
 /* restore original surface info (for fb console). */
 static void RADEONRestoreSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr restore)
 {
@@ -4922,289 +4106,6 @@ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
     }
 }
 
-/* Read common registers */
-static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    save->ovr_clr            = INREG(RADEON_OVR_CLR);
-    save->ovr_wid_left_right = INREG(RADEON_OVR_WID_LEFT_RIGHT);
-    save->ovr_wid_top_bottom = INREG(RADEON_OVR_WID_TOP_BOTTOM);
-    save->ov0_scale_cntl     = INREG(RADEON_OV0_SCALE_CNTL);
-    save->subpic_cntl        = INREG(RADEON_SUBPIC_CNTL);
-    save->viph_control       = INREG(RADEON_VIPH_CONTROL);
-    save->i2c_cntl_1         = INREG(RADEON_I2C_CNTL_1);
-    save->gen_int_cntl       = INREG(RADEON_GEN_INT_CNTL);
-    save->cap0_trig_cntl     = INREG(RADEON_CAP0_TRIG_CNTL);
-    save->cap1_trig_cntl     = INREG(RADEON_CAP1_TRIG_CNTL);
-    save->bus_cntl           = INREG(RADEON_BUS_CNTL);
-    save->surface_cntl	     = INREG(RADEON_SURFACE_CNTL);
-    save->grph_buffer_cntl   = INREG(RADEON_GRPH_BUFFER_CNTL);
-    save->grph2_buffer_cntl  = INREG(RADEON_GRPH2_BUFFER_CNTL);
-}
-
-/* Read CRTC registers */
-static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    save->crtc_gen_cntl        = INREG(RADEON_CRTC_GEN_CNTL);
-    save->crtc_ext_cntl        = INREG(RADEON_CRTC_EXT_CNTL);
-    save->crtc_h_total_disp    = INREG(RADEON_CRTC_H_TOTAL_DISP);
-    save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID);
-    save->crtc_v_total_disp    = INREG(RADEON_CRTC_V_TOTAL_DISP);
-    save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID);
-
-    save->fp_h_sync_strt_wid   = INREG(RADEON_FP_H_SYNC_STRT_WID);
-    save->fp_v_sync_strt_wid   = INREG(RADEON_FP_V_SYNC_STRT_WID);
-    save->fp_crtc_h_total_disp = INREG(RADEON_FP_CRTC_H_TOTAL_DISP);
-    save->fp_crtc_v_total_disp = INREG(RADEON_FP_CRTC_V_TOTAL_DISP);
-
-    save->crtc_offset          = INREG(RADEON_CRTC_OFFSET);
-    save->crtc_offset_cntl     = INREG(RADEON_CRTC_OFFSET_CNTL);
-    save->crtc_pitch           = INREG(RADEON_CRTC_PITCH);
-    save->disp_merge_cntl      = INREG(RADEON_DISP_MERGE_CNTL);
-    save->crtc_more_cntl       = INREG(RADEON_CRTC_MORE_CNTL);
-
-    if (IS_R300_VARIANT)
-	save->crtc_tile_x0_y0 =  INREG(R300_CRTC_TILE_X0_Y0);
-
-    if (info->IsDellServer) {
-	save->tv_dac_cntl      = INREG(RADEON_TV_DAC_CNTL);
-	save->dac2_cntl        = INREG(RADEON_DAC_CNTL2);
-	save->disp_hw_debug    = INREG (RADEON_DISP_HW_DEBUG);
-	save->crtc2_gen_cntl   = INREG(RADEON_CRTC2_GEN_CNTL);
-    }
-
-    /* track if the crtc is enabled for text restore */
-    if (save->crtc_ext_cntl & RADEON_CRTC_DISPLAY_DIS)
-	info->crtc_on = FALSE;
-    else
-	info->crtc_on = TRUE;
-
-}
-
-/* Read DAC registers */
-static void RADEONSaveDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    save->dac_cntl              = INREG(RADEON_DAC_CNTL);
-    save->dac2_cntl             = INREG(RADEON_DAC_CNTL2);
-    save->tv_dac_cntl           = INREG(RADEON_TV_DAC_CNTL);
-    save->disp_output_cntl      = INREG(RADEON_DISP_OUTPUT_CNTL);
-    save->disp_tv_out_cntl      = INREG(RADEON_DISP_TV_OUT_CNTL);
-    save->disp_hw_debug         = INREG(RADEON_DISP_HW_DEBUG);
-    save->dac_macro_cntl        = INREG(RADEON_DAC_MACRO_CNTL);
-    save->gpiopad_a             = INREG(RADEON_GPIOPAD_A);
-
-}
-
-static void RADEONSaveBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    save->bios_4_scratch       = INREG(RADEON_BIOS_4_SCRATCH);
-    save->bios_5_scratch       = INREG(RADEON_BIOS_5_SCRATCH);
-    save->bios_6_scratch       = INREG(RADEON_BIOS_6_SCRATCH);
-}
-
-/* Read flat panel registers */
-static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    save->fp_gen_cntl          = INREG(RADEON_FP_GEN_CNTL);
-    save->fp2_gen_cntl          = INREG (RADEON_FP2_GEN_CNTL);
-    save->fp_horz_stretch      = INREG(RADEON_FP_HORZ_STRETCH);
-    save->fp_vert_stretch      = INREG(RADEON_FP_VERT_STRETCH);
-    save->lvds_gen_cntl        = INREG(RADEON_LVDS_GEN_CNTL);
-    save->lvds_pll_cntl        = INREG(RADEON_LVDS_PLL_CNTL);
-    save->tmds_pll_cntl        = INREG(RADEON_TMDS_PLL_CNTL);
-    save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL);
-
-    if (info->ChipFamily == CHIP_FAMILY_RV280) {
-	/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
-	save->tmds_pll_cntl ^= (1 << 22);
-    }
-}
-
-/* Read CRTC2 registers */
-static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    save->crtc2_gen_cntl        = INREG(RADEON_CRTC2_GEN_CNTL);
-    save->crtc2_h_total_disp    = INREG(RADEON_CRTC2_H_TOTAL_DISP);
-    save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
-    save->crtc2_v_total_disp    = INREG(RADEON_CRTC2_V_TOTAL_DISP);
-    save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
-    save->crtc2_offset          = INREG(RADEON_CRTC2_OFFSET);
-    save->crtc2_offset_cntl     = INREG(RADEON_CRTC2_OFFSET_CNTL);
-    save->crtc2_pitch           = INREG(RADEON_CRTC2_PITCH);
-
-    if (IS_R300_VARIANT)
-	save->crtc2_tile_x0_y0 =  INREG(R300_CRTC2_TILE_X0_Y0);
-
-    save->fp_h2_sync_strt_wid   = INREG (RADEON_FP_H2_SYNC_STRT_WID);
-    save->fp_v2_sync_strt_wid   = INREG (RADEON_FP_V2_SYNC_STRT_WID);
-
-    if (info->ChipFamily == CHIP_FAMILY_RS400) {
-	save->rs480_unk_e30 = INREG(RADEON_RS480_UNK_e30);
-	save->rs480_unk_e34 = INREG(RADEON_RS480_UNK_e34);
-	save->rs480_unk_e38 = INREG(RADEON_RS480_UNK_e38);
-	save->rs480_unk_e3c = INREG(RADEON_RS480_UNK_e3c);
-    }
-    
-    save->disp2_merge_cntl      = INREG(RADEON_DISP2_MERGE_CNTL);
-
-    /* track if the crtc is enabled for text restore */
-    if (save->crtc2_gen_cntl & RADEON_CRTC2_DISP_DIS)
-	info->crtc2_on = FALSE;
-    else
-	info->crtc2_on = TRUE;
-
-}
-
-/* Save horizontal/vertical timing code tables */
-static void RADEONSaveTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD16 hTable;
-    CARD16 vTable;
-    CARD32 tmp;
-    unsigned i;
-
-    save->tv_uv_adr = INREG(RADEON_TV_UV_ADR);
-    hTable = RADEONGetHTimingTablesAddr(save->tv_uv_adr);
-    vTable = RADEONGetVTimingTablesAddr(save->tv_uv_adr);
-
-    /*
-     * Reset FIFO arbiter in order to be able to access FIFO RAM
-     */
-
-    OUTREG(RADEON_TV_MASTER_CNTL, (RADEON_TV_ASYNC_RST
-				   | RADEON_CRT_ASYNC_RST
-				   | RADEON_RESTART_PHASE_FIX
-				   | RADEON_CRT_FIFO_CE_EN
-				   | RADEON_TV_FIFO_CE_EN
-				   | RADEON_TV_ON));
-
-    /*OUTREG(RADEON_TV_MASTER_CNTL, save->tv_master_cntl | RADEON_TV_ON);*/
-
-    ErrorF("saveTimingTables: reading timing tables\n");
-
-    for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2) {
-	tmp = RADEONReadTVFIFO(pScrn, hTable--);
-	save->h_code_timing[ i     ] = (CARD16)((tmp >> 14) & 0x3fff);
-	save->h_code_timing[ i + 1 ] = (CARD16)(tmp & 0x3fff);
-
-	if (save->h_code_timing[ i ] == 0 || save->h_code_timing[ i + 1 ] == 0)
-	    break;
-    }
-
-    for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2) {
-	tmp = RADEONReadTVFIFO(pScrn, vTable++);
-	save->v_code_timing[ i     ] = (CARD16)(tmp & 0x3fff);
-	save->v_code_timing[ i + 1 ] = (CARD16)((tmp >> 14) & 0x3fff);
-
-	if (save->v_code_timing[ i ] == 0 || save->v_code_timing[ i + 1 ] == 0)
-	    break;
-    }
-}
-
-/* read TV regs */
-static void RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    ErrorF("Entering TV Save\n");
-
-    save->tv_crc_cntl = INREG(RADEON_TV_CRC_CNTL);
-    save->tv_frestart = INREG(RADEON_TV_FRESTART);
-    save->tv_hrestart = INREG(RADEON_TV_HRESTART);
-    save->tv_vrestart = INREG(RADEON_TV_VRESTART);
-    save->tv_gain_limit_settings = INREG(RADEON_TV_GAIN_LIMIT_SETTINGS);
-    save->tv_hdisp = INREG(RADEON_TV_HDISP);
-    save->tv_hstart = INREG(RADEON_TV_HSTART);
-    save->tv_htotal = INREG(RADEON_TV_HTOTAL);
-    save->tv_linear_gain_settings = INREG(RADEON_TV_LINEAR_GAIN_SETTINGS);
-    save->tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL);
-    save->tv_rgb_cntl = INREG(RADEON_TV_RGB_CNTL);
-    save->tv_modulator_cntl1 = INREG(RADEON_TV_MODULATOR_CNTL1);
-    save->tv_modulator_cntl2 = INREG(RADEON_TV_MODULATOR_CNTL2);
-    save->tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
-    save->tv_sync_cntl = INREG(RADEON_TV_SYNC_CNTL);
-    save->tv_timing_cntl = INREG(RADEON_TV_TIMING_CNTL);
-    save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
-    save->tv_upsamp_and_gain_cntl = INREG(RADEON_TV_UPSAMP_AND_GAIN_CNTL);
-    save->tv_vdisp = INREG(RADEON_TV_VDISP);
-    save->tv_ftotal = INREG(RADEON_TV_FTOTAL);
-    save->tv_vscaler_cntl1 = INREG(RADEON_TV_VSCALER_CNTL1);
-    save->tv_vscaler_cntl2 = INREG(RADEON_TV_VSCALER_CNTL2);
-    save->tv_vtotal = INREG(RADEON_TV_VTOTAL);
-    save->tv_y_fall_cntl = INREG(RADEON_TV_Y_FALL_CNTL);
-    save->tv_y_rise_cntl = INREG(RADEON_TV_Y_RISE_CNTL);
-    save->tv_y_saw_tooth_cntl = INREG(RADEON_TV_Y_SAW_TOOTH_CNTL);
-
-    save->tv_pll_cntl = INPLL(pScrn, RADEON_TV_PLL_CNTL);
-    save->tv_pll_cntl1 = INPLL(pScrn, RADEON_TV_PLL_CNTL1);
-
-    ErrorF("Save TV timing tables\n");
-
-    RADEONSaveTVTimingTables(pScrn, save);
-
-    ErrorF("TV Save done\n");
-}
-
-/* Read PLL registers */
-static void RADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV);
-    save->ppll_div_3   = INPLL(pScrn, RADEON_PPLL_DIV_3);
-    save->htotal_cntl  = INPLL(pScrn, RADEON_HTOTAL_CNTL);
-    save->vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Read: 0x%08x 0x%08x 0x%08x\n",
-		   save->ppll_ref_div,
-		   save->ppll_div_3,
-		   (unsigned)save->htotal_cntl);
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Read: rd=%d, fd=%d, pd=%d\n",
-		   save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
-		   save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
-		   (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16);
-}
-
-/* Read PLL registers */
-static void RADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    save->p2pll_ref_div = INPLL(pScrn, RADEON_P2PLL_REF_DIV);
-    save->p2pll_div_0   = INPLL(pScrn, RADEON_P2PLL_DIV_0);
-    save->htotal_cntl2  = INPLL(pScrn, RADEON_HTOTAL2_CNTL);
-    save->pixclks_cntl  = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Read: 0x%08x 0x%08x 0x%08x\n",
-		   (unsigned)save->p2pll_ref_div,
-		   (unsigned)save->p2pll_div_0,
-		   (unsigned)save->htotal_cntl2);
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Read: rd=%u, fd=%u, pd=%u\n",
-		   (unsigned)(save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK),
-		   (unsigned)(save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK),
-		   (unsigned)((save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK)
-			      >> 16));
-}
 
 #if 0
 /* Read palette data */
@@ -5228,7 +4129,8 @@ static void RADEONSavePalette(ScrnInfoPtr pScrn, RADEONSavePtr save)
 }
 #endif
 
-void avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
+void
+avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
@@ -5382,7 +4284,8 @@ void avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
 
 }
 
-void avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+void
+avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
diff --git a/src/radeon_tv.c b/src/radeon_tv.c
index 5e9a9c8..9959295 100644
--- a/src/radeon_tv.c
+++ b/src/radeon_tv.c
@@ -180,6 +180,401 @@ static long SLOPE_value[5] = { 1, 2, 2, 4, 8 };
 static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 };
 
 
+static void
+RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests,
+		  unsigned nWaitLoops, unsigned cntThreshold)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 savePLLTest;
+    unsigned i;
+    unsigned j;
+
+    OUTREG(RADEON_TEST_DEBUG_MUX, (INREG(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
+
+    savePLLTest = INPLL(pScrn, RADEON_PLL_TEST_CNTL);
+
+    OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest & ~RADEON_PLL_MASK_READ_B);
+
+    /* XXX: these should probably be OUTPLL to avoid various PLL errata */
+
+    OUTREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
+
+    for (i = 0; i < nTests; i++) {
+	OUTREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
+      
+	for (j = 0; j < nWaitLoops; j++)
+	    if (INREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cntThreshold)
+		break;
+    }
+
+    OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest);
+
+    OUTREG(RADEON_TEST_DEBUG_MUX, INREG(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
+}
+
+/* Write to TV FIFO RAM */
+static void
+RADEONWriteTVFIFO(ScrnInfoPtr pScrn, CARD16 addr,
+		  CARD32 value)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 tmp;
+    int i = 0;
+
+    OUTREG(RADEON_TV_HOST_WRITE_DATA, value);
+
+    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr);
+    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
+
+    do {
+	tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL);
+	if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
+	    break;
+	i++;
+    }
+    while (i < 10000);
+    /*while ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0);*/
+
+    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0);
+}
+
+/* Read from TV FIFO RAM */
+static CARD32
+RADEONReadTVFIFO(ScrnInfoPtr pScrn, CARD16 addr)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 tmp;
+    int i = 0;
+  
+    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr);
+    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
+
+    do {
+	tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL);
+	if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
+	    break;
+	i++;
+    }
+    while (i < 10000);
+    /*while ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0);*/
+
+    OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0);
+
+    return INREG(RADEON_TV_HOST_READ_DATA);
+}
+
+/* Get FIFO addresses of horizontal & vertical code timing tables from
+ * settings of uv_adr register. 
+ */
+static CARD16
+RADEONGetHTimingTablesAddr(CARD32 tv_uv_adr)
+{
+    CARD16 hTable;
+
+    switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
+    case 0:
+	hTable = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
+	break;
+    case 1:
+	hTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
+	break;
+    case 2:
+	hTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
+	break;
+    default:
+	/* Of course, this should never happen */
+	hTable = 0;
+	break;
+    }
+    return hTable;
+}
+
+static CARD16
+RADEONGetVTimingTablesAddr(CARD32 tv_uv_adr)
+{
+    CARD16 vTable;
+
+    switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
+    case 0:
+	vTable = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
+	break;
+    case 1:
+	vTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
+	break;
+    case 2:
+	vTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
+	break;
+    default:
+	/* Of course, this should never happen */
+	vTable = 0;
+	break;
+    }
+    return vTable;
+}
+
+/* Restore horizontal/vertical timing code tables */
+static void
+RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD16 hTable;
+    CARD16 vTable;
+    CARD32 tmp;
+    unsigned i;
+
+    OUTREG(RADEON_TV_UV_ADR, restore->tv_uv_adr);
+    hTable = RADEONGetHTimingTablesAddr(restore->tv_uv_adr);
+    vTable = RADEONGetVTimingTablesAddr(restore->tv_uv_adr);
+
+    for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, hTable--) {
+	tmp = ((CARD32)restore->h_code_timing[ i ] << 14) | ((CARD32)restore->h_code_timing[ i + 1 ]);
+	RADEONWriteTVFIFO(pScrn, hTable, tmp);
+	if (restore->h_code_timing[ i ] == 0 || restore->h_code_timing[ i + 1 ] == 0)
+	    break;
+    }
+
+    for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, vTable++) {
+	tmp = ((CARD32)restore->v_code_timing[ i + 1 ] << 14) | ((CARD32)restore->v_code_timing[ i ]);
+	RADEONWriteTVFIFO(pScrn, vTable, tmp);
+	if (restore->v_code_timing[ i ] == 0 || restore->v_code_timing[ i + 1 ] == 0)
+	    break;
+    }
+}
+
+/* restore TV PLLs */
+static void
+RADEONRestoreTVPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+
+    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
+    OUTPLL(pScrn, RADEON_TV_PLL_CNTL, restore->tv_pll_cntl);
+    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
+
+    RADEONWaitPLLLock(pScrn, 200, 800, 135);
+  
+    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
+
+    RADEONWaitPLLLock(pScrn, 300, 160, 27);
+    RADEONWaitPLLLock(pScrn, 200, 800, 135);
+  
+    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~0xf);
+    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
+  
+    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
+    OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
+}
+
+/* Restore TV horizontal/vertical settings */
+static void
+RADEONRestoreTVHVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    OUTREG(RADEON_TV_RGB_CNTL, restore->tv_rgb_cntl);
+
+    OUTREG(RADEON_TV_HTOTAL, restore->tv_htotal);
+    OUTREG(RADEON_TV_HDISP, restore->tv_hdisp);
+    OUTREG(RADEON_TV_HSTART, restore->tv_hstart);
+
+    OUTREG(RADEON_TV_VTOTAL, restore->tv_vtotal);
+    OUTREG(RADEON_TV_VDISP, restore->tv_vdisp);
+
+    OUTREG(RADEON_TV_FTOTAL, restore->tv_ftotal);
+
+    OUTREG(RADEON_TV_VSCALER_CNTL1, restore->tv_vscaler_cntl1);
+    OUTREG(RADEON_TV_VSCALER_CNTL2, restore->tv_vscaler_cntl2);
+
+    OUTREG(RADEON_TV_Y_FALL_CNTL, restore->tv_y_fall_cntl);
+    OUTREG(RADEON_TV_Y_RISE_CNTL, restore->tv_y_rise_cntl);
+    OUTREG(RADEON_TV_Y_SAW_TOOTH_CNTL, restore->tv_y_saw_tooth_cntl);
+}
+
+/* restore TV RESTART registers */
+static void
+RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    OUTREG(RADEON_TV_FRESTART, restore->tv_frestart);
+    OUTREG(RADEON_TV_HRESTART, restore->tv_hrestart);
+    OUTREG(RADEON_TV_VRESTART, restore->tv_vrestart);
+}
+
+/* restore tv standard & output muxes */
+static void
+RADEONRestoreTVOutputStd(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    OUTREG(RADEON_TV_SYNC_CNTL, restore->tv_sync_cntl);
+  
+    OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl);
+
+    OUTREG(RADEON_TV_MODULATOR_CNTL1, restore->tv_modulator_cntl1);
+    OUTREG(RADEON_TV_MODULATOR_CNTL2, restore->tv_modulator_cntl2);
+ 
+    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, restore->tv_pre_dac_mux_cntl);
+
+    OUTREG(RADEON_TV_CRC_CNTL, restore->tv_crc_cntl);
+}
+
+/* Restore TV out regs */
+void
+RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    ErrorF("Entering Restore TV\n");
+
+    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
+				   | RADEON_TV_ASYNC_RST
+				   | RADEON_CRT_ASYNC_RST
+				   | RADEON_TV_FIFO_ASYNC_RST));
+
+    /* Temporarily turn the TV DAC off */
+    OUTREG(RADEON_TV_DAC_CNTL, ((restore->tv_dac_cntl & ~RADEON_TV_DAC_NBLANK)
+				| RADEON_TV_DAC_BGSLEEP
+				| RADEON_TV_DAC_RDACPD
+				| RADEON_TV_DAC_GDACPD
+				| RADEON_TV_DAC_BDACPD));
+
+    ErrorF("Restore TV PLL\n");
+    RADEONRestoreTVPLLRegisters(pScrn, restore);
+
+    ErrorF("Restore TVHV\n");
+    RADEONRestoreTVHVRegisters(pScrn, restore);
+
+    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
+				   | RADEON_TV_ASYNC_RST
+				   | RADEON_CRT_ASYNC_RST));
+
+    ErrorF("Restore TV Restarts\n");
+    RADEONRestoreTVRestarts(pScrn, restore);
+  
+    ErrorF("Restore Timing Tables\n");
+    RADEONRestoreTVTimingTables(pScrn, restore);
+  
+
+    OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl
+				   | RADEON_TV_ASYNC_RST));
+
+    ErrorF("Restore TV standard\n");
+    RADEONRestoreTVOutputStd(pScrn, restore);
+
+    OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl);
+
+    OUTREG(RADEON_TV_GAIN_LIMIT_SETTINGS, restore->tv_gain_limit_settings);
+    OUTREG(RADEON_TV_LINEAR_GAIN_SETTINGS, restore->tv_linear_gain_settings);
+
+    OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
+
+    ErrorF("Leaving Restore TV\n");
+}
+
+/* Save horizontal/vertical timing code tables */
+static void
+RADEONSaveTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD16 hTable;
+    CARD16 vTable;
+    CARD32 tmp;
+    unsigned i;
+
+    save->tv_uv_adr = INREG(RADEON_TV_UV_ADR);
+    hTable = RADEONGetHTimingTablesAddr(save->tv_uv_adr);
+    vTable = RADEONGetVTimingTablesAddr(save->tv_uv_adr);
+
+    /*
+     * Reset FIFO arbiter in order to be able to access FIFO RAM
+     */
+
+    OUTREG(RADEON_TV_MASTER_CNTL, (RADEON_TV_ASYNC_RST
+				   | RADEON_CRT_ASYNC_RST
+				   | RADEON_RESTART_PHASE_FIX
+				   | RADEON_CRT_FIFO_CE_EN
+				   | RADEON_TV_FIFO_CE_EN
+				   | RADEON_TV_ON));
+
+    /*OUTREG(RADEON_TV_MASTER_CNTL, save->tv_master_cntl | RADEON_TV_ON);*/
+
+    ErrorF("saveTimingTables: reading timing tables\n");
+
+    for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2) {
+	tmp = RADEONReadTVFIFO(pScrn, hTable--);
+	save->h_code_timing[ i     ] = (CARD16)((tmp >> 14) & 0x3fff);
+	save->h_code_timing[ i + 1 ] = (CARD16)(tmp & 0x3fff);
+
+	if (save->h_code_timing[ i ] == 0 || save->h_code_timing[ i + 1 ] == 0)
+	    break;
+    }
+
+    for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2) {
+	tmp = RADEONReadTVFIFO(pScrn, vTable++);
+	save->v_code_timing[ i     ] = (CARD16)(tmp & 0x3fff);
+	save->v_code_timing[ i + 1 ] = (CARD16)((tmp >> 14) & 0x3fff);
+
+	if (save->v_code_timing[ i ] == 0 || save->v_code_timing[ i + 1 ] == 0)
+	    break;
+    }
+}
+
+/* read TV regs */
+void
+RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    ErrorF("Entering TV Save\n");
+
+    save->tv_crc_cntl = INREG(RADEON_TV_CRC_CNTL);
+    save->tv_frestart = INREG(RADEON_TV_FRESTART);
+    save->tv_hrestart = INREG(RADEON_TV_HRESTART);
+    save->tv_vrestart = INREG(RADEON_TV_VRESTART);
+    save->tv_gain_limit_settings = INREG(RADEON_TV_GAIN_LIMIT_SETTINGS);
+    save->tv_hdisp = INREG(RADEON_TV_HDISP);
+    save->tv_hstart = INREG(RADEON_TV_HSTART);
+    save->tv_htotal = INREG(RADEON_TV_HTOTAL);
+    save->tv_linear_gain_settings = INREG(RADEON_TV_LINEAR_GAIN_SETTINGS);
+    save->tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL);
+    save->tv_rgb_cntl = INREG(RADEON_TV_RGB_CNTL);
+    save->tv_modulator_cntl1 = INREG(RADEON_TV_MODULATOR_CNTL1);
+    save->tv_modulator_cntl2 = INREG(RADEON_TV_MODULATOR_CNTL2);
+    save->tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
+    save->tv_sync_cntl = INREG(RADEON_TV_SYNC_CNTL);
+    save->tv_timing_cntl = INREG(RADEON_TV_TIMING_CNTL);
+    save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+    save->tv_upsamp_and_gain_cntl = INREG(RADEON_TV_UPSAMP_AND_GAIN_CNTL);
+    save->tv_vdisp = INREG(RADEON_TV_VDISP);
+    save->tv_ftotal = INREG(RADEON_TV_FTOTAL);
+    save->tv_vscaler_cntl1 = INREG(RADEON_TV_VSCALER_CNTL1);
+    save->tv_vscaler_cntl2 = INREG(RADEON_TV_VSCALER_CNTL2);
+    save->tv_vtotal = INREG(RADEON_TV_VTOTAL);
+    save->tv_y_fall_cntl = INREG(RADEON_TV_Y_FALL_CNTL);
+    save->tv_y_rise_cntl = INREG(RADEON_TV_Y_RISE_CNTL);
+    save->tv_y_saw_tooth_cntl = INREG(RADEON_TV_Y_SAW_TOOTH_CNTL);
+
+    save->tv_pll_cntl = INPLL(pScrn, RADEON_TV_PLL_CNTL);
+    save->tv_pll_cntl1 = INPLL(pScrn, RADEON_TV_PLL_CNTL1);
+
+    ErrorF("Save TV timing tables\n");
+
+    RADEONSaveTVTimingTables(pScrn, save);
+
+    ErrorF("TV Save done\n");
+}
+
+
 /* Compute F,V,H restarts from default restart position and hPos & vPos
  * Return TRUE when code timing table was changed
  */
commit 910773d3a6c717f9d4762ea7b9ee6c3ae061781e
Author: Alex Deucher <alex at botch2.(none)>
Date:   Fri Dec 21 15:53:15 2007 -0500

    RADEON: more re-org.  move XAA Mem init to radeon_accel.c

diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 5bf03f5..8b2f167 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -915,3 +915,340 @@ void RADEONInit3DEngine(ScrnInfoPtr pScrn)
     info->XInited3D = TRUE;
 }
 
+#ifdef USE_XAA
+#ifdef XF86DRI
+Bool
+RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen)
+{
+    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    int            cpp = info->CurrentLayout.pixel_bytes;
+    int            depthCpp = (info->depthBits - 8) / 4;
+    int            width_bytes = pScrn->displayWidth * cpp;
+    int            bufferSize;
+    int            depthSize;
+    int            l;
+    int            scanlines;
+    int            texsizerequest;
+    BoxRec         MemBox;
+    FBAreaPtr      fbarea;
+
+    info->frontOffset = 0;
+    info->frontPitch = pScrn->displayWidth;
+    info->backPitch = pScrn->displayWidth;
+
+    /* make sure we use 16 line alignment for tiling (8 might be enough).
+     * Might need that for non-XF86DRI too?
+     */
+    if (info->allowColorTiling) {
+	bufferSize = (((pScrn->virtualY + 15) & ~15) * width_bytes
+		      + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN;
+    } else {
+        bufferSize = (pScrn->virtualY * width_bytes
+		      + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN;
+    }
+
+    /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels,
+     * which is always the case if color tiling is used due to color pitch
+     * but not necessarily otherwise, and its height a multiple of 16 lines.
+     */
+    info->depthPitch = (pScrn->displayWidth + 31) & ~31;
+    depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch
+		  * depthCpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN);
+
+    switch (info->CPMode) {
+    case RADEON_DEFAULT_CP_PIO_MODE:
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n");
+	break;
+    case RADEON_DEFAULT_CP_BM_MODE:
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n");
+	break;
+    default:
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n");
+	break;
+    }
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Using %d MB GART aperture\n", info->gartSize);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Using %d MB for the ring buffer\n", info->ringSize);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Using %d MB for vertex/indirect buffers\n", info->bufSize);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Using %d MB for GART textures\n", info->gartTexSize);
+
+    /* Try for front, back, depth, and three framebuffers worth of
+     * pixmap cache.  Should be enough for a fullscreen background
+     * image plus some leftovers.
+     * If the FBTexPercent option was used, try to achieve that percentage instead,
+     * but still have at least one pixmap buffer (get problems with xvideo/render
+     * otherwise probably), and never reserve more than 3 offscreen buffers as it's
+     * probably useless for XAA.
+     */
+    if (info->textureSize >= 0) {
+	texsizerequest = ((int)info->FbMapSize - 2 * bufferSize - depthSize
+			 - 2 * width_bytes - 16384 - info->FbSecureSize)
+	/* first divide, then multiply or we'll get an overflow (been there...) */
+			 / 100 * info->textureSize;
+    }
+    else {
+	texsizerequest = (int)info->FbMapSize / 2;
+    }
+    info->textureSize = info->FbMapSize - info->FbSecureSize - 5 * bufferSize - depthSize;
+
+    /* If that gives us less than the requested memory, let's
+     * be greedy and grab some more.  Sorry, I care more about 3D
+     * performance than playing nicely, and you'll get around a full
+     * framebuffer's worth of pixmap cache anyway.
+     */
+    if (info->textureSize < texsizerequest) {
+        info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize;
+    }
+    if (info->textureSize < texsizerequest) {
+        info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize;
+    }
+
+    /* If there's still no space for textures, try without pixmap cache, but
+     * never use the reserved space, the space hw cursor and PCIGART table might
+     * use.
+     */
+    if (info->textureSize < 0) {
+	info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize
+	                    - 2 * width_bytes - 16384 - info->FbSecureSize;
+    }
+
+    /* Check to see if there is more room available after the 8192nd
+     * scanline for textures
+     */
+    /* FIXME: what's this good for? condition is pretty much impossible to meet */
+    if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize
+	> info->textureSize) {
+	info->textureSize =
+		info->FbMapSize - 8192*width_bytes - bufferSize - depthSize;
+    }
+
+    /* If backbuffer is disabled, don't allocate memory for it */
+    if (info->noBackBuffer) {
+	info->textureSize += bufferSize;
+    }
+
+    /* RADEON_BUFFER_ALIGN is not sufficient for backbuffer!
+       At least for pageflip + color tiling, need to make sure it's 16 scanlines aligned,
+       otherwise the copy-from-front-to-back will fail (width_bytes * 16 will also guarantee
+       it's still 4kb aligned for tiled case). Need to round up offset (might get into cursor
+       area otherwise).
+       This might cause some space at the end of the video memory to be unused, since it
+       can't be used (?) due to that log_tex_granularity thing???
+       Could use different copyscreentoscreen function for the pageflip copies
+       (which would use different src and dst offsets) to avoid this. */   
+    if (info->allowColorTiling && !info->noBackBuffer) {
+	info->textureSize = info->FbMapSize - ((info->FbMapSize - info->textureSize +
+			  width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes * 16);
+    }
+    if (info->textureSize > 0) {
+	l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS);
+	if (l < RADEON_LOG_TEX_GRANULARITY)
+	    l = RADEON_LOG_TEX_GRANULARITY;
+	/* Round the texture size up to the nearest whole number of
+	 * texture regions.  Again, be greedy about this, don't
+	 * round down.
+	 */
+	info->log2TexGran = l;
+	info->textureSize = (info->textureSize >> l) << l;
+    } else {
+	info->textureSize = 0;
+    }
+
+    /* Set a minimum usable local texture heap size.  This will fit
+     * two 256x256x32bpp textures.
+     */
+    if (info->textureSize < 512 * 1024) {
+	info->textureOffset = 0;
+	info->textureSize = 0;
+    }
+
+    if (info->allowColorTiling && !info->noBackBuffer) {
+	info->textureOffset = ((info->FbMapSize - info->textureSize) /
+			       (width_bytes * 16)) * (width_bytes * 16);
+    }
+    else {
+	/* Reserve space for textures */
+	info->textureOffset = ((info->FbMapSize - info->textureSize +
+				RADEON_BUFFER_ALIGN) &
+			       ~(CARD32)RADEON_BUFFER_ALIGN);
+    }
+
+    /* Reserve space for the shared depth
+     * buffer.
+     */
+    info->depthOffset = ((info->textureOffset - depthSize +
+			  RADEON_BUFFER_ALIGN) &
+			 ~(CARD32)RADEON_BUFFER_ALIGN);
+
+    /* Reserve space for the shared back buffer */
+    if (info->noBackBuffer) {
+       info->backOffset = info->depthOffset;
+    } else {
+       info->backOffset = ((info->depthOffset - bufferSize +
+			    RADEON_BUFFER_ALIGN) &
+			   ~(CARD32)RADEON_BUFFER_ALIGN);
+    }
+
+    info->backY = info->backOffset / width_bytes;
+    info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp;
+
+    scanlines = (info->FbMapSize-info->FbSecureSize) / width_bytes;
+    if (scanlines > 8191)
+	scanlines = 8191;
+
+    MemBox.x1 = 0;
+    MemBox.y1 = 0;
+    MemBox.x2 = pScrn->displayWidth;
+    MemBox.y2 = scanlines;
+
+    if (!xf86InitFBManager(pScreen, &MemBox)) {
+        xf86DrvMsg(scrnIndex, X_ERROR,
+		   "Memory manager initialization to "
+		   "(%d,%d) (%d,%d) failed\n",
+		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+	return FALSE;
+    } else {
+	int  width, height;
+
+	xf86DrvMsg(scrnIndex, X_INFO,
+		   "Memory manager initialized to (%d,%d) (%d,%d)\n",
+		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+	/* why oh why can't we just request modes which are guaranteed to be 16 lines
+	   aligned... sigh */
+	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+						pScrn->displayWidth,
+						info->allowColorTiling ? 
+						((pScrn->virtualY + 15) & ~15)
+						- pScrn->virtualY + 2 : 2,
+						0, NULL, NULL,
+						NULL))) {
+	    xf86DrvMsg(scrnIndex, X_INFO,
+		       "Reserved area from (%d,%d) to (%d,%d)\n",
+		       fbarea->box.x1, fbarea->box.y1,
+		       fbarea->box.x2, fbarea->box.y2);
+	} else {
+	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
+	}
+
+	RADEONDRIAllocatePCIGARTTable(pScreen);
+
+	if (xf86QueryLargestOffscreenArea(pScreen, &width,
+					  &height, 0, 0, 0)) {
+	    xf86DrvMsg(scrnIndex, X_INFO,
+		       "Largest offscreen area available: %d x %d\n",
+		       width, height);
+
+	    /* Lines in offscreen area needed for depth buffer and
+	     * textures
+	     */
+	    info->depthTexLines = (scanlines
+				   - info->depthOffset / width_bytes);
+	    info->backLines	    = (scanlines
+				       - info->backOffset / width_bytes
+				       - info->depthTexLines);
+	    info->backArea	    = NULL;
+	} else {
+	    xf86DrvMsg(scrnIndex, X_ERROR,
+		       "Unable to determine largest offscreen area "
+		       "available\n");
+	    return FALSE;
+	}
+    }
+
+    xf86DrvMsg(scrnIndex, X_INFO,
+	       "Will use front buffer at offset 0x%x\n",
+	       info->frontOffset);
+
+    xf86DrvMsg(scrnIndex, X_INFO,
+	       "Will use back buffer at offset 0x%x\n",
+	       info->backOffset);
+    xf86DrvMsg(scrnIndex, X_INFO,
+	       "Will use depth buffer at offset 0x%x\n",
+	       info->depthOffset);
+    if (info->cardType==CARD_PCIE)
+    	xf86DrvMsg(scrnIndex, X_INFO,
+	           "Will use %d kb for PCI GART table at offset 0x%x\n",
+		   info->pciGartSize/1024, (unsigned)info->pciGartOffset);
+    xf86DrvMsg(scrnIndex, X_INFO,
+	       "Will use %d kb for textures at offset 0x%x\n",
+	       info->textureSize/1024, info->textureOffset);
+
+    info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) |
+			      ((info->frontOffset + info->fbLocation) >> 10));
+
+    info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) |
+			     ((info->backOffset + info->fbLocation) >> 10));
+
+    info->depthPitchOffset = (((info->depthPitch * depthCpp / 64) << 22) |
+			      ((info->depthOffset + info->fbLocation) >> 10));
+    return TRUE;
+}
+#endif /* XF86DRI */
+
+Bool
+RADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen)
+{
+    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    BoxRec         MemBox;
+    int            y2;
+
+    int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+
+    MemBox.x1 = 0;
+    MemBox.y1 = 0;
+    MemBox.x2 = pScrn->displayWidth;
+    y2 = info->FbMapSize / width_bytes;
+    if (y2 >= 32768)
+	y2 = 32767; /* because MemBox.y2 is signed short */
+    MemBox.y2 = y2;
+    
+    /* The acceleration engine uses 14 bit
+     * signed coordinates, so we can't have any
+     * drawable caches beyond this region.
+     */
+    if (MemBox.y2 > 8191)
+	MemBox.y2 = 8191;
+
+    if (!xf86InitFBManager(pScreen, &MemBox)) {
+	xf86DrvMsg(scrnIndex, X_ERROR,
+		   "Memory manager initialization to "
+		   "(%d,%d) (%d,%d) failed\n",
+		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+	return FALSE;
+    } else {
+	int       width, height;
+	FBAreaPtr fbarea;
+
+	xf86DrvMsg(scrnIndex, X_INFO,
+		   "Memory manager initialized to (%d,%d) (%d,%d)\n",
+		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+						pScrn->displayWidth,
+						info->allowColorTiling ? 
+						((pScrn->virtualY + 15) & ~15)
+						- pScrn->virtualY + 2 : 2,
+						0, NULL, NULL,
+						NULL))) {
+	    xf86DrvMsg(scrnIndex, X_INFO,
+		       "Reserved area from (%d,%d) to (%d,%d)\n",
+		       fbarea->box.x1, fbarea->box.y1,
+		       fbarea->box.x2, fbarea->box.y2);
+	} else {
+	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
+	}
+	if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
+					      0, 0, 0)) {
+	    xf86DrvMsg(scrnIndex, X_INFO,
+		       "Largest offscreen area available: %d x %d\n",
+		       width, height);
+	}
+	return TRUE;
+    }    
+}
+#endif /* USE_XAA */
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 85cfe88..7b9cd85 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -2955,11 +2955,6 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
       goto fail;
    }
 
-    /* Free the video bios (if applicable) */
-    //if (info->VBIOS) {
-    //xfree(info->VBIOS);
-    //info->VBIOS = NULL;
-    //}
 
 				/* Free int10 info */
     if (pInt10)
@@ -3108,343 +3103,6 @@ static void RADEONBlockHandler(int i, pointer blockData,
 #endif
 }
 
-
-#ifdef USE_XAA
-#ifdef XF86DRI
-Bool RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen)
-{
-    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
-    RADEONInfoPtr  info  = RADEONPTR(pScrn);
-    int            cpp = info->CurrentLayout.pixel_bytes;
-    int            depthCpp = (info->depthBits - 8) / 4;
-    int            width_bytes = pScrn->displayWidth * cpp;
-    int            bufferSize;
-    int            depthSize;
-    int            l;
-    int            scanlines;
-    int            texsizerequest;
-    BoxRec         MemBox;
-    FBAreaPtr      fbarea;
-
-    info->frontOffset = 0;
-    info->frontPitch = pScrn->displayWidth;
-    info->backPitch = pScrn->displayWidth;
-
-    /* make sure we use 16 line alignment for tiling (8 might be enough).
-     * Might need that for non-XF86DRI too?
-     */
-    if (info->allowColorTiling) {
-	bufferSize = (((pScrn->virtualY + 15) & ~15) * width_bytes
-		      + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN;
-    } else {
-        bufferSize = (pScrn->virtualY * width_bytes
-		      + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN;
-    }
-
-    /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels,
-     * which is always the case if color tiling is used due to color pitch
-     * but not necessarily otherwise, and its height a multiple of 16 lines.
-     */
-    info->depthPitch = (pScrn->displayWidth + 31) & ~31;
-    depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch
-		  * depthCpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN);
-
-    switch (info->CPMode) {
-    case RADEON_DEFAULT_CP_PIO_MODE:
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n");
-	break;
-    case RADEON_DEFAULT_CP_BM_MODE:
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n");
-	break;
-    default:
-        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n");
-	break;
-    }
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Using %d MB GART aperture\n", info->gartSize);
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Using %d MB for the ring buffer\n", info->ringSize);
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Using %d MB for vertex/indirect buffers\n", info->bufSize);
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Using %d MB for GART textures\n", info->gartTexSize);
-
-    /* Try for front, back, depth, and three framebuffers worth of
-     * pixmap cache.  Should be enough for a fullscreen background
-     * image plus some leftovers.
-     * If the FBTexPercent option was used, try to achieve that percentage instead,
-     * but still have at least one pixmap buffer (get problems with xvideo/render
-     * otherwise probably), and never reserve more than 3 offscreen buffers as it's
-     * probably useless for XAA.
-     */
-    if (info->textureSize >= 0) {
-	texsizerequest = ((int)info->FbMapSize - 2 * bufferSize - depthSize
-			 - 2 * width_bytes - 16384 - info->FbSecureSize)
-	/* first divide, then multiply or we'll get an overflow (been there...) */
-			 / 100 * info->textureSize;
-    }
-    else {
-	texsizerequest = (int)info->FbMapSize / 2;
-    }
-    info->textureSize = info->FbMapSize - info->FbSecureSize - 5 * bufferSize - depthSize;
-
-    /* If that gives us less than the requested memory, let's
-     * be greedy and grab some more.  Sorry, I care more about 3D
-     * performance than playing nicely, and you'll get around a full
-     * framebuffer's worth of pixmap cache anyway.
-     */
-    if (info->textureSize < texsizerequest) {
-        info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize;
-    }
-    if (info->textureSize < texsizerequest) {
-        info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize;
-    }
-
-    /* If there's still no space for textures, try without pixmap cache, but
-     * never use the reserved space, the space hw cursor and PCIGART table might
-     * use.
-     */
-    if (info->textureSize < 0) {
-	info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize
-	                    - 2 * width_bytes - 16384 - info->FbSecureSize;
-    }
-
-    /* Check to see if there is more room available after the 8192nd
-     * scanline for textures
-     */
-    /* FIXME: what's this good for? condition is pretty much impossible to meet */
-    if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize
-	> info->textureSize) {
-	info->textureSize =
-		info->FbMapSize - 8192*width_bytes - bufferSize - depthSize;
-    }
-
-    /* If backbuffer is disabled, don't allocate memory for it */
-    if (info->noBackBuffer) {
-	info->textureSize += bufferSize;
-    }
-
-    /* RADEON_BUFFER_ALIGN is not sufficient for backbuffer!
-       At least for pageflip + color tiling, need to make sure it's 16 scanlines aligned,
-       otherwise the copy-from-front-to-back will fail (width_bytes * 16 will also guarantee
-       it's still 4kb aligned for tiled case). Need to round up offset (might get into cursor
-       area otherwise).
-       This might cause some space at the end of the video memory to be unused, since it
-       can't be used (?) due to that log_tex_granularity thing???
-       Could use different copyscreentoscreen function for the pageflip copies
-       (which would use different src and dst offsets) to avoid this. */   
-    if (info->allowColorTiling && !info->noBackBuffer) {
-	info->textureSize = info->FbMapSize - ((info->FbMapSize - info->textureSize +
-			  width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes * 16);
-    }
-    if (info->textureSize > 0) {
-	l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS);
-	if (l < RADEON_LOG_TEX_GRANULARITY)
-	    l = RADEON_LOG_TEX_GRANULARITY;
-	/* Round the texture size up to the nearest whole number of
-	 * texture regions.  Again, be greedy about this, don't
-	 * round down.
-	 */
-	info->log2TexGran = l;
-	info->textureSize = (info->textureSize >> l) << l;
-    } else {
-	info->textureSize = 0;
-    }
-
-    /* Set a minimum usable local texture heap size.  This will fit
-     * two 256x256x32bpp textures.
-     */
-    if (info->textureSize < 512 * 1024) {
-	info->textureOffset = 0;
-	info->textureSize = 0;
-    }
-
-    if (info->allowColorTiling && !info->noBackBuffer) {
-	info->textureOffset = ((info->FbMapSize - info->textureSize) /
-			       (width_bytes * 16)) * (width_bytes * 16);
-    }
-    else {
-	/* Reserve space for textures */
-	info->textureOffset = ((info->FbMapSize - info->textureSize +
-				RADEON_BUFFER_ALIGN) &
-			       ~(CARD32)RADEON_BUFFER_ALIGN);
-    }
-
-    /* Reserve space for the shared depth
-     * buffer.
-     */
-    info->depthOffset = ((info->textureOffset - depthSize +
-			  RADEON_BUFFER_ALIGN) &
-			 ~(CARD32)RADEON_BUFFER_ALIGN);
-
-    /* Reserve space for the shared back buffer */
-    if (info->noBackBuffer) {
-       info->backOffset = info->depthOffset;
-    } else {
-       info->backOffset = ((info->depthOffset - bufferSize +
-			    RADEON_BUFFER_ALIGN) &
-			   ~(CARD32)RADEON_BUFFER_ALIGN);
-    }
-
-    info->backY = info->backOffset / width_bytes;
-    info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp;
-
-    scanlines = (info->FbMapSize-info->FbSecureSize) / width_bytes;
-    if (scanlines > 8191)
-	scanlines = 8191;
-
-    MemBox.x1 = 0;
-    MemBox.y1 = 0;
-    MemBox.x2 = pScrn->displayWidth;
-    MemBox.y2 = scanlines;
-
-    if (!xf86InitFBManager(pScreen, &MemBox)) {
-        xf86DrvMsg(scrnIndex, X_ERROR,
-		   "Memory manager initialization to "
-		   "(%d,%d) (%d,%d) failed\n",
-		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
-	return FALSE;
-    } else {
-	int  width, height;
-
-	xf86DrvMsg(scrnIndex, X_INFO,
-		   "Memory manager initialized to (%d,%d) (%d,%d)\n",
-		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
-	/* why oh why can't we just request modes which are guaranteed to be 16 lines
-	   aligned... sigh */
-	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
-						pScrn->displayWidth,
-						info->allowColorTiling ? 
-						((pScrn->virtualY + 15) & ~15)
-						- pScrn->virtualY + 2 : 2,
-						0, NULL, NULL,
-						NULL))) {
-	    xf86DrvMsg(scrnIndex, X_INFO,
-		       "Reserved area from (%d,%d) to (%d,%d)\n",
-		       fbarea->box.x1, fbarea->box.y1,
-		       fbarea->box.x2, fbarea->box.y2);
-	} else {
-	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
-	}
-
-	RADEONDRIAllocatePCIGARTTable(pScreen);
-
-	if (xf86QueryLargestOffscreenArea(pScreen, &width,
-					  &height, 0, 0, 0)) {
-	    xf86DrvMsg(scrnIndex, X_INFO,
-		       "Largest offscreen area available: %d x %d\n",
-		       width, height);
-
-	    /* Lines in offscreen area needed for depth buffer and
-	     * textures
-	     */
-	    info->depthTexLines = (scanlines
-				   - info->depthOffset / width_bytes);
-	    info->backLines	    = (scanlines
-				       - info->backOffset / width_bytes
-				       - info->depthTexLines);
-	    info->backArea	    = NULL;
-	} else {
-	    xf86DrvMsg(scrnIndex, X_ERROR,
-		       "Unable to determine largest offscreen area "
-		       "available\n");
-	    return FALSE;
-	}
-    }
-
-    xf86DrvMsg(scrnIndex, X_INFO,
-	       "Will use front buffer at offset 0x%x\n",
-	       info->frontOffset);
-
-    xf86DrvMsg(scrnIndex, X_INFO,
-	       "Will use back buffer at offset 0x%x\n",
-	       info->backOffset);
-    xf86DrvMsg(scrnIndex, X_INFO,
-	       "Will use depth buffer at offset 0x%x\n",
-	       info->depthOffset);
-    if (info->cardType==CARD_PCIE)
-    	xf86DrvMsg(scrnIndex, X_INFO,
-	           "Will use %d kb for PCI GART table at offset 0x%x\n",
-		   info->pciGartSize/1024, (unsigned)info->pciGartOffset);
-    xf86DrvMsg(scrnIndex, X_INFO,
-	       "Will use %d kb for textures at offset 0x%x\n",
-	       info->textureSize/1024, info->textureOffset);
-
-    info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) |
-			      ((info->frontOffset + info->fbLocation) >> 10));
-
-    info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) |
-			     ((info->backOffset + info->fbLocation) >> 10));
-
-    info->depthPitchOffset = (((info->depthPitch * depthCpp / 64) << 22) |
-			      ((info->depthOffset + info->fbLocation) >> 10));
-    return TRUE;
-}
-#endif /* XF86DRI */
-
-Bool RADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen)
-{
-    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
-    RADEONInfoPtr  info  = RADEONPTR(pScrn);
-    BoxRec         MemBox;
-    int            y2;
-
-    int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
-
-    MemBox.x1 = 0;
-    MemBox.y1 = 0;
-    MemBox.x2 = pScrn->displayWidth;
-    y2 = info->FbMapSize / width_bytes;
-    if (y2 >= 32768)
-	y2 = 32767; /* because MemBox.y2 is signed short */
-    MemBox.y2 = y2;
-    
-    /* The acceleration engine uses 14 bit
-     * signed coordinates, so we can't have any
-     * drawable caches beyond this region.
-     */
-    if (MemBox.y2 > 8191)
-	MemBox.y2 = 8191;
-
-    if (!xf86InitFBManager(pScreen, &MemBox)) {
-	xf86DrvMsg(scrnIndex, X_ERROR,
-		   "Memory manager initialization to "
-		   "(%d,%d) (%d,%d) failed\n",
-		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
-	return FALSE;
-    } else {
-	int       width, height;
-	FBAreaPtr fbarea;
-
-	xf86DrvMsg(scrnIndex, X_INFO,
-		   "Memory manager initialized to (%d,%d) (%d,%d)\n",
-		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
-	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
-						pScrn->displayWidth,
-						info->allowColorTiling ? 
-						((pScrn->virtualY + 15) & ~15)
-						- pScrn->virtualY + 2 : 2,
-						0, NULL, NULL,
-						NULL))) {
-	    xf86DrvMsg(scrnIndex, X_INFO,
-		       "Reserved area from (%d,%d) to (%d,%d)\n",
-		       fbarea->box.x1, fbarea->box.y1,
-		       fbarea->box.x2, fbarea->box.y2);
-	} else {
-	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
-	}
-	if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
-					      0, 0, 0)) {
-	    xf86DrvMsg(scrnIndex, X_INFO,
-		       "Largest offscreen area available: %d x %d\n",
-		       width, height);
-	}
-	return TRUE;
-    }    
-}
-#endif /* USE_XAA */
-
 static void
 RADEONPointerMoved(int index, int x, int y)
 {
commit 0631a23bd103f9b74e525da2c41304eab60c6f17
Author: Alex Deucher <alex at botch2.(none)>
Date:   Fri Dec 21 15:40:18 2007 -0500

    RADEON: fix rn50 reversion from last merge

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index e65e446..85cfe88 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1222,18 +1222,6 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
         info->mclk = 200.00;
     }
 
-    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
-        /* Avoid RN50 corruption due to memory bandwidth starvation.
-         * 18 is an empirical value based on the databook and Windows driver.
-         *
-	 * Empirical value changed to 24 to raise pixel clock limit and
-	 * allow higher resolution modes on capable monitors
-	 */
-        pll->pll_out_max = min(pll->pll_out_max,
-                               24 * info->mclk * 100 / pScrn->bitsPerPixel *
-                               info->RamWidth / 16);
-    }
-
     /* card limits for computing PLLs */
     if (IS_AVIVO_VARIANT) {
 	pll->min_post_div = 2;
commit 5b917797a13c6caa80028d1842a284598e874288
Author: Alex Deucher <alex at botch2.(none)>
Date:   Fri Dec 21 15:30:20 2007 -0500

    RADEON: remove no longer used radeon_display.c

diff --git a/src/radeon_display.c b/src/radeon_display.c
deleted file mode 100644
index 1c529cf..0000000
--- a/src/radeon_display.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
- *                VA Linux Systems Inc., Fremont, California.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
- * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <stdio.h>
-
-/* X and server generic header files */
-#include "xf86.h"
-#include "xf86_OSproc.h"
-#include "vgaHW.h"
-#include "xf86Modes.h"
-
-/* Driver data structures */
-#include "radeon.h"
-#include "radeon_reg.h"
-#include "radeon_macros.h"
-#include "radeon_probe.h"
-#include "radeon_version.h"
-
-extern int getRADEONEntityIndex(void);
-
-
-void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
-{
-    MonPtr      mon = pScrn->monitor;
-    xf86MonPtr  ddc = mon->DDC;
-    int         i;
-
-    if (flag) { /* HSync */
-	for (i = 0; i < 4; i++) {
-	    if (ddc->det_mon[i].type == DS_RANGES) {
-		mon->nHsync = 1;
-		mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h;
-		mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h;
-		return;
-	    }
-	}
-	/* If no sync ranges detected in detailed timing table, let's
-	 * try to derive them from supported VESA modes.  Are we doing
-	 * too much here!!!?  */
-	i = 0;
-	if (ddc->timings1.t1 & 0x02) { /* 800x600 at 56 */
-	    mon->hsync[i].lo = mon->hsync[i].hi = 35.2;
-	    i++;
-	}
-	if (ddc->timings1.t1 & 0x04) { /* 640x480 at 75 */
-	    mon->hsync[i].lo = mon->hsync[i].hi = 37.5;
-	    i++;
-	}
-	if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) {
-	    mon->hsync[i].lo = mon->hsync[i].hi = 37.9;
-	    i++;
-	}
-	if (ddc->timings1.t2 & 0x40) {
-	    mon->hsync[i].lo = mon->hsync[i].hi = 46.9;
-	    i++;
-	}
-	if ((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) {
-	    mon->hsync[i].lo = mon->hsync[i].hi = 48.1;
-	    i++;
-	}
-	if (ddc->timings1.t2 & 0x04) {
-	    mon->hsync[i].lo = mon->hsync[i].hi = 56.5;
-	    i++;
-	}
-	if (ddc->timings1.t2 & 0x02) {
-	    mon->hsync[i].lo = mon->hsync[i].hi = 60.0;
-	    i++;
-	}
-	if (ddc->timings1.t2 & 0x01) {
-	    mon->hsync[i].lo = mon->hsync[i].hi = 64.0;
-	    i++;
-	}
-	mon->nHsync = i;
-    } else {  /* Vrefresh */
-	for (i = 0; i < 4; i++) {
-	    if (ddc->det_mon[i].type == DS_RANGES) {
-		mon->nVrefresh = 1;
-		mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v;
-		mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v;
-		return;
-	    }
-	}
-
-	i = 0;
-	if (ddc->timings1.t1 & 0x02) { /* 800x600 at 56 */
-	    mon->vrefresh[i].lo = mon->vrefresh[i].hi = 56;
-	    i++;
-	}
-	if ((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) {
-	    mon->vrefresh[i].lo = mon->vrefresh[i].hi = 60;
-	    i++;
-	}
-	if (ddc->timings1.t2 & 0x04) {
-	    mon->vrefresh[i].lo = mon->vrefresh[i].hi = 70;
-	    i++;
-	}
-	if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) {
-	    mon->vrefresh[i].lo = mon->vrefresh[i].hi = 72;
-	    i++;
-	}
-	if ((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) ||
-	    (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) {
-	    mon->vrefresh[i].lo = mon->vrefresh[i].hi = 75;
-	    i++;
-	}
-	mon->nVrefresh = i;
-    }
-}
commit bf14aa5f88fc3b4e69d71db5b23248b8bb2018d0
Author: Alex Deucher <alex at botch2.(none)>
Date:   Fri Dec 21 15:29:47 2007 -0500

    RADEON: re-org legacy crtc/output code into separate files

diff --git a/src/Makefile.am b/src/Makefile.am
index 3e0352b..7b25e4b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -116,7 +116,8 @@ radeon_drv_ladir = @moduledir@/drivers
 radeon_drv_la_SOURCES = \
 	radeon_accel.c radeon_cursor.c radeon_dga.c \
 	radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \
-	radeon_vip.c radeon_misc.c radeon_probe.c radeon_display.c \
+	radeon_vip.c radeon_misc.c radeon_probe.c \
+	legacy_crtc.c legacy_output.c \
 	radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \
 	$(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \
 	$(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c
diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
new file mode 100644
index 0000000..f1bf9be
--- /dev/null
+++ b/src/legacy_crtc.c
@@ -0,0 +1,1268 @@
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ *                VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+/* X and server generic header files */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "vgaHW.h"
+#include "xf86Modes.h"
+
+/* Driver data structures */
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_version.h"
+
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "radeon_dri.h"
+#include "radeon_sarea.h"
+#include "sarea.h"
+#endif
+
+
+void
+legacy_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+    int mask;
+    ScrnInfoPtr pScrn = crtc->scrn;
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS);
+
+
+    switch(mode) {
+    case DPMSModeOn:
+	if (radeon_crtc->crtc_id) {
+	    OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask);
+	} else {
+	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
+	    OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask);
+	}
+	break;
+    case DPMSModeStandby:
+	if (radeon_crtc->crtc_id) {
+	    OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask);
+	} else {
+	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
+	    OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask);
+	}
+	break;
+    case DPMSModeSuspend:
+	if (radeon_crtc->crtc_id) {
+	    OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask);
+	} else {
+	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
+	    OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask);
+	}
+	break;
+    case DPMSModeOff:
+	if (radeon_crtc->crtc_id) {
+	    OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
+	} else {
+	    OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B);
+	    OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask);
+	}
+	break;
+    }
+  
+    if (mode != DPMSModeOff)
+	radeon_crtc_load_lut(crtc);
+}
+
+
+/* Define common registers for requested video mode */
+static void
+RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info)
+{
+    save->ovr_clr            = 0;
+    save->ovr_wid_left_right = 0;
+    save->ovr_wid_top_bottom = 0;
+    save->ov0_scale_cntl     = 0;
+    save->subpic_cntl        = 0;
+    save->viph_control       = 0;
+    save->i2c_cntl_1         = 0;
+    save->rbbm_soft_reset    = 0;
+    save->cap0_trig_cntl     = 0;
+    save->cap1_trig_cntl     = 0;
+    save->bus_cntl           = info->BusCntl;
+    /*
+     * If bursts are enabled, turn on discards
+     * Radeon doesn't have write bursts
+     */
+    if (save->bus_cntl & (RADEON_BUS_READ_BURST))
+	save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN;
+}
+
+static void
+RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save)
+{
+    save->surface_cntl = 0;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+    /* We must set both apertures as they can be both used to map the entire
+     * video memory. -BenH.
+     */
+    switch (crtc->scrn->bitsPerPixel) {
+    case 16:
+	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP;
+	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP;
+	break;
+
+    case 32:
+	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP;
+	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP;
+	break;
+    }
+#endif
+
+}
+
+
+static Bool
+RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save,
+		   int x, int y)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    int    Base;
+#ifdef XF86DRI
+    RADEONSAREAPrivPtr pSAREAPriv;
+    XF86DRISAREAPtr pSAREA;
+#endif
+
+    save->crtc_offset      = pScrn->fbOffset;
+#ifdef XF86DRI
+    if (info->allowPageFlip)
+	save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL;
+    else
+#endif
+	save->crtc_offset_cntl = 0;
+
+    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
+       if (IS_R300_VARIANT)
+          save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
+				     R300_CRTC_MICRO_TILE_BUFFER_DIS |
+				     R300_CRTC_MACRO_TILE_EN);
+       else
+          save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN;
+    }
+    else {
+       if (IS_R300_VARIANT)
+          save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
+				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
+				      R300_CRTC_MACRO_TILE_EN);
+       else
+          save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
+    }
+
+    Base = pScrn->fbOffset;
+
+    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
+        if (IS_R300_VARIANT) {
+	/* On r300/r400 when tiling is enabled crtc_offset is set to the address of
+	 * the surface.  the x/y offsets are handled by the X_Y tile reg for each crtc
+	 * Makes tiling MUCH easier.
+	 */
+             save->crtc_tile_x0_y0 = x | (y << 16);
+             Base &= ~0x7ff;
+         } else {
+	     /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the
+		drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes
+		flickering when scrolling vertically in a virtual screen, possibly because crtc will
+		pick up the new offset value at the end of each scanline, but the new offset_cntl value
+		only after a vsync. We'd probably need to wait (in drm) for vsync and only then update
+		OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */
+	     /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/
+#if 0
+	     /* try to get rid of flickering when scrolling at least for 2d */
+#ifdef XF86DRI
+	     if (!info->have3DWindows)
+#endif
+		 save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL;
+#endif
+	     
+             int byteshift = info->CurrentLayout.bitsPerPixel >> 4;
+             /* crtc uses 256(bytes)x8 "half-tile" start addresses? */
+             int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11;
+             Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
+             save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16);
+         }
+    }
+    else {
+       int offset = y * info->CurrentLayout.displayWidth + x;
+       switch (info->CurrentLayout.pixel_code) {
+       case 15:
+       case 16: offset *= 2; break;
+       case 24: offset *= 3; break;
+       case 32: offset *= 4; break;
+       }
+       Base += offset;
+    }
+
+    if (crtc->rotatedData != NULL) {
+	Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
+    }
+
+    Base &= ~7;                 /* 3 lower bits are always 0 */
+
+
+#ifdef XF86DRI
+    if (info->directRenderingInited) {
+	/* note cannot use pScrn->pScreen since this is unitialized when called from
+	   RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */
+        /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for
+	 *** pageflipping!
+	 ***/
+	pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
+	/* can't get at sarea in a semi-sane way? */
+	pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec));
+
+	pSAREA->frame.x = (Base  / info->CurrentLayout.pixel_bytes)
+	    % info->CurrentLayout.displayWidth;
+	pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes)
+	    / info->CurrentLayout.displayWidth;
+	pSAREA->frame.width = pScrn->frameX1 - x + 1;
+	pSAREA->frame.height = pScrn->frameY1 - y + 1;
+
+	if (pSAREAPriv->pfCurrentPage == 1) {
+	    Base += info->backOffset - info->frontOffset;
+	}
+    }
+#endif
+    save->crtc_offset = Base;
+
+    return TRUE;
+
+}
+
+/* Define CRTC registers for requested video mode */
+static Bool
+RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
+			DisplayModePtr mode)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    int    format;
+    int    hsync_start;
+    int    hsync_wid;
+    int    vsync_wid;
+
+    switch (info->CurrentLayout.pixel_code) {
+    case 4:  format = 1; break;
+    case 8:  format = 2; break;
+    case 15: format = 3; break;      /*  555 */
+    case 16: format = 4; break;      /*  565 */
+    case 24: format = 5; break;      /*  RGB */
+    case 32: format = 6; break;      /* xRGB */
+    default:
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Unsupported pixel depth (%d)\n",
+		   info->CurrentLayout.bitsPerPixel);
+	return FALSE;
+    }
+
+    /*save->bios_4_scratch = info->SavedReg->bios_4_scratch;*/
+    save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
+			   | RADEON_CRTC_EN
+			   | (format << 8)
+			   | ((mode->Flags & V_DBLSCAN)
+			      ? RADEON_CRTC_DBL_SCAN_EN
+			      : 0)
+			   | ((mode->Flags & V_CSYNC)
+			      ? RADEON_CRTC_CSYNC_EN
+			      : 0)
+			   | ((mode->Flags & V_INTERLACE)
+			      ? RADEON_CRTC_INTERLACE_EN
+			      : 0));
+
+    save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN|
+			    RADEON_CRTC_VSYNC_DIS |
+			    RADEON_CRTC_HSYNC_DIS |
+			    RADEON_CRTC_DISPLAY_DIS);
+
+    save->disp_merge_cntl = info->SavedReg->disp_merge_cntl;
+    save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+
+    save->crtc_more_cntl = 0;
+    if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+        (info->ChipFamily == CHIP_FAMILY_RS200)) {
+        /* This is to workaround the asic bug for RMX, some versions
+           of BIOS dosen't have this register initialized correctly.
+	*/
+        save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
+    }
+
+    save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
+			       | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff)
+				  << 16));
+
+    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
+    if (!hsync_wid)       hsync_wid = 1;
+    hsync_start = mode->CrtcHSyncStart - 8;
+
+    save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
+				  | ((hsync_wid & 0x3f) << 16)
+				  | ((mode->Flags & V_NHSYNC)
+				     ? RADEON_CRTC_H_SYNC_POL
+				     : 0));
+
+				/* This works for double scan mode. */
+    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+			       | ((mode->CrtcVDisplay - 1) << 16));
+
+    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+    if (!vsync_wid)       vsync_wid = 1;
+
+    save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
+				  | ((vsync_wid & 0x1f) << 16)
+				  | ((mode->Flags & V_NVSYNC)
+				     ? RADEON_CRTC_V_SYNC_POL
+				     : 0));
+
+    save->crtc_pitch  = (((pScrn->displayWidth * pScrn->bitsPerPixel) +
+			  ((pScrn->bitsPerPixel * 8) -1)) /
+			 (pScrn->bitsPerPixel * 8));
+    save->crtc_pitch |= save->crtc_pitch << 16;
+    
+    save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid;
+    save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid;
+    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
+    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
+
+    if (info->IsDellServer) {
+	save->dac2_cntl = info->SavedReg->dac2_cntl;
+	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl;
+	save->crtc2_gen_cntl = info->SavedReg->crtc2_gen_cntl;
+	save->disp_hw_debug = info->SavedReg->disp_hw_debug;
+
+	save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
+	save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
+
+	/* For CRT on DAC2, don't turn it on if BIOS didn't
+	   enable it, even it's detected.
+	*/
+	save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
+	save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
+	save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
+    }
+
+    return TRUE;
+}
+
+
+static Bool
+RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save,
+		    int x, int y)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    int    Base;
+#ifdef XF86DRI
+    RADEONSAREAPrivPtr pSAREAPriv;
+    XF86DRISAREAPtr pSAREA;
+#endif
+
+    /* It seems all fancy options apart from pflip can be safely disabled
+     */
+    save->crtc2_offset      = pScrn->fbOffset;
+#ifdef XF86DRI
+    if (info->allowPageFlip)
+	save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL;
+    else
+#endif
+	save->crtc2_offset_cntl = 0;
+
+    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
+       if (IS_R300_VARIANT)
+          save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
+				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
+				      R300_CRTC_MACRO_TILE_EN);
+       else
+          save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN;
+    }
+    else {
+       if (IS_R300_VARIANT)
+          save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
+				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
+				      R300_CRTC_MACRO_TILE_EN);
+       else
+          save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN;
+    }
+
+    Base = pScrn->fbOffset;
+
+    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
+        if (IS_R300_VARIANT) {
+	/* On r300/r400 when tiling is enabled crtc_offset is set to the address of
+	 * the surface.  the x/y offsets are handled by the X_Y tile reg for each crtc
+	 * Makes tiling MUCH easier.
+	 */
+             save->crtc2_tile_x0_y0 = x | (y << 16);
+             Base &= ~0x7ff;
+         } else {
+	     /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the
+		drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes
+		flickering when scrolling vertically in a virtual screen, possibly because crtc will
+		pick up the new offset value at the end of each scanline, but the new offset_cntl value
+		only after a vsync. We'd probably need to wait (in drm) for vsync and only then update
+		OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */
+	     /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/
+#if 0
+	     /* try to get rid of flickering when scrolling at least for 2d */
+#ifdef XF86DRI
+	     if (!info->have3DWindows)
+#endif
+		 save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL;
+#endif
+
+             int byteshift = info->CurrentLayout.bitsPerPixel >> 4;
+             /* crtc uses 256(bytes)x8 "half-tile" start addresses? */
+             int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11;
+             Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
+             save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16);
+         }
+    }
+    else {
+       int offset = y * info->CurrentLayout.displayWidth + x;
+       switch (info->CurrentLayout.pixel_code) {
+       case 15:
+       case 16: offset *= 2; break;
+       case 24: offset *= 3; break;
+       case 32: offset *= 4; break;
+       }
+       Base += offset;
+    }
+
+    if (crtc->rotatedData != NULL) {
+	Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
+    }
+
+    Base &= ~7;                 /* 3 lower bits are always 0 */
+
+#ifdef XF86DRI
+    if (info->directRenderingInited) {
+	/* note cannot use pScrn->pScreen since this is unitialized when called from
+	   RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */
+        /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for
+	 *** pageflipping!
+	 ***/
+	pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
+	/* can't get at sarea in a semi-sane way? */
+	pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec));
+
+	pSAREAPriv->crtc2_base = Base;
+
+	if (pSAREAPriv->pfCurrentPage == 1) {
+	    Base += info->backOffset - info->frontOffset;
+	}
+    }
+#endif
+    save->crtc2_offset = Base;
+
+    return TRUE;
+}
+
+
+/* Define CRTC2 registers for requested video mode */
+static Bool
+RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
+			 DisplayModePtr mode)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    int    format;
+    int    hsync_start;
+    int    hsync_wid;
+    int    vsync_wid;
+
+    switch (info->CurrentLayout.pixel_code) {
+    case 4:  format = 1; break;
+    case 8:  format = 2; break;
+    case 15: format = 3; break;      /*  555 */
+    case 16: format = 4; break;      /*  565 */
+    case 24: format = 5; break;      /*  RGB */
+    case 32: format = 6; break;      /* xRGB */
+    default:
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Unsupported pixel depth (%d)\n",
+		   info->CurrentLayout.bitsPerPixel);
+	return FALSE;
+    }
+
+    save->crtc2_h_total_disp =
+	((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
+	 | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16));
+
+    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
+    if (!hsync_wid)       hsync_wid = 1;
+    hsync_start = mode->CrtcHSyncStart - 8;
+
+    save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff)
+				   | ((hsync_wid & 0x3f) << 16)
+				   | ((mode->Flags & V_NHSYNC)
+				      ? RADEON_CRTC_H_SYNC_POL
+				      : 0));
+
+				/* This works for double scan mode. */
+    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+				| ((mode->CrtcVDisplay - 1) << 16));
+
+    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+    if (!vsync_wid)       vsync_wid = 1;
+
+    save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
+				   | ((vsync_wid & 0x1f) << 16)
+				   | ((mode->Flags & V_NVSYNC)
+				      ? RADEON_CRTC2_V_SYNC_POL
+				      : 0));
+
+    save->crtc2_pitch  = ((pScrn->displayWidth * pScrn->bitsPerPixel) +
+			  ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8);
+    save->crtc2_pitch |= save->crtc2_pitch << 16;
+
+    /* check to see if TV DAC is enabled for another crtc and keep it enabled */
+    if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON)
+	save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
+    else
+	save->crtc2_gen_cntl = 0;
+
+    save->crtc2_gen_cntl |= (RADEON_CRTC2_EN
+			     | (format << 8)
+			     | RADEON_CRTC2_VSYNC_DIS
+			     | RADEON_CRTC2_HSYNC_DIS
+			     | RADEON_CRTC2_DISP_DIS
+			     | ((mode->Flags & V_DBLSCAN)
+				? RADEON_CRTC2_DBL_SCAN_EN
+				: 0)
+			     | ((mode->Flags & V_CSYNC)
+				? RADEON_CRTC2_CSYNC_EN
+				: 0)
+			     | ((mode->Flags & V_INTERLACE)
+				? RADEON_CRTC2_INTERLACE_EN
+				: 0));
+
+    save->disp2_merge_cntl = info->SavedReg->disp2_merge_cntl;
+    save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN);
+
+    save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid;
+    save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid;
+
+    if (info->ChipFamily == CHIP_FAMILY_RS400) {
+	save->rs480_unk_e30 = 0x105DC1CC; /* because I'm worth it */
+	save->rs480_unk_e34 = 0x2749D000; /* AMD really should */
+	save->rs480_unk_e38 = 0x29ca71dc; /* release docs */
+	save->rs480_unk_e3c = 0x28FBC3AC; /* this is so a trade secret */
+    }
+
+    return TRUE;
+}
+
+
+/* Define PLL registers for requested video mode */
+static void
+RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
+		       RADEONPLLPtr pll, DisplayModePtr mode,
+		       int flags)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    CARD32 feedback_div = 0;
+    CARD32 reference_div = 0;
+    CARD32 post_divider = 0;
+    CARD32 freq = 0;
+
+    struct {
+	int divider;
+	int bitvalue;
+    } *post_div, post_divs[]   = {
+				/* From RAGE 128 VR/RAGE 128 GL Register
+				 * Reference Manual (Technical Reference
+				 * Manual P/N RRG-G04100-C Rev. 0.04), page
+				 * 3-17 (PLL_DIV_[3:0]).
+				 */
+	{  1, 0 },              /* VCLK_SRC                 */
+	{  2, 1 },              /* VCLK_SRC/2               */
+	{  4, 2 },              /* VCLK_SRC/4               */
+	{  8, 3 },              /* VCLK_SRC/8               */
+	{  3, 4 },              /* VCLK_SRC/3               */
+	{ 16, 5 },              /* VCLK_SRC/16              */
+	{  6, 6 },              /* VCLK_SRC/6               */
+	{ 12, 7 },              /* VCLK_SRC/12              */
+	{  0, 0 }
+    };
+
+
+    if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
+       save->ppll_ref_div = info->RefDivider;
+       save->ppll_div_3   = info->FeedbackDivider | (info->PostDivider << 16);
+       save->htotal_cntl  = 0;
+       return;
+    }
+
+    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
+
+    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+	if (post_div->divider == post_divider)
+	    break;
+    }
+
+    if (!post_div->divider) {
+	save->pll_output_freq = freq;
+	post_div = &post_divs[0];
+    }
+
+    save->dot_clock_freq = freq;
+    save->feedback_div   = feedback_div;
+    save->reference_div  = reference_div;
+    save->post_div       = post_divider;
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
+		   (unsigned)save->dot_clock_freq,
+		   (unsigned)save->pll_output_freq,
+		   save->feedback_div,
+		   save->reference_div,
+		   save->post_div);
+
+    save->ppll_ref_div   = save->reference_div;
+
+#if defined(__powerpc__)
+    /* apparently programming this otherwise causes a hang??? */
+    if (info->MacModel == RADEON_MAC_IBOOK)
+	save->ppll_div_3 = 0x000600ad;
+    else
+#endif
+    save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
+
+    save->htotal_cntl    = mode->HTotal & 0x7;
+
+    save->vclk_ecp_cntl = (info->SavedReg->vclk_ecp_cntl &
+	    ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
+}
+
+/* Define PLL2 registers for requested video mode */
+static void
+RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
+			RADEONPLLPtr pll, DisplayModePtr mode,
+			int flags)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    CARD32 feedback_div = 0;
+    CARD32 reference_div = 0;
+    CARD32 post_divider = 0;
+    CARD32 freq = 0;
+
+    struct {
+	int divider;
+	int bitvalue;
+    } *post_div, post_divs[]   = {
+				/* From RAGE 128 VR/RAGE 128 GL Register
+				 * Reference Manual (Technical Reference
+				 * Manual P/N RRG-G04100-C Rev. 0.04), page
+				 * 3-17 (PLL_DIV_[3:0]).
+				 */
+	{  1, 0 },              /* VCLK_SRC                 */
+	{  2, 1 },              /* VCLK_SRC/2               */
+	{  4, 2 },              /* VCLK_SRC/4               */
+	{  8, 3 },              /* VCLK_SRC/8               */
+	{  3, 4 },              /* VCLK_SRC/3               */
+	{  6, 6 },              /* VCLK_SRC/6               */
+	{ 12, 7 },              /* VCLK_SRC/12              */
+	{  0, 0 }
+    };
+
+    if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
+       save->p2pll_ref_div = info->RefDivider;
+       save->p2pll_div_0   = info->FeedbackDivider | (info->PostDivider << 16);
+       save->htotal_cntl2  = 0;
+       return;
+    }
+
+    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
+
+    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+	if (post_div->divider == post_divider)
+	    break;
+    }
+
+    if (!post_div->divider) {
+	save->pll_output_freq_2 = freq;
+	post_div = &post_divs[0];
+    }
+
+    save->dot_clock_freq_2 = freq;
+    save->feedback_div_2   = feedback_div;
+    save->reference_div_2  = reference_div;
+    save->post_div_2       = post_divider;
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
+		   (unsigned)save->dot_clock_freq_2,
+		   (unsigned)save->pll_output_freq_2,
+		   save->feedback_div_2,
+		   save->reference_div_2,
+		   save->post_div_2);
+
+    save->p2pll_ref_div    = save->reference_div_2;
+
+    save->p2pll_div_0      = (save->feedback_div_2 |
+			      (post_div->bitvalue << 16));
+
+    save->htotal_cntl2     = mode->HTotal & 0x7;
+
+    save->pixclks_cntl     = ((info->SavedReg->pixclks_cntl &
+			       ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
+			      RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
+}
+
+static void
+RADEONInitBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info      = RADEONPTR(pScrn);
+
+    /* tell the bios not to muck with the hardware on events */
+    save->bios_4_scratch = 0x4; /* 0x4 needed for backlight */
+    save->bios_5_scratch = (info->SavedReg->bios_5_scratch & 0xff) | 0xff00; /* bits 0-3 keep backlight level */
+    save->bios_6_scratch = info->SavedReg->bios_6_scratch | 0x40000000;
+
+}
+
+static void
+radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    /* pixclks_cntl controls tv clock routing */
+    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl);
+}
+
+/* Calculate display buffer watermark to prevent buffer underflow */
+static void
+RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2, DisplayModePtr mode1, DisplayModePtr mode2)
+{
+    RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0;
+    float mem_tcas;
+    int k1, c;
+    CARD32 MemTrcdExtMemCntl[4]     = {1, 2, 3, 4};
+    CARD32 MemTrpExtMemCntl[4]      = {1, 2, 3, 4};
+    CARD32 MemTrasExtMemCntl[8]     = {1, 2, 3, 4, 5, 6, 7, 8};
+
+    CARD32 MemTrcdMemTimingCntl[8]     = {1, 2, 3, 4, 5, 6, 7, 8};
+    CARD32 MemTrpMemTimingCntl[8]      = {1, 2, 3, 4, 5, 6, 7, 8};
+    CARD32 MemTrasMemTimingCntl[16]    = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+    float MemTcas[8]  = {0, 1, 2, 3, 0, 1.5, 2.5, 0};
+    float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+    float MemTrbs[8]  = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5};
+
+    float mem_bw, peak_disp_bw;
+    float min_mem_eff = 0.8;
+    float sclk_eff, sclk_delay;
+    float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk;
+    float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2;
+    float pix_clk, pix_clk2; /* in MHz */
+    int cur_size = 16;       /* in octawords */
+    int critical_point, critical_point2;
+    int stop_req, max_stop_req;
+    float read_return_rate, time_disp1_drop_priority;
+
+    /*
+     * Set display0/1 priority up on r3/4xx in the memory controller for
+     * high res modes if the user specifies HIGH for displaypriority
+     * option.
+     */
+    if ((info->DispPriority == 2) && IS_R300_VARIANT) {
+	CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
+	if (pRADEONEnt->pCrtc[1]->enabled) {
+	    mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */
+	} else {
+	    mc_init_misc_lat_timer |= 0x0100; /* display 0 only */
+	}
+	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+    }
+
+
+    /* R420 and RV410 family not supported yet */
+    if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; 
+
+    /*
+     * Determine if there is enough bandwidth for current display mode
+     */
+    mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
+
+    pix_clk = mode1->Clock/1000.0;
+    if (mode2)
+	pix_clk2 = mode2->Clock/1000.0;
+    else
+	pix_clk2 = 0;
+
+    peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes);
+    if (pixel_bytes2)
+      peak_disp_bw += (pix_clk2 * pixel_bytes2);
+
+    if (peak_disp_bw >= mem_bw * min_mem_eff) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "You may not have enough display bandwidth for current mode\n"
+		   "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
+    }
+
+    /*  CRTC1
+        Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
+	GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
+    */
+    stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16;
+
+    /* setup Max GRPH_STOP_REQ default value */
+    if (IS_RV100_VARIANT)
+	max_stop_req = 0x5c;
+    else
+	max_stop_req  = 0x7c;
+    if (stop_req > max_stop_req)
+	stop_req = max_stop_req;
+
+    /*  Get values from the EXT_MEM_CNTL register...converting its contents. */
+    temp = INREG(RADEON_MEM_TIMING_CNTL);
+    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
+	mem_trcd      = MemTrcdExtMemCntl[(temp & 0x0c) >> 2];
+	mem_trp       = MemTrpExtMemCntl[ (temp & 0x03) >> 0];
+	mem_tras      = MemTrasExtMemCntl[(temp & 0x70) >> 4];
+    } else { /* RV200 and later */
+	mem_trcd      = MemTrcdMemTimingCntl[(temp & 0x07) >> 0];
+	mem_trp       = MemTrpMemTimingCntl[ (temp & 0x700) >> 8];
+	mem_tras      = MemTrasMemTimingCntl[(temp & 0xf000) >> 12];
+    }
+
+    /* Get values from the MEM_SDRAM_MODE_REG register...converting its */
+    temp = INREG(RADEON_MEM_SDRAM_MODE_REG);
+    data = (temp & (7<<20)) >> 20;
+    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
+	mem_tcas = MemTcas [data];
+    } else {
+	mem_tcas = MemTcas2 [data];
+    }
+
+    if (IS_R300_VARIANT) {
+
+	/* on the R300, Tcas is included in Trbs.
+	*/
+	temp = INREG(RADEON_MEM_CNTL);
+	data = (R300_MEM_NUM_CHANNELS_MASK & temp);
+	if (data == 1) {
+	    if (R300_MEM_USE_CD_CH_ONLY & temp) {
+		temp  = INREG(R300_MC_IND_INDEX);
+		temp &= ~R300_MC_IND_ADDR_MASK;
+		temp |= R300_MC_READ_CNTL_CD_mcind;
+		OUTREG(R300_MC_IND_INDEX, temp);
+		temp  = INREG(R300_MC_IND_DATA);
+		data = (R300_MEM_RBS_POSITION_C_MASK & temp);
+	    } else {
+		temp = INREG(R300_MC_READ_CNTL_AB);
+		data = (R300_MEM_RBS_POSITION_A_MASK & temp);
+	    }
+	} else {
+	    temp = INREG(R300_MC_READ_CNTL_AB);
+	    data = (R300_MEM_RBS_POSITION_A_MASK & temp);
+	}
+
+	mem_trbs = MemTrbs[data];
+	mem_tcas += mem_trbs;
+    }
+
+    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
+	/* DDR64 SCLK_EFF = SCLK for analysis */
+	sclk_eff = info->sclk;
+    } else {
+#ifdef XF86DRI
+	if (info->directRenderingEnabled)
+	    sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0);
+	else
+#endif
+	    sclk_eff = info->sclk;
+    }
+
+    /* Find the memory controller latency for the display client.
+    */
+    if (IS_R300_VARIANT) {
+	/*not enough for R350 ???*/
+	/*
+	if (!mode2) sclk_delay = 150;
+	else {
+	    if (info->RamWidth == 256) sclk_delay = 87;
+	    else sclk_delay = 97;
+	}
+	*/
+	sclk_delay = 250;
+    } else {
+	if ((info->ChipFamily == CHIP_FAMILY_RV100) ||
+	    info->IsIGP) {
+	    if (info->IsDDR) sclk_delay = 41;
+	    else sclk_delay = 33;
+	} else {
+	    if (info->RamWidth == 128) sclk_delay = 57;
+	    else sclk_delay = 41;
+	}
+    }
+
+    mc_latency_sclk = sclk_delay / sclk_eff;
+
+    if (info->IsDDR) {
+	if (info->RamWidth == 32) {
+	    k1 = 40;
+	    c  = 3;
+	} else {
+	    k1 = 20;
+	    c  = 1;
+	}
+    } else {
+	k1 = 40;
+	c  = 3;
+    }
+    mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) /
+		       info->mclk) + (4.0 / sclk_eff);
+
+    /*
+      HW cursor time assuming worst case of full size colour cursor.
+    */
+    cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk;
+    cur_latency_sclk = cur_size / sclk_eff;
+
+    /*
+      Find the total latency for the display data.
+    */
+    disp_latency_overhead = 8.0 / info->sclk;
+    mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk;
+    mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk;
+    disp_latency = MAX(mc_latency_mclk, mc_latency_sclk);
+
+    /*
+      Find the drain rate of the display buffer.
+    */
+    disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes);
+    if (pixel_bytes2)
+	disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2);
+    else
+	disp_drain_rate2 = 0;
+
+    /*
+      Find the critical point of the display buffer.
+    */
+    critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5);
+
+    /* ???? */
+    /*
+    temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT;
+    if (critical_point < temp) critical_point = temp;
+    */
+    if (info->DispPriority == 2) {
+	critical_point = 0;
+    }
+
+    /*
+      The critical point should never be above max_stop_req-4.  Setting
+      GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
+    */
+    if (max_stop_req - critical_point < 4) critical_point = 0;
+
+    if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) {
+	/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
+	critical_point = 0x10;
+    }
+
+    temp = info->SavedReg->grph_buffer_cntl;
+    temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
+    temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
+    temp &= ~(RADEON_GRPH_START_REQ_MASK);
+    if ((info->ChipFamily == CHIP_FAMILY_R350) &&
+	(stop_req > 0x15)) {
+	stop_req -= 0x10;
+    }
+    temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+
+    temp |= RADEON_GRPH_BUFFER_SIZE;
+    temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
+	      RADEON_GRPH_CRITICAL_AT_SOF |
+	      RADEON_GRPH_STOP_CNTL);
+    /*
+      Write the result into the register.
+    */
+    OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
+				     (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "GRPH_BUFFER_CNTL from %x to %x\n",
+		   (unsigned int)info->SavedReg->grph_buffer_cntl,
+		   (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL));
+
+    if (mode2) {
+	stop_req = mode2->HDisplay * pixel_bytes2 / 16;
+
+	if (stop_req > max_stop_req) stop_req = max_stop_req;
+
+	temp = info->SavedReg->grph2_buffer_cntl;
+	temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
+	temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
+	temp &= ~(RADEON_GRPH_START_REQ_MASK);
+	if ((info->ChipFamily == CHIP_FAMILY_R350) &&
+	    (stop_req > 0x15)) {
+	    stop_req -= 0x10;
+	}
+	temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+	temp |= RADEON_GRPH_BUFFER_SIZE;
+	temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
+		  RADEON_GRPH_CRITICAL_AT_SOF |
+		  RADEON_GRPH_STOP_CNTL);
+
+	if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS200))
+	    critical_point2 = 0;
+	else {
+	    read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128));
+	    time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate);
+
+	    critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + 
+					disp_latency) * disp_drain_rate2 + 0.5);
+
+	    if (info->DispPriority == 2) {
+		critical_point2 = 0;
+	    }
+
+	    if (max_stop_req - critical_point2 < 4) critical_point2 = 0;
+
+	}
+
+	if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) {
+	    /* some R300 cards have problem with this set to 0 */
+	    critical_point2 = 0x10;
+	}
+
+	OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
+					  (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		       "GRPH2_BUFFER_CNTL from %x to %x\n",
+		       (unsigned int)info->SavedReg->grph2_buffer_cntl,
+		       (unsigned int)INREG(RADEON_GRPH2_BUFFER_CNTL));
+    }
+}
+
+void
+RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    DisplayModePtr mode1, mode2;
+    int pixel_bytes2 = 0;
+
+    if (info->IsPrimary || info->IsSecondary)
+	mode1 = &xf86_config->crtc[0]->mode;
+    else
+	mode1 = info->CurrentLayout.mode;
+    mode2 = NULL;
+    pixel_bytes2 = info->CurrentLayout.pixel_bytes;
+
+    if (xf86_config->num_crtc == 2) {
+      pixel_bytes2 = 0;
+      mode2 = NULL;
+
+      if (xf86_config->crtc[1]->enabled && xf86_config->crtc[0]->enabled) {
+	pixel_bytes2 = info->CurrentLayout.pixel_bytes;
+	mode1 = &xf86_config->crtc[0]->mode;
+	mode2 = &xf86_config->crtc[1]->mode;
+      } else if (xf86_config->crtc[0]->enabled) {
+	mode1 = &xf86_config->crtc[0]->mode;
+      } else if (xf86_config->crtc[1]->enabled) {
+	mode1 = &xf86_config->crtc[1]->mode;
+      } else
+	return;
+    } else {
+	if (xf86_config->crtc[0]->enabled)
+	    mode1 = &xf86_config->crtc[0]->mode;
+	else
+	    return;
+    }
+
+    RADEONInitDispBandwidth2(pScrn, info, pixel_bytes2, mode1, mode2);
+}
+
+void
+legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
+		     DisplayModePtr adjusted_mode, int x, int y)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    Bool           tilingOld   = info->tilingEnabled;
+    int i = 0;
+    double dot_clock = 0;
+    int pll_flags = RADEON_PLL_LEGACY;
+    Bool update_tv_routing = FALSE;
+
+
+    if (info->allowColorTiling) {
+	info->tilingEnabled = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
+#ifdef XF86DRI
+	if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) {
+	    RADEONSAREAPrivPtr pSAREAPriv;
+	    if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_SWITCH_TILING, (info->tilingEnabled ? 1 : 0)) < 0)
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "[drm] failed changing tiling status\n");
+	    /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
+	    pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
+	    info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE;
+	}
+#endif
+    }
+
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
+	RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+	if (output->crtc == crtc) {
+	    if (radeon_output->MonType != MT_CRT)
+		pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+	    if (radeon_output->MonType == MT_LCD)
+		pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV);
+	}
+    }
+
+    if (info->IsMobility)
+	RADEONInitBIOSRegisters(pScrn, info->ModeReg);
+
+    ErrorF("init memmap\n");
+    RADEONInitMemMapRegisters(pScrn, info->ModeReg, info);
+    ErrorF("init common\n");
+    RADEONInitCommonRegisters(info->ModeReg, info);
+
+    RADEONInitSurfaceCntl(crtc, info->ModeReg);
+
+    switch (radeon_crtc->crtc_id) {
+    case 0:
+	ErrorF("init crtc1\n");
+	RADEONInitCrtcRegisters(crtc, info->ModeReg, adjusted_mode);
+	RADEONInitCrtcBase(crtc, info->ModeReg, x, y);
+	dot_clock = adjusted_mode->Clock / 1000.0;
+	if (dot_clock) {
+	    ErrorF("init pll1\n");
+	    RADEONInitPLLRegisters(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
+	} else {
+	    info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div;
+	    info->ModeReg->ppll_div_3   = info->SavedReg->ppll_div_3;
+	    info->ModeReg->htotal_cntl  = info->SavedReg->htotal_cntl;
+	}
+	break;
+    case 1:
+	ErrorF("init crtc2\n");
+	RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode);
+	RADEONInitCrtc2Base(crtc, info->ModeReg, x, y);
+	dot_clock = adjusted_mode->Clock / 1000.0;
+	if (dot_clock) {
+	    ErrorF("init pll2\n");
+	    RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
+	}
+	break;
+    }
+
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
+	RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+	if (output->crtc == crtc) {
+	    if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) {
+		switch (radeon_crtc->crtc_id) {
+		case 0:
+		    RADEONAdjustCrtcRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
+		    RADEONAdjustPLLRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
+		    update_tv_routing = TRUE;
+		    break;
+		case 1:
+		    RADEONAdjustCrtc2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
+		    RADEONAdjustPLL2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
+		    break;
+		}
+	    }
+	}
+    }
+
+    if (info->IsMobility)
+	RADEONRestoreBIOSRegisters(pScrn, info->ModeReg);
+
+    ErrorF("restore memmap\n");
+    RADEONRestoreMemMapRegisters(pScrn, info->ModeReg);
+    ErrorF("restore common\n");
+    RADEONRestoreCommonRegisters(pScrn, info->ModeReg);
+
+    switch (radeon_crtc->crtc_id) {
+    case 0:
+	ErrorF("restore crtc1\n");
+	RADEONRestoreCrtcRegisters(pScrn, info->ModeReg);
+	ErrorF("restore pll1\n");
+	RADEONRestorePLLRegisters(pScrn, info->ModeReg);
+	break;
+    case 1:
+	ErrorF("restore crtc2\n");
+	RADEONRestoreCrtc2Registers(pScrn, info->ModeReg);
+	ErrorF("restore pll2\n");
+	RADEONRestorePLL2Registers(pScrn, info->ModeReg);
+	break;
+    }
+
+    /* pixclks_cntl handles tv-out clock routing */
+    if (update_tv_routing)
+	radeon_update_tv_routing(pScrn, info->ModeReg);
+
+    if (info->DispPriority)
+        RADEONInitDispBandwidth(pScrn);
+
+    if (info->tilingEnabled != tilingOld) {
+	/* need to redraw front buffer, I guess this can be considered a hack ? */
+	/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
+	if (pScrn->pScreen)
+	    xf86EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
+	RADEONChangeSurfaces(pScrn);
+	if (pScrn->pScreen)
+	    xf86EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
+	/* xf86SetRootClip would do, but can't access that here */
+    }
+
+    /* reset ecp_div for Xv */
+    info->ecp_div = -1;
+
+}
+
diff --git a/src/legacy_output.c b/src/legacy_output.c
new file mode 100644
index 0000000..6f55ae2
--- /dev/null
+++ b/src/legacy_output.c
@@ -0,0 +1,1577 @@
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ *                VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+/* X and server generic header files */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "vgaHW.h"
+#include "xf86Modes.h"
+
+/* Driver data structures */
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_version.h"
+#include "radeon_tv.h"
+#include "radeon_atombios.h"
+
+static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn);
+static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color);
+static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color);
+static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn);
+
+
+Bool
+RADEONDVOReadByte(I2CDevPtr dvo, int addr, CARD8 *ch)
+{
+    if (!xf86I2CReadByte(dvo, addr, ch)) {
+	xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read from %s Slave %d.\n",
+		   dvo->pI2CBus->BusName, dvo->SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+Bool
+RADEONDVOWriteByte(I2CDevPtr dvo, int addr, CARD8 ch)
+{
+    if (!xf86I2CWriteByte(dvo, addr, ch)) {
+	xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n",
+		   dvo->pI2CBus->BusName, dvo->SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+I2CDevPtr
+RADEONDVODeviceInit(I2CBusPtr b, I2CSlaveAddr addr)
+{
+    I2CDevPtr dvo;
+
+    dvo = xcalloc(1, sizeof(I2CDevRec));
+    if (dvo == NULL)
+	return NULL;
+
+    dvo->DevName = "RADEON DVO Controller";
+    dvo->SlaveAddr = addr;
+    dvo->pI2CBus = b;
+    dvo->StartTimeout = b->StartTimeout;
+    dvo->BitTimeout = b->BitTimeout;
+    dvo->AcknTimeout = b->AcknTimeout;
+    dvo->ByteTimeout = b->ByteTimeout;
+
+    if (xf86I2CDevInit(dvo)) {
+	return dvo;
+    }
+
+    xfree(dvo);
+    return NULL;
+}
+
+static void
+RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (!radeon_output->DVOChip)
+	return;
+
+    OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
+	   (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+
+    if (!RADEONInitExtTMDSInfoFromBIOS(output)) {
+	if (radeon_output->DVOChip) {
+	    switch(info->ext_tmds_chip) {
+	    case RADEON_SIL_164:
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x30);
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x00);
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x90);
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0x89);
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x3b);
+		break;
+#if 0
+		/* needs work see bug 10418 */
+	    case RADEON_SIL_1178:
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x44);
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x4c);
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0e, 0x01);
+		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x80);
+                RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x30);
+                RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0xc9);
+                RADEONDVOWriteByte(radeon_output->DVOChip, 0x0d, 0x70);
+                RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x32);
+                RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x33);
+		break;
+#endif
+	    default:
+		break;
+	    }
+	}
+    }
+}
+
+#if 0
+static RADEONMonitorType
+RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
+{
+    RADEONInfoPtr info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    int		  bConnected = 0;
+
+    /* the monitor either wasn't connected or it is a non-DDC CRT.
+     * try to probe it
+     */
+    if(IsCrtDac) {
+	unsigned long ulOrigVCLK_ECP_CNTL;
+	unsigned long ulOrigDAC_CNTL;
+	unsigned long ulOrigDAC_MACRO_CNTL;
+	unsigned long ulOrigDAC_EXT_CNTL;
+	unsigned long ulOrigCRTC_EXT_CNTL;
+	unsigned long ulData;
+	unsigned long ulMask;
+
+	ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+
+	ulData              = ulOrigVCLK_ECP_CNTL;
+	ulData             &= ~(RADEON_PIXCLK_ALWAYS_ONb
+				| RADEON_PIXCLK_DAC_ALWAYS_ONb);
+	ulMask              = ~(RADEON_PIXCLK_ALWAYS_ONb
+				|RADEON_PIXCLK_DAC_ALWAYS_ONb);
+	OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask);
+
+	ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL);
+	ulData              = ulOrigCRTC_EXT_CNTL;
+	ulData             |= RADEON_CRTC_CRT_ON;
+	OUTREG(RADEON_CRTC_EXT_CNTL, ulData);
+
+	ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL);
+	ulData             = ulOrigDAC_EXT_CNTL;
+	ulData            &= ~RADEON_DAC_FORCE_DATA_MASK;
+	ulData            |=  (RADEON_DAC_FORCE_BLANK_OFF_EN
+			       |RADEON_DAC_FORCE_DATA_EN
+			       |RADEON_DAC_FORCE_DATA_SEL_MASK);
+	if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
+	    (info->ChipFamily == CHIP_FAMILY_RV280))
+	    ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+	else
+	    ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT);
+
+	OUTREG(RADEON_DAC_EXT_CNTL, ulData);
+
+	/* turn on power so testing can go through */
+	ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL);
+	ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN;
+	OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL);
+
+	ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
+	ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
+				  RADEON_DAC_PDWN_B);
+	OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
+
+	/* Enable comparators and set DAC range to PS2 (VGA) output level */
+	ulData = ulOrigDAC_CNTL;
+	ulData |= RADEON_DAC_CMP_EN;
+	ulData &= ~RADEON_DAC_RANGE_CNTL_MASK;
+	ulData |= 0x2;
+	OUTREG(RADEON_DAC_CNTL, ulData);
+
+	/* Settle down */
+	usleep(10000);
+
+	/* Read comparators */
+	ulData     = INREG(RADEON_DAC_CNTL);
+	bConnected =  (RADEON_DAC_CMP_OUTPUT & ulData)?1:0;
+
+	/* Restore things */
+	ulData    = ulOrigVCLK_ECP_CNTL;
+	ulMask    = 0xFFFFFFFFL;
+	OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask);
+
+	OUTREG(RADEON_DAC_CNTL,      ulOrigDAC_CNTL     );
+	OUTREG(RADEON_DAC_EXT_CNTL,  ulOrigDAC_EXT_CNTL );
+	OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);
+
+	if (!bConnected) {
+	    /* Power DAC down if CRT is not connected */
+            ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
+            ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
+	    	RADEON_DAC_PDWN_B);
+            OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
+
+	    ulData = INREG(RADEON_DAC_CNTL);
+	    ulData |= RADEON_DAC_PDWN;
+	    OUTREG(RADEON_DAC_CNTL, ulData);
+    	}
+    } else { /* TV DAC */
+
+        /* This doesn't seem to work reliably (maybe worse on some OEM cards),
+           for now we always return false. If one wants to connected a
+           non-DDC monitor on the DVI port when CRT port is also connected,
+           he will need to explicitly tell the driver in the config file
+           with Option MonitorLayout.
+        */
+        bConnected = FALSE;
+
+#if 0
+	if (info->ChipFamily == CHIP_FAMILY_R200) {
+	    unsigned long ulOrigGPIO_MONID;
+	    unsigned long ulOrigFP2_GEN_CNTL;
+	    unsigned long ulOrigDISP_OUTPUT_CNTL;
+	    unsigned long ulOrigCRTC2_GEN_CNTL;
+	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_A;
+	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_B;
+	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_C;
+	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_D;
+	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_E;
+	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_F;
+	    unsigned long ulOrigCRTC2_H_TOTAL_DISP;
+	    unsigned long ulOrigCRTC2_V_TOTAL_DISP;
+	    unsigned long ulOrigCRTC2_H_SYNC_STRT_WID;
+	    unsigned long ulOrigCRTC2_V_SYNC_STRT_WID;
+	    unsigned long ulData, i;
+
+	    ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID);
+	    ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL);
+	    ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL);
+	    ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL);
+	    ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A);
+	    ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B);
+	    ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C);
+	    ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D);
+	    ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E);
+	    ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F);
+
+	    ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP);
+	    ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP);
+	    ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
+	    ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+	    ulData     = INREG(RADEON_GPIO_MONID);
+	    ulData    &= ~RADEON_GPIO_A_0;
+	    OUTREG(RADEON_GPIO_MONID, ulData);
+
+	    OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c);
+
+	    OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012);
+
+	    OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+	    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+	    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+	    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+	    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+	    for (i = 0; i < 200; i++) {
+		ulData     = INREG(RADEON_GPIO_MONID);
+		bConnected = (ulData & RADEON_GPIO_Y_0)?1:0;
+		if (!bConnected) break;
+
+		usleep(1000);
+	    }
+
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E);
+	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F);
+	    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP);
+	    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP);
+	    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID);
+	    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID);
+	    OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL);
+	    OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL);
+	    OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL);
+	    OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID);
+        } else {
+	    unsigned long ulOrigPIXCLKSDATA;
+	    unsigned long ulOrigTV_MASTER_CNTL;
+	    unsigned long ulOrigTV_DAC_CNTL;
+	    unsigned long ulOrigTV_PRE_DAC_MUX_CNTL;
+	    unsigned long ulOrigDAC_CNTL2;
+	    unsigned long ulData;
+	    unsigned long ulMask;
+
+	    ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+
+	    ulData            = ulOrigPIXCLKSDATA;
+	    ulData           &= ~(RADEON_PIX2CLK_ALWAYS_ONb
+				  | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
+	    ulMask            = ~(RADEON_PIX2CLK_ALWAYS_ONb
+			  | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
+	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask);
+
+	    ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL);
+	    ulData               = ulOrigTV_MASTER_CNTL;
+	    ulData              &= ~RADEON_TVCLK_ALWAYS_ONb;
+	    OUTREG(RADEON_TV_MASTER_CNTL, ulData);
+
+	    ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2);
+	    ulData          = ulOrigDAC_CNTL2;
+	    ulData          &= ~RADEON_DAC2_DAC2_CLK_SEL;
+	    OUTREG(RADEON_DAC_CNTL2, ulData);
+
+	    ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL);
+
+	    ulData  = 0x00880213;
+	    OUTREG(RADEON_TV_DAC_CNTL, ulData);
+
+	    ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
+
+	    ulData  =  (RADEON_Y_RED_EN
+			| RADEON_C_GRN_EN
+			| RADEON_CMP_BLU_EN
+			| RADEON_RED_MX_FORCE_DAC_DATA
+			| RADEON_GRN_MX_FORCE_DAC_DATA
+			| RADEON_BLU_MX_FORCE_DAC_DATA);
+            if (IS_R300_VARIANT)
+		ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
+	    else
+		ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
+	    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData);
+
+	    usleep(10000);
+
+	    ulData     = INREG(RADEON_TV_DAC_CNTL);
+	    bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0;
+
+	    ulData    = ulOrigPIXCLKSDATA;
+	    ulMask    = 0xFFFFFFFFL;
+	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask);
+
+	    OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL);
+	    OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2);
+	    OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL);
+	    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL);
+	}
+#endif
+	return MT_UNKNOWN;
+    }
+
+    return(bConnected ? MT_CRT : MT_NONE);
+}
+#endif
+
+RADEONMonitorType
+legacy_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+    RADEONInfoPtr info      = RADEONPTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONMonitorType found = MT_NONE;
+
+    if (OUTPUT_IS_TV) {
+	if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
+	    if (radeon_output->type == OUTPUT_STV)
+		radeon_output->MonType = MT_STV;
+	    else
+		radeon_output->MonType = MT_CTV;
+	} else {
+	    if (info->InternalTVOut) {
+		if (radeon_output->load_detection)
+		    radeon_output->MonType = radeon_detect_tv(pScrn);
+		else
+		    radeon_output->MonType = MT_NONE;
+	    }
+	}
+    } else {
+	if (radeon_output->DACType == DAC_PRIMARY) {
+	    if (radeon_output->load_detection)
+		found = radeon_detect_primary_dac(pScrn, TRUE);
+	} else if (radeon_output->DACType == DAC_TVDAC) {
+	    if (radeon_output->load_detection) {
+		if (info->ChipFamily == CHIP_FAMILY_R200)
+		    found = radeon_detect_ext_dac(pScrn);
+		else
+		    found = radeon_detect_tv_dac(pScrn, TRUE);
+	    } else
+		found = MT_NONE;
+	}
+    }
+
+    return found;
+}
+
+/*
+ * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant).
+ *
+ */
+static void
+RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    if (IsPrimaryDAC) {
+	CARD32 dac_cntl;
+	CARD32 dac_macro_cntl = 0;
+	dac_cntl = INREG(RADEON_DAC_CNTL);
+	dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL);
+	if (IsOn) {
+	    dac_cntl &= ~RADEON_DAC_PDWN;
+	    dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
+				RADEON_DAC_PDWN_G |
+				RADEON_DAC_PDWN_B);
+	} else {
+	    dac_cntl |= RADEON_DAC_PDWN;
+	    dac_macro_cntl |= (RADEON_DAC_PDWN_R |
+			       RADEON_DAC_PDWN_G |
+			       RADEON_DAC_PDWN_B);
+	}
+	OUTREG(RADEON_DAC_CNTL, dac_cntl);
+	OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
+    } else {
+	CARD32 tv_dac_cntl;
+	CARD32 fp2_gen_cntl;
+
+	switch(info->ChipFamily)
+	{
+	case CHIP_FAMILY_R420:
+	case CHIP_FAMILY_RV410:
+	    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+	    if (IsOn) {
+		tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
+				 R420_TV_DAC_GDACPD |
+				 R420_TV_DAC_BDACPD |
+				 RADEON_TV_DAC_BGSLEEP);
+	    } else {
+		tv_dac_cntl |= (R420_TV_DAC_RDACPD |
+				R420_TV_DAC_GDACPD |
+				R420_TV_DAC_BDACPD |
+				RADEON_TV_DAC_BGSLEEP);
+	    }
+	    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+	    break;
+	case CHIP_FAMILY_R200:
+	    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
+	    if (IsOn) {
+		fp2_gen_cntl |= RADEON_FP2_DVO_EN;
+	    } else {
+		fp2_gen_cntl &= ~RADEON_FP2_DVO_EN;
+	    }
+	    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+	    break;
+
+	default:
+	    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+	    if (IsOn) {
+		tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
+				 RADEON_TV_DAC_GDACPD |
+				 RADEON_TV_DAC_BDACPD |
+				 RADEON_TV_DAC_BGSLEEP);
+	    } else {
+		tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
+				RADEON_TV_DAC_GDACPD |
+				RADEON_TV_DAC_BDACPD |
+				RADEON_TV_DAC_BGSLEEP);
+	    }
+	    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+	    break;
+	}
+    }
+}
+
+/* This is to be used enable/disable displays dynamically */
+static void
+RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONSavePtr save = info->ModeReg;
+    unsigned char * RADEONMMIO = info->MMIO;
+    unsigned long tmp;
+    RADEONOutputPrivatePtr radeon_output;
+    int tv_dac_change = 0, o;
+    radeon_output = output->driver_private;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+    for (o = 0; o < xf86_config->num_output; o++) {
+	if (output == xf86_config->output[o]) {
+	    break;
+	}
+    }
+
+    if (bEnable) {
+	ErrorF("enable montype: %d\n", radeon_output->MonType);
+	if (radeon_output->MonType == MT_CRT) {
+	    if (radeon_output->DACType == DAC_PRIMARY) {
+		info->output_crt1 |= (1 << o);
+		tmp = INREG(RADEON_CRTC_EXT_CNTL);
+		tmp |= RADEON_CRTC_CRT_ON;
+		OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
+		save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
+		RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
+	    } else if (radeon_output->DACType == DAC_TVDAC) {
+		info->output_crt2 |= (1 << o);
+		if (info->ChipFamily == CHIP_FAMILY_R200) {
+		    tmp = INREG(RADEON_FP2_GEN_CNTL);
+		    tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
+		    save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		} else {
+		    tmp = INREG(RADEON_CRTC2_GEN_CNTL);
+		    tmp |= RADEON_CRTC2_CRT2_ON;
+		    OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
+		    save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
+		}
+		tv_dac_change = 1;
+	    }
+	} else if (radeon_output->MonType == MT_DFP) {
+	    if (radeon_output->TMDSType == TMDS_INT) {
+		info->output_dfp1 |= (1 << o);
+		tmp = INREG(RADEON_FP_GEN_CNTL);
+		tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+		OUTREG(RADEON_FP_GEN_CNTL, tmp);
+		save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+	    } else if (radeon_output->TMDSType == TMDS_EXT) {
+		info->output_dfp2 |= (1 << o);
+		tmp = INREG(RADEON_FP2_GEN_CNTL);
+		tmp &= ~RADEON_FP2_BLANK_EN;
+		tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		OUTREG(RADEON_FP2_GEN_CNTL, tmp);
+		save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		save->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
+	    }
+	} else if (radeon_output->MonType == MT_LCD) {
+	    info->output_lcd1 |= (1 << o);
+	    tmp = INREG(RADEON_LVDS_GEN_CNTL);
+	    tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
+	    tmp &= ~(RADEON_LVDS_DISPLAY_DIS);
+	    usleep (radeon_output->PanelPwrDly * 1000);
+	    OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
+	    save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
+	    save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
+	} else if (radeon_output->MonType == MT_STV ||
+		   radeon_output->MonType == MT_CTV) {
+	    info->output_tv1 |= (1 << o);
+	    tmp = INREG(RADEON_TV_MASTER_CNTL);
+	    tmp |= RADEON_TV_ON;
+	    OUTREG(RADEON_TV_MASTER_CNTL, tmp);
+	    tv_dac_change = 2;
+	    radeon_output->tv_on = TRUE;
+	}
+    } else {
+	ErrorF("disable montype: %d\n", radeon_output->MonType);
+	if (radeon_output->MonType == MT_CRT) {
+	    if (radeon_output->DACType == DAC_PRIMARY) {
+		info->output_crt1 &= ~(1 << o);
+		if (!info->output_crt1) {
+		    tmp = INREG(RADEON_CRTC_EXT_CNTL);
+		    tmp &= ~RADEON_CRTC_CRT_ON;
+		    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
+		    save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
+		    RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
+		}
+	    } else if (radeon_output->DACType == DAC_TVDAC) {
+		info->output_crt2 &= ~(1 << o);
+		tv_dac_change = 1;
+		if (!info->output_crt2) {
+		    if (info->ChipFamily == CHIP_FAMILY_R200) {
+			tmp = INREG(RADEON_FP2_GEN_CNTL);
+			tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+			OUTREG(RADEON_FP2_GEN_CNTL, tmp);
+			save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		    } else {
+			tmp = INREG(RADEON_CRTC2_GEN_CNTL);
+			tmp &= ~RADEON_CRTC2_CRT2_ON;
+			OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
+			save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
+		    }
+		}
+	    }
+	} else if (radeon_output->MonType == MT_DFP) {
+	    if (radeon_output->TMDSType == TMDS_INT) {
+		info->output_dfp1 &= ~(1 << o);
+		if (!info->output_dfp1) {
+		    tmp = INREG(RADEON_FP_GEN_CNTL);
+		    tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+		    OUTREG(RADEON_FP_GEN_CNTL, tmp);
+		    save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+		}
+	    } else if (radeon_output->TMDSType == TMDS_EXT) {
+		info->output_dfp2 &= ~(1 << o);
+		if (!info->output_dfp2) {
+		    tmp = INREG(RADEON_FP2_GEN_CNTL);
+		    tmp |= RADEON_FP2_BLANK_EN;
+		    tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
+		    save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		    save->fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
+		}
+	    }
+	} else if (radeon_output->MonType == MT_LCD) {
+	    info->output_lcd1 &= ~(1 << o);
+	    if (!info->output_lcd1) {
+		unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+		if (info->IsMobility || info->IsIGP) {
+		    /* Asic bug, when turning off LVDS_ON, we have to make sure
+		       RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+		    */
+		    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
+		}
+		tmp = INREG(RADEON_LVDS_GEN_CNTL);
+		tmp |= RADEON_LVDS_DISPLAY_DIS;
+		tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
+		OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
+		save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
+		save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
+		if (info->IsMobility || info->IsIGP) {
+		    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
+		}
+	    }
+	} else if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) {
+	    info->output_tv1 &= ~(1 << o);
+	    tv_dac_change = 2;
+	    if (!info->output_tv1) {
+		tmp = INREG(RADEON_TV_MASTER_CNTL);
+		tmp &= ~RADEON_TV_ON;
+		OUTREG(RADEON_TV_MASTER_CNTL, tmp);
+		radeon_output->tv_on = FALSE;
+	    }
+	}
+    }
+
+    if (tv_dac_change) {
+	if (bEnable)
+	    info->tv_dac_enable_mask |= tv_dac_change;
+	else
+	    info->tv_dac_enable_mask &= ~tv_dac_change;
+
+	if (bEnable && info->tv_dac_enable_mask)
+	    RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
+	else if (!bEnable && info->tv_dac_enable_mask == 0)
+	    RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
+
+    }
+}
+
+void
+legacy_output_dpms(xf86OutputPtr output, int mode)
+{
+    ScrnInfoPtr pScrn  = output->scrn;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
+    switch(mode) {
+    case DPMSModeOn:
+	RADEONEnableDisplay(output, TRUE);
+	break;
+    case DPMSModeOff:
+    case DPMSModeSuspend:
+    case DPMSModeStandby:
+	RADEONEnableDisplay(output, FALSE);
+	break;
+    }
+}
+
+static void
+RADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save,
+		      DisplayModePtr mode, BOOL IsPrimary)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONEntPtr  pRADEONEnt = RADEONEntPriv(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int i;
+    CARD32 tmp = info->SavedReg->tmds_pll_cntl & 0xfffff;
+
+    for (i=0; i<4; i++) {
+	if (radeon_output->tmds_pll[i].freq == 0) break;
+	if ((CARD32)(mode->Clock/10) < radeon_output->tmds_pll[i].freq) {
+	    tmp = radeon_output->tmds_pll[i].value ;
+	    break;
+	}
+    }
+
+    if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) {
+	if (tmp & 0xfff00000)
+	    save->tmds_pll_cntl = tmp;
+	else {
+	    save->tmds_pll_cntl = info->SavedReg->tmds_pll_cntl & 0xfff00000;
+	    save->tmds_pll_cntl |= tmp;
+	}
+    } else save->tmds_pll_cntl = tmp;
+
+    save->tmds_transmitter_cntl = info->SavedReg->tmds_transmitter_cntl &
+					~(RADEON_TMDS_TRANSMITTER_PLLRST);
+
+    if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2)
+	save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
+    else /* weird, RV chips got this bit reversed? */
+        save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN);
+
+    save->fp_gen_cntl = info->SavedReg->fp_gen_cntl |
+			 (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
+			  RADEON_FP_CRTC_DONT_SHADOW_HEND );
+
+    save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+
+    if (pScrn->rgbBits == 8)
+        save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
+    else
+        save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
+
+
+    if (IsPrimary) {
+	if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) {
+	    save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
+	    if (mode->Flags & RADEON_USE_RMX) 
+		save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
+	    else
+		save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
+	} else 
+	    save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1;
+    } else {
+	if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) {
+	    save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
+	    save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
+	} else 
+	    save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
+    }
+
+}
+
+static void
+RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save,
+		       DisplayModePtr mode, BOOL IsPrimary)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
+
+    if (pScrn->rgbBits == 8) 
+	save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl |
+				RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
+    else
+	save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
+				~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
+
+    save->fp2_gen_cntl &= ~(RADEON_FP2_ON |
+			    RADEON_FP2_DVO_EN |
+			    RADEON_FP2_DVO_RATE_SEL_SDR);
+
+
+    /* XXX: these may be oem specific */
+    if (IS_R300_VARIANT) {
+	save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
+#if 0
+	if (mode->Clock > 165000)
+	    save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;
+#endif
+    }
+
+    if (IsPrimary) {
+        if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
+            save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
+	    if (mode->Flags & RADEON_USE_RMX)
+		save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
+        } else {
+            save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
+	}
+    } else {
+        if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
+            save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
+            save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
+        } else {
+            save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
+        }
+    }
+
+}
+
+static void
+RADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save,
+			DisplayModePtr mode, BOOL IsPrimary)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+
+    save->lvds_pll_cntl = (info->SavedReg->lvds_pll_cntl |
+			   RADEON_LVDS_PLL_EN);
+
+    save->lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
+
+    save->lvds_gen_cntl = info->SavedReg->lvds_gen_cntl;
+    save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
+    save->lvds_gen_cntl &= ~(RADEON_LVDS_ON |
+			     RADEON_LVDS_BLON |
+			     RADEON_LVDS_EN |
+			     RADEON_LVDS_RST_FM);
+
+    if (IS_R300_VARIANT)
+	save->lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
+
+    if (IsPrimary) {
+	if (IS_R300_VARIANT) {
+	    if (mode->Flags & RADEON_USE_RMX)
+		save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
+	} else
+	    save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
+    } else {
+	if (IS_R300_VARIANT) {
+	    save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
+	} else
+	    save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
+    }
+
+}
+
+static void
+RADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save,
+		       DisplayModePtr mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int    xres = mode->HDisplay;
+    int    yres = mode->VDisplay;
+    float  Hratio, Vratio;
+
+    save->fp_vert_stretch = info->SavedReg->fp_vert_stretch &
+	                    RADEON_VERT_STRETCH_RESERVED;
+    save->fp_horz_stretch = info->SavedReg->fp_horz_stretch &
+	                    (RADEON_HORZ_FP_LOOP_STRETCH |
+	                     RADEON_HORZ_AUTO_RATIO_INC);
+
+    if (radeon_output->MonType != MT_LCD && radeon_output->MonType != MT_DFP)
+	return;
+
+    if (radeon_output->PanelXRes == 0 || radeon_output->PanelYRes == 0) {
+	Hratio = 1.0;
+	Vratio = 1.0;
+    } else {
+	if (xres > radeon_output->PanelXRes) xres = radeon_output->PanelXRes;
+	if (yres > radeon_output->PanelYRes) yres = radeon_output->PanelYRes;
+	    
+	Hratio = (float)xres/(float)radeon_output->PanelXRes;
+	Vratio = (float)yres/(float)radeon_output->PanelYRes;
+    }
+
+    if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) {
+	save->fp_horz_stretch |= ((xres/8-1)<<16);
+    } else {
+	save->fp_horz_stretch |= ((((unsigned long)
+				    (Hratio * RADEON_HORZ_STRETCH_RATIO_MAX)) &
+				   RADEON_HORZ_STRETCH_RATIO_MASK) |
+				  RADEON_HORZ_STRETCH_BLEND |
+				  RADEON_HORZ_STRETCH_ENABLE |
+				  ((radeon_output->PanelXRes/8-1)<<16));
+    }
+
+    if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) {
+	save->fp_vert_stretch |= ((yres-1)<<12);
+    } else {
+	save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX)) &
+				   RADEON_VERT_STRETCH_RATIO_MASK) |
+				  RADEON_VERT_STRETCH_ENABLE |
+				  RADEON_VERT_STRETCH_BLEND |
+				  ((radeon_output->PanelYRes-1)<<12));
+    }
+
+}
+
+static void
+RADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save,
+		       DisplayModePtr mode, BOOL IsPrimary)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+
+    if (IsPrimary) {
+	if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
+            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
+					~RADEON_DISP_DAC_SOURCE_MASK;
+        } else {
+            save->dac2_cntl = info->SavedReg->dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL);
+        }
+    } else {
+        if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
+            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
+					~RADEON_DISP_DAC_SOURCE_MASK;
+            save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
+        } else {
+            save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC_CLK_SEL;
+        }
+    }
+    save->dac_cntl = (RADEON_DAC_MASK_ALL
+		      | RADEON_DAC_VGA_ADR_EN
+		      | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN));
+
+    save->dac_macro_cntl = info->SavedReg->dac_macro_cntl;
+}
+
+static void
+RADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (info->ChipFamily == CHIP_FAMILY_R420 ||
+	info->ChipFamily == CHIP_FAMILY_RV410) {
+	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl &
+			     ~(RADEON_TV_DAC_STD_MASK |
+			       RADEON_TV_DAC_BGADJ_MASK |
+			       R420_TV_DAC_DACADJ_MASK |
+			       R420_TV_DAC_RDACPD |
+			       R420_TV_DAC_GDACPD |
+			       R420_TV_DAC_GDACPD |
+			       R420_TV_DAC_TVENABLE);
+    } else {
+	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl &
+			     ~(RADEON_TV_DAC_STD_MASK |
+			       RADEON_TV_DAC_BGADJ_MASK |
+			       RADEON_TV_DAC_DACADJ_MASK |
+			       RADEON_TV_DAC_RDACPD |
+			       RADEON_TV_DAC_GDACPD |
+			       RADEON_TV_DAC_GDACPD);
+    }
+
+    save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
+			  RADEON_TV_DAC_NHOLD |
+			  RADEON_TV_DAC_STD_PS2 |
+			  radeon_output->tv_dac_adj);
+
+}
+
+static void
+RADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save,
+			DisplayModePtr mode, BOOL IsPrimary)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+
+    /*0x0028023;*/
+    RADEONInitTvDacCntl(output, save);
+
+    if (IS_R300_VARIANT)
+	save->gpiopad_a = info->SavedReg->gpiopad_a | 1;
+
+    save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL;
+
+    if (IsPrimary) {
+        if (IS_R300_VARIANT) {
+            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
+					~RADEON_DISP_TVDAC_SOURCE_MASK;
+            save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
+        } else if (info->ChipFamily == CHIP_FAMILY_R200) {
+	    save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
+				  ~(R200_FP2_SOURCE_SEL_MASK |
+				    RADEON_FP2_DVO_RATE_SEL_SDR);
+	} else {
+            save->disp_hw_debug = info->SavedReg->disp_hw_debug | RADEON_CRT2_DISP1_SEL;
+        }
+    } else {
+        if (IS_R300_VARIANT) {
+            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
+					~RADEON_DISP_TVDAC_SOURCE_MASK;
+            save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+	} else if (info->ChipFamily == CHIP_FAMILY_R200) {
+	    save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
+				  ~(R200_FP2_SOURCE_SEL_MASK |
+				    RADEON_FP2_DVO_RATE_SEL_SDR);
+            save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
+        } else {
+            save->disp_hw_debug = info->SavedReg->disp_hw_debug &
+					~RADEON_CRT2_DISP1_SEL;
+        }
+    }
+}
+
+static void
+RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
+			  DisplayModePtr mode, xf86OutputPtr output,
+			  int crtc_num)
+{
+    Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (crtc_num == 0)
+	RADEONInitRMXRegisters(output, save, mode);
+
+    if (radeon_output->MonType == MT_CRT) {
+	if (radeon_output->DACType == DAC_PRIMARY) {
+	    RADEONInitDACRegisters(output, save, mode, IsPrimary);
+	} else {
+	    RADEONInitDAC2Registers(output, save, mode, IsPrimary);
+	}
+    } else if (radeon_output->MonType == MT_LCD) {
+	RADEONInitLVDSRegisters(output, save, mode, IsPrimary);
+    } else if (radeon_output->MonType == MT_DFP) {
+	if (radeon_output->TMDSType == TMDS_INT) {
+	    RADEONInitFPRegisters(output, save, mode, IsPrimary);
+	} else {
+	    RADEONInitFP2Registers(output, save, mode, IsPrimary);
+	}
+    } else if (radeon_output->MonType == MT_STV ||
+	       radeon_output->MonType == MT_CTV) {
+	RADEONInitTVRegisters(output, save, mode, IsPrimary);
+    }
+}
+
+void
+legacy_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+		  DisplayModePtr adjusted_mode)
+{
+    ScrnInfoPtr	    pScrn = output->scrn;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    xf86CrtcPtr	crtc = output->crtc;
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+
+    RADEONInitOutputRegisters(pScrn, info->ModeReg, adjusted_mode, output, radeon_crtc->crtc_id);
+
+    if (radeon_crtc->crtc_id == 0)
+	RADEONRestoreRMXRegisters(pScrn, info->ModeReg);
+
+    switch(radeon_output->MonType) {
+    case MT_LCD:
+	ErrorF("restore LVDS\n");
+	RADEONRestoreLVDSRegisters(pScrn, info->ModeReg);
+	break;
+    case MT_DFP:
+	if (radeon_output->TMDSType == TMDS_INT) {
+	    ErrorF("restore FP\n");
+	    RADEONRestoreFPRegisters(pScrn, info->ModeReg);
+	} else {
+	    ErrorF("restore FP2\n");
+	    if (info->IsAtomBios)
+		atombios_external_tmds_setup(output, mode);
+	    else
+		RADEONRestoreDVOChip(pScrn, output);
+	    RADEONRestoreFP2Registers(pScrn, info->ModeReg);
+	}
+	break;
+    case MT_STV:
+    case MT_CTV:
+	ErrorF("restore tv\n");
+	RADEONRestoreDACRegisters(pScrn, info->ModeReg);
+	RADEONRestoreTVRegisters(pScrn, info->ModeReg);
+	break;
+    default:
+	ErrorF("restore dac\n");
+	RADEONRestoreDACRegisters(pScrn, info->ModeReg);
+    }
+
+}
+
+/* the following functions are based on the load detection code
+ * in the beos radeon driver by Thomas Kurschel and the existing
+ * load detection code in this driver.
+ */
+static RADEONMonitorType
+radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 vclk_ecp_cntl, crtc_ext_cntl;
+    CARD32 dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
+    RADEONMonitorType found = MT_NONE;
+
+    /* save the regs we need */
+    vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+    crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
+    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
+    dac_cntl = INREG(RADEON_DAC_CNTL);
+    dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL);
+
+    tmp = vclk_ecp_cntl &
+	~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
+    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
+
+    tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
+
+    tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
+	RADEON_DAC_FORCE_DATA_EN;
+
+    if (color)
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
+    else
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
+
+    if (IS_R300_VARIANT)
+	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+    else
+	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
+
+    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
+
+    tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
+    tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
+    OUTREG(RADEON_DAC_CNTL, tmp);
+
+    tmp &= ~(RADEON_DAC_PDWN_R |
+	     RADEON_DAC_PDWN_G |
+	     RADEON_DAC_PDWN_B);
+
+    OUTREG(RADEON_DAC_MACRO_CNTL, tmp);
+
+    usleep(2000);
+
+    if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) {
+	found = MT_CRT;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "Found %s CRT connected to primary DAC\n",
+		    color ? "color" : "bw");
+    }
+
+    /* restore the regs we used */
+    OUTREG(RADEON_DAC_CNTL, dac_cntl);
+    OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
+    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+    OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
+
+    return found;
+}
+
+static RADEONMonitorType
+radeon_detect_ext_dac(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
+    CARD32 disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
+    CARD32 disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
+    CARD32 tmp, crtc2_h_total_disp, crtc2_v_total_disp;
+    CARD32 crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
+    RADEONMonitorType found = MT_NONE;
+    int connected = 0;
+    int i = 0;
+
+    /* save the regs we need */
+    gpio_monid = INREG(RADEON_GPIO_MONID);
+    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
+    disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
+    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+    disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A);
+    disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B);
+    disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C);
+    disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D);
+    disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E);
+    disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F);
+    crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP);
+    crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP);
+    crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
+    crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+    tmp = INREG(RADEON_GPIO_MONID);
+    tmp &= ~RADEON_GPIO_A_0;
+    OUTREG(RADEON_GPIO_MONID, tmp);
+
+    OUTREG(RADEON_FP2_GEN_CNTL,
+	   RADEON_FP2_ON |
+	   RADEON_FP2_PANEL_FORMAT |
+	   R200_FP2_SOURCE_SEL_TRANS_UNIT |
+	   RADEON_FP2_DVO_EN |
+	   R200_FP2_DVO_RATE_SEL_SDR);
+
+    OUTREG(RADEON_DISP_OUTPUT_CNTL,
+	   RADEON_DISP_DAC_SOURCE_RMX |
+	   RADEON_DISP_TRANS_MATRIX_GRAPHICS);
+
+    OUTREG(RADEON_CRTC2_GEN_CNTL,
+	   RADEON_CRTC2_EN |
+	   RADEON_CRTC2_DISP_REQ_EN_B);
+
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+
+    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+    for (i = 0; i < 200; i++) {
+	tmp = INREG(RADEON_GPIO_MONID);
+	if (tmp & RADEON_GPIO_Y_0)
+	    connected = 1;
+	else
+	    connected = 0;
+
+	if (!connected)
+	    break;
+
+	usleep(1000);
+    }
+
+    if (connected)
+	found = MT_CRT;
+
+    /* restore the regs we used */
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
+    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
+    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
+    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
+    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
+    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+    OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+    OUTREG(RADEON_GPIO_MONID, gpio_monid);
+
+    return found;
+}
+
+static RADEONMonitorType
+radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+    CARD32 disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+    RADEONMonitorType found = MT_NONE;
+
+    /* save the regs we need */
+    pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+    gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0;
+    disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0;
+    disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0;
+    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
+    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
+
+    tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
+			   | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
+    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
+
+    if (IS_R300_VARIANT) {
+	OUTREGP(RADEON_GPIOPAD_A, 1, ~1 );
+    }
+
+    tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+    tmp |= RADEON_CRTC2_CRT2_ON |
+	(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+
+    OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
+
+    if (IS_R300_VARIANT) {
+	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+	OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp);
+    } else {
+	tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+	OUTREG(RADEON_DISP_HW_DEBUG, tmp);
+    }
+
+    tmp = RADEON_TV_DAC_NBLANK |
+	RADEON_TV_DAC_NHOLD |
+	RADEON_TV_MONITOR_DETECT_EN |
+	RADEON_TV_DAC_STD_PS2;
+
+    OUTREG(RADEON_TV_DAC_CNTL, tmp);
+
+    tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
+	RADEON_DAC2_FORCE_DATA_EN;
+
+    if (color)
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
+    else
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
+
+    if (IS_R300_VARIANT)
+	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+    else
+	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
+
+    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
+
+    tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
+    OUTREG(RADEON_DAC_CNTL2, tmp);
+
+    usleep(10000);
+
+    if (IS_R300_VARIANT) {
+	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) {
+	    found = MT_CRT;
+	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+			"Found %s CRT connected to TV DAC\n",
+			color ? "color" : "bw");
+	}
+    } else {
+	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) {
+	    found = MT_CRT;
+	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+			"Found %s CRT connected to TV DAC\n",
+			color ? "color" : "bw");
+	}
+    }
+
+    /* restore regs we used */
+    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
+    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+
+    if (IS_R300_VARIANT) {
+	OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+	OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 );
+    } else {
+	OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+    }
+    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl);
+
+    return found;
+}
+
+static RADEONMonitorType
+r300_detect_tv(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl;
+    CARD32 gpiopad_a, disp_output_cntl;
+    RADEONMonitorType found = MT_NONE;
+
+    /* save the regs we need */
+    gpiopad_a = INREG(RADEON_GPIOPAD_A);
+    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
+    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
+    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+    disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
+
+    OUTREGP(RADEON_GPIOPAD_A, 0, ~1 );
+
+    OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL );
+
+    OUTREG(RADEON_CRTC2_GEN_CNTL,
+	   RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT );
+
+    tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+    tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+    OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp);
+
+    OUTREG(RADEON_DAC_EXT_CNTL,
+	   RADEON_DAC2_FORCE_BLANK_OFF_EN |
+	   RADEON_DAC2_FORCE_DATA_EN |
+	   RADEON_DAC_FORCE_DATA_SEL_RGB |
+	   (0xec << RADEON_DAC_FORCE_DATA_SHIFT ));
+
+    OUTREG(RADEON_TV_DAC_CNTL,
+	   RADEON_TV_DAC_STD_NTSC |
+	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
+	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
+
+    INREG(RADEON_TV_DAC_CNTL);
+
+    usleep(4000);
+
+    OUTREG(RADEON_TV_DAC_CNTL,
+	   RADEON_TV_DAC_NBLANK |
+	   RADEON_TV_DAC_NHOLD |
+	   RADEON_TV_MONITOR_DETECT_EN |
+	   RADEON_TV_DAC_STD_NTSC |
+	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
+	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
+
+    INREG(RADEON_TV_DAC_CNTL);
+
+    usleep(6000);
+
+    tmp = INREG(RADEON_TV_DAC_CNTL);
+    if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) {
+	found = MT_STV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "S-Video TV connection detected\n");
+    } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) {
+	found = MT_CTV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "Composite TV connection detected\n" );
+    }
+
+    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl );
+    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+    OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
+    OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+
+    return found;
+}
+
+static RADEONMonitorType
+radeon_detect_tv(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 tmp, dac_cntl2, tv_master_cntl;
+    CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl;
+    RADEONMonitorType found = MT_NONE;
+
+    if (IS_R300_VARIANT)
+	return r300_detect_tv(pScrn);
+
+    /* save the regs we need */
+    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
+    tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL);
+    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+    config_cntl = INREG(RADEON_CONFIG_CNTL);
+    tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
+
+    tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
+    OUTREG(RADEON_DAC_CNTL2, tmp);
+
+    tmp = tv_master_cntl | RADEON_TV_ON;
+    tmp &= ~(RADEON_TV_ASYNC_RST |
+	     RADEON_RESTART_PHASE_FIX |
+	     RADEON_CRT_FIFO_CE_EN |
+	     RADEON_TV_FIFO_CE_EN |
+	     RADEON_RE_SYNC_NOW_SEL_MASK);
+    tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
+
+    OUTREG(RADEON_TV_MASTER_CNTL, tmp);
+
+    tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
+	RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
+	(8 << RADEON_TV_DAC_BGADJ_SHIFT);
+
+    if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
+	tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
+    else
+	tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
+
+    OUTREG(RADEON_TV_DAC_CNTL, tmp);
+
+    tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
+	RADEON_RED_MX_FORCE_DAC_DATA |
+	RADEON_GRN_MX_FORCE_DAC_DATA |
+	RADEON_BLU_MX_FORCE_DAC_DATA |
+	(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
+
+    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
+
+    usleep(3000);
+
+    tmp = INREG(RADEON_TV_DAC_CNTL);
+    if (tmp & RADEON_TV_DAC_GDACDET) {
+	found = MT_STV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "S-Video TV connection detected\n");
+    } else if (tmp & RADEON_TV_DAC_BDACDET) {
+	found = MT_CTV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "Composite TV connection detected\n" );
+    }
+
+    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
+    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+    OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl);
+    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
+
+    return found;
+}
+
+/* disable all ouputs before enabling the ones we want */
+void
+RADEONDisableDisplays(ScrnInfoPtr pScrn) {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char * RADEONMMIO = info->MMIO;
+    unsigned long tmp, tmpPixclksCntl;
+
+
+    /* primary DAC */
+    tmp = INREG(RADEON_CRTC_EXT_CNTL);
+    tmp &= ~RADEON_CRTC_CRT_ON;
+    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
+    RADEONDacPowerSet(pScrn, FALSE, TRUE);
+
+    /* Secondary DAC */
+    if (info->ChipFamily == CHIP_FAMILY_R200) {
+	tmp = INREG(RADEON_FP2_GEN_CNTL);
+	tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+	OUTREG(RADEON_FP2_GEN_CNTL, tmp);
+    } else {
+	tmp = INREG(RADEON_CRTC2_GEN_CNTL);
+	tmp &= ~RADEON_CRTC2_CRT2_ON;
+	OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
+    }
+    RADEONDacPowerSet(pScrn, FALSE, FALSE);
+
+    /* turn off tv-out */
+    if (info->InternalTVOut) {
+	tmp = INREG(RADEON_TV_MASTER_CNTL);
+	tmp &= ~RADEON_TV_ON;
+	OUTREG(RADEON_TV_MASTER_CNTL, tmp);
+    }
+
+    /* FP 1 */
+    tmp = INREG(RADEON_FP_GEN_CNTL);
+    tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+    OUTREG(RADEON_FP_GEN_CNTL, tmp);
+
+    /* FP 2 */
+    tmp = INREG(RADEON_FP2_GEN_CNTL);
+    tmp |= RADEON_FP2_BLANK_EN;
+    tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
+
+    /* LVDS */
+    if (info->IsMobility) {
+	tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+	if (info->IsMobility || info->IsIGP) {
+	    /* Asic bug, when turning off LVDS_ON, we have to make sure
+	       RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+	    */
+	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
+	}
+	tmp = INREG(RADEON_LVDS_GEN_CNTL);
+	tmp |= RADEON_LVDS_DISPLAY_DIS;
+	tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
+	OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
+	if (info->IsMobility || info->IsIGP) {
+	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
+	}
+    }
+
+}
diff --git a/src/radeon.h b/src/radeon.h
index 7f4d001..47e1b89 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -842,13 +842,10 @@ extern void        RADEONInitMemMapRegisters(ScrnInfoPtr pScrn,
 					     RADEONInfoPtr info);
 extern void        RADEONInitDispBandwidth(ScrnInfoPtr pScrn);
 extern Bool        RADEONI2cInit(ScrnInfoPtr pScrn);
-extern void        RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag);
 extern Bool        RADEONSetupConnectors(ScrnInfoPtr pScrn);
 extern void        RADEONPrintPortMap(ScrnInfoPtr pScrn);
-extern void        RADEONEnableDisplay(xf86OutputPtr pPort, BOOL bEnable);
 extern void        RADEONDisableDisplays(ScrnInfoPtr pScrn);
 extern void        RADEONGetPanelInfo(ScrnInfoPtr pScrn);
-extern void        RADEONGetTVDacAdjInfo(xf86OutputPtr output);
 extern void        RADEONUnblank(ScrnInfoPtr pScrn);
 extern void        RADEONUnblank(ScrnInfoPtr pScrn);
 extern void        RADEONBlank(ScrnInfoPtr pScrn);
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index 8e66518..9034cf5 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -53,68 +53,27 @@
 #include "sarea.h"
 #endif
 
-void radeon_crtc_load_lut(xf86CrtcPtr crtc);
-
 extern void atombios_crtc_mode_set(xf86CrtcPtr crtc,
 				   DisplayModePtr mode,
 				   DisplayModePtr adjusted_mode,
 				   int x, int y);
+extern void legacy_crtc_mode_set(xf86CrtcPtr crtc,
+				 DisplayModePtr mode,
+				 DisplayModePtr adjusted_mode,
+				 int x, int y);
 extern void atombios_crtc_dpms(xf86CrtcPtr crtc, int mode);
+extern void legacy_crtc_dpms(xf86CrtcPtr crtc, int mode);
 
 static void
 radeon_crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
-    int mask;
-    ScrnInfoPtr pScrn = crtc->scrn;
-    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONInfoPtr info = RADEONPTR(crtc->scrn);
 
     if (IS_AVIVO_VARIANT) {
 	atombios_crtc_dpms(crtc, mode);
-	return;
-    }
-
-    mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS);
-
-
-    switch(mode) {
-    case DPMSModeOn:
-	if (radeon_crtc->crtc_id) {
-	    OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask);
-	} else {
-	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
-	    OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask);
-	}
-	break;
-    case DPMSModeStandby:
-	if (radeon_crtc->crtc_id) {
-	    OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask);
-	} else {
-	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
-	    OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask);
-	}
-	break;
-    case DPMSModeSuspend:
-	if (radeon_crtc->crtc_id) {
-	    OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask);
-	} else {
-	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
-	    OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask);
-	}
-	break;
-    case DPMSModeOff:
-	if (radeon_crtc->crtc_id) {
-	    OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
-	} else {
-	    OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B);
-	    OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask);
-	}
-	break;
+    } else {
+	legacy_crtc_dpms(crtc, mode);
     }
-  
-    if (mode != DPMSModeOff)
-	radeon_crtc_load_lut(crtc);
 }
 
 static Bool
@@ -133,491 +92,6 @@ radeon_crtc_mode_prepare(xf86CrtcPtr crtc)
     radeon_crtc_dpms(crtc, DPMSModeOff);
 }
 
-/* Define common registers for requested video mode */
-static void
-RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info)
-{
-    save->ovr_clr            = 0;
-    save->ovr_wid_left_right = 0;
-    save->ovr_wid_top_bottom = 0;
-    save->ov0_scale_cntl     = 0;
-    save->subpic_cntl        = 0;
-    save->viph_control       = 0;
-    save->i2c_cntl_1         = 0;
-    save->rbbm_soft_reset    = 0;
-    save->cap0_trig_cntl     = 0;
-    save->cap1_trig_cntl     = 0;
-    save->bus_cntl           = info->BusCntl;
-    /*
-     * If bursts are enabled, turn on discards
-     * Radeon doesn't have write bursts
-     */
-    if (save->bus_cntl & (RADEON_BUS_READ_BURST))
-	save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN;
-}
-
-static void
-RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save)
-{
-    save->surface_cntl = 0;
-
-#if X_BYTE_ORDER == X_BIG_ENDIAN
-    /* We must set both apertures as they can be both used to map the entire
-     * video memory. -BenH.
-     */
-    switch (crtc->scrn->bitsPerPixel) {
-    case 16:
-	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP;
-	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP;
-	break;
-
-    case 32:
-	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP;
-	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP;
-	break;
-    }
-#endif
-
-}
-
-Bool
-RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save,
-		   int x, int y)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    int    Base;
-#ifdef XF86DRI
-    RADEONSAREAPrivPtr pSAREAPriv;
-    XF86DRISAREAPtr pSAREA;
-#endif
-
-    save->crtc_offset      = pScrn->fbOffset;
-#ifdef XF86DRI
-    if (info->allowPageFlip)
-	save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL;
-    else
-#endif
-	save->crtc_offset_cntl = 0;
-
-    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
-       if (IS_R300_VARIANT)
-          save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
-				     R300_CRTC_MICRO_TILE_BUFFER_DIS |
-				     R300_CRTC_MACRO_TILE_EN);
-       else
-          save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN;
-    }
-    else {
-       if (IS_R300_VARIANT)
-          save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
-				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
-				      R300_CRTC_MACRO_TILE_EN);
-       else
-          save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
-    }
-
-    Base = pScrn->fbOffset;
-
-    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
-        if (IS_R300_VARIANT) {
-	/* On r300/r400 when tiling is enabled crtc_offset is set to the address of
-	 * the surface.  the x/y offsets are handled by the X_Y tile reg for each crtc
-	 * Makes tiling MUCH easier.
-	 */
-             save->crtc_tile_x0_y0 = x | (y << 16);
-             Base &= ~0x7ff;
-         } else {
-	     /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the
-		drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes
-		flickering when scrolling vertically in a virtual screen, possibly because crtc will
-		pick up the new offset value at the end of each scanline, but the new offset_cntl value
-		only after a vsync. We'd probably need to wait (in drm) for vsync and only then update
-		OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */
-	     /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/
-#if 0
-	     /* try to get rid of flickering when scrolling at least for 2d */
-#ifdef XF86DRI
-	     if (!info->have3DWindows)
-#endif
-		 save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL;
-#endif
-	     
-             int byteshift = info->CurrentLayout.bitsPerPixel >> 4;
-             /* crtc uses 256(bytes)x8 "half-tile" start addresses? */
-             int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11;
-             Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
-             save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16);
-         }
-    }
-    else {
-       int offset = y * info->CurrentLayout.displayWidth + x;
-       switch (info->CurrentLayout.pixel_code) {
-       case 15:
-       case 16: offset *= 2; break;
-       case 24: offset *= 3; break;
-       case 32: offset *= 4; break;
-       }
-       Base += offset;
-    }
-
-    if (crtc->rotatedData != NULL) {
-	Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
-    }
-
-    Base &= ~7;                 /* 3 lower bits are always 0 */
-
-
-#ifdef XF86DRI
-    if (info->directRenderingInited) {
-	/* note cannot use pScrn->pScreen since this is unitialized when called from
-	   RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */
-        /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for
-	 *** pageflipping!
-	 ***/
-	pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
-	/* can't get at sarea in a semi-sane way? */
-	pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec));
-
-	pSAREA->frame.x = (Base  / info->CurrentLayout.pixel_bytes)
-	    % info->CurrentLayout.displayWidth;
-	pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes)
-	    / info->CurrentLayout.displayWidth;
-	pSAREA->frame.width = pScrn->frameX1 - x + 1;
-	pSAREA->frame.height = pScrn->frameY1 - y + 1;
-
-	if (pSAREAPriv->pfCurrentPage == 1) {
-	    Base += info->backOffset - info->frontOffset;
-	}
-    }
-#endif
-    save->crtc_offset = Base;
-
-    return TRUE;
-
-}
-
-/* Define CRTC registers for requested video mode */
-Bool
-RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
-			DisplayModePtr mode)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    int    format;
-    int    hsync_start;
-    int    hsync_wid;
-    int    vsync_wid;
-
-    switch (info->CurrentLayout.pixel_code) {
-    case 4:  format = 1; break;
-    case 8:  format = 2; break;
-    case 15: format = 3; break;      /*  555 */
-    case 16: format = 4; break;      /*  565 */
-    case 24: format = 5; break;      /*  RGB */
-    case 32: format = 6; break;      /* xRGB */
-    default:
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Unsupported pixel depth (%d)\n",
-		   info->CurrentLayout.bitsPerPixel);
-	return FALSE;
-    }
-
-    /*save->bios_4_scratch = info->SavedReg->bios_4_scratch;*/
-    save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
-			   | RADEON_CRTC_EN
-			   | (format << 8)
-			   | ((mode->Flags & V_DBLSCAN)
-			      ? RADEON_CRTC_DBL_SCAN_EN
-			      : 0)
-			   | ((mode->Flags & V_CSYNC)
-			      ? RADEON_CRTC_CSYNC_EN
-			      : 0)
-			   | ((mode->Flags & V_INTERLACE)
-			      ? RADEON_CRTC_INTERLACE_EN
-			      : 0));
-
-    save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN|
-			    RADEON_CRTC_VSYNC_DIS |
-			    RADEON_CRTC_HSYNC_DIS |
-			    RADEON_CRTC_DISPLAY_DIS);
-
-    save->disp_merge_cntl = info->SavedReg->disp_merge_cntl;
-    save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
-
-    save->crtc_more_cntl = 0;
-    if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
-        (info->ChipFamily == CHIP_FAMILY_RS200)) {
-        /* This is to workaround the asic bug for RMX, some versions
-           of BIOS dosen't have this register initialized correctly.
-	*/
-        save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
-    }
-
-    save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
-			       | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff)
-				  << 16));
-
-    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
-    if (!hsync_wid)       hsync_wid = 1;
-    hsync_start = mode->CrtcHSyncStart - 8;
-
-    save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
-				  | ((hsync_wid & 0x3f) << 16)
-				  | ((mode->Flags & V_NHSYNC)
-				     ? RADEON_CRTC_H_SYNC_POL
-				     : 0));
-
-				/* This works for double scan mode. */
-    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
-			       | ((mode->CrtcVDisplay - 1) << 16));
-
-    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
-    if (!vsync_wid)       vsync_wid = 1;
-
-    save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
-				  | ((vsync_wid & 0x1f) << 16)
-				  | ((mode->Flags & V_NVSYNC)
-				     ? RADEON_CRTC_V_SYNC_POL
-				     : 0));
-
-    save->crtc_pitch  = (((pScrn->displayWidth * pScrn->bitsPerPixel) +
-			  ((pScrn->bitsPerPixel * 8) -1)) /
-			 (pScrn->bitsPerPixel * 8));
-    save->crtc_pitch |= save->crtc_pitch << 16;
-    
-    save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid;
-    save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid;
-    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
-    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
-
-    if (info->IsDellServer) {
-	save->dac2_cntl = info->SavedReg->dac2_cntl;
-	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl;
-	save->crtc2_gen_cntl = info->SavedReg->crtc2_gen_cntl;
-	save->disp_hw_debug = info->SavedReg->disp_hw_debug;
-
-	save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
-	save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
-
-	/* For CRT on DAC2, don't turn it on if BIOS didn't
-	   enable it, even it's detected.
-	*/
-	save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
-	save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
-	save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
-    }
-
-    return TRUE;
-}
-
-Bool
-RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save,
-		    int x, int y)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    int    Base;
-#ifdef XF86DRI
-    RADEONSAREAPrivPtr pSAREAPriv;
-    XF86DRISAREAPtr pSAREA;
-#endif
-
-    /* It seems all fancy options apart from pflip can be safely disabled
-     */
-    save->crtc2_offset      = pScrn->fbOffset;
-#ifdef XF86DRI
-    if (info->allowPageFlip)
-	save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL;
-    else
-#endif
-	save->crtc2_offset_cntl = 0;
-
-    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
-       if (IS_R300_VARIANT)
-          save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
-				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
-				      R300_CRTC_MACRO_TILE_EN);
-       else
-          save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN;
-    }
-    else {
-       if (IS_R300_VARIANT)
-          save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
-				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
-				      R300_CRTC_MACRO_TILE_EN);
-       else
-          save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN;
-    }
-
-    Base = pScrn->fbOffset;
-
-    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
-        if (IS_R300_VARIANT) {
-	/* On r300/r400 when tiling is enabled crtc_offset is set to the address of
-	 * the surface.  the x/y offsets are handled by the X_Y tile reg for each crtc
-	 * Makes tiling MUCH easier.
-	 */
-             save->crtc2_tile_x0_y0 = x | (y << 16);
-             Base &= ~0x7ff;
-         } else {
-	     /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the
-		drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes
-		flickering when scrolling vertically in a virtual screen, possibly because crtc will
-		pick up the new offset value at the end of each scanline, but the new offset_cntl value
-		only after a vsync. We'd probably need to wait (in drm) for vsync and only then update
-		OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */
-	     /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/
-#if 0
-	     /* try to get rid of flickering when scrolling at least for 2d */
-#ifdef XF86DRI
-	     if (!info->have3DWindows)
-#endif
-		 save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL;
-#endif
-
-             int byteshift = info->CurrentLayout.bitsPerPixel >> 4;
-             /* crtc uses 256(bytes)x8 "half-tile" start addresses? */
-             int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11;
-             Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
-             save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16);
-         }
-    }
-    else {
-       int offset = y * info->CurrentLayout.displayWidth + x;
-       switch (info->CurrentLayout.pixel_code) {
-       case 15:
-       case 16: offset *= 2; break;
-       case 24: offset *= 3; break;
-       case 32: offset *= 4; break;
-       }
-       Base += offset;
-    }
-
-    if (crtc->rotatedData != NULL) {
-	Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
-    }
-
-    Base &= ~7;                 /* 3 lower bits are always 0 */
-
-#ifdef XF86DRI
-    if (info->directRenderingInited) {
-	/* note cannot use pScrn->pScreen since this is unitialized when called from
-	   RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */
-        /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for
-	 *** pageflipping!
-	 ***/
-	pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
-	/* can't get at sarea in a semi-sane way? */
-	pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec));
-
-	pSAREAPriv->crtc2_base = Base;
-
-	if (pSAREAPriv->pfCurrentPage == 1) {
-	    Base += info->backOffset - info->frontOffset;
-	}
-    }
-#endif
-    save->crtc2_offset = Base;
-
-    return TRUE;
-}
-
-/* Define CRTC2 registers for requested video mode */
-Bool
-RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
-			 DisplayModePtr mode)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    int    format;
-    int    hsync_start;
-    int    hsync_wid;
-    int    vsync_wid;
-
-    switch (info->CurrentLayout.pixel_code) {
-    case 4:  format = 1; break;
-    case 8:  format = 2; break;
-    case 15: format = 3; break;      /*  555 */
-    case 16: format = 4; break;      /*  565 */
-    case 24: format = 5; break;      /*  RGB */
-    case 32: format = 6; break;      /* xRGB */
-    default:
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Unsupported pixel depth (%d)\n",
-		   info->CurrentLayout.bitsPerPixel);
-	return FALSE;
-    }
-
-    save->crtc2_h_total_disp =
-	((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
-	 | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16));
-
-    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
-    if (!hsync_wid)       hsync_wid = 1;
-    hsync_start = mode->CrtcHSyncStart - 8;
-
-    save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff)
-				   | ((hsync_wid & 0x3f) << 16)
-				   | ((mode->Flags & V_NHSYNC)
-				      ? RADEON_CRTC_H_SYNC_POL
-				      : 0));
-
-				/* This works for double scan mode. */
-    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
-				| ((mode->CrtcVDisplay - 1) << 16));
-
-    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
-    if (!vsync_wid)       vsync_wid = 1;
-
-    save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
-				   | ((vsync_wid & 0x1f) << 16)
-				   | ((mode->Flags & V_NVSYNC)
-				      ? RADEON_CRTC2_V_SYNC_POL
-				      : 0));
-
-    save->crtc2_pitch  = ((pScrn->displayWidth * pScrn->bitsPerPixel) +
-			  ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8);
-    save->crtc2_pitch |= save->crtc2_pitch << 16;
-
-    /* check to see if TV DAC is enabled for another crtc and keep it enabled */
-    if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON)
-	save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
-    else
-	save->crtc2_gen_cntl = 0;
-
-    save->crtc2_gen_cntl |= (RADEON_CRTC2_EN
-			     | (format << 8)
-			     | RADEON_CRTC2_VSYNC_DIS
-			     | RADEON_CRTC2_HSYNC_DIS
-			     | RADEON_CRTC2_DISP_DIS
-			     | ((mode->Flags & V_DBLSCAN)
-				? RADEON_CRTC2_DBL_SCAN_EN
-				: 0)
-			     | ((mode->Flags & V_CSYNC)
-				? RADEON_CRTC2_CSYNC_EN
-				: 0)
-			     | ((mode->Flags & V_INTERLACE)
-				? RADEON_CRTC2_INTERLACE_EN
-				: 0));
-
-    save->disp2_merge_cntl = info->SavedReg->disp2_merge_cntl;
-    save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN);
-
-    save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid;
-    save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid;
-
-    if (info->ChipFamily == CHIP_FAMILY_RS400) {
-	save->rs480_unk_e30 = 0x105DC1CC; /* because I'm worth it */
-	save->rs480_unk_e34 = 0x2749D000; /* AMD really should */
-	save->rs480_unk_e38 = 0x29ca71dc; /* release docs */
-	save->rs480_unk_e3c = 0x28FBC3AC; /* this is so a trade secret */
-    }
-
-    return TRUE;
-}
-
-
 static CARD32 RADEONDiv(CARD64 n, CARD32 d)
 {
     return (n + (d / 2)) / d;
@@ -716,333 +190,6 @@ RADEONComputePLL(RADEONPLLPtr pll,
 
 }
 
-/* Define PLL registers for requested video mode */
-static void
-RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
-		       RADEONPLLPtr pll, DisplayModePtr mode,
-		       int flags)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    CARD32 feedback_div = 0;
-    CARD32 reference_div = 0;
-    CARD32 post_divider = 0;
-    CARD32 freq = 0;
-
-    struct {
-	int divider;
-	int bitvalue;
-    } *post_div, post_divs[]   = {
-				/* From RAGE 128 VR/RAGE 128 GL Register
-				 * Reference Manual (Technical Reference
-				 * Manual P/N RRG-G04100-C Rev. 0.04), page
-				 * 3-17 (PLL_DIV_[3:0]).
-				 */
-	{  1, 0 },              /* VCLK_SRC                 */
-	{  2, 1 },              /* VCLK_SRC/2               */
-	{  4, 2 },              /* VCLK_SRC/4               */
-	{  8, 3 },              /* VCLK_SRC/8               */
-	{  3, 4 },              /* VCLK_SRC/3               */
-	{ 16, 5 },              /* VCLK_SRC/16              */
-	{  6, 6 },              /* VCLK_SRC/6               */
-	{ 12, 7 },              /* VCLK_SRC/12              */
-	{  0, 0 }
-    };
-
-
-    if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
-       save->ppll_ref_div = info->RefDivider;
-       save->ppll_div_3   = info->FeedbackDivider | (info->PostDivider << 16);
-       save->htotal_cntl  = 0;
-       return;
-    }
-
-    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
-
-    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
-	if (post_div->divider == post_divider)
-	    break;
-    }
-
-    if (!post_div->divider) {
-	save->pll_output_freq = freq;
-	post_div = &post_divs[0];
-    }
-
-    save->dot_clock_freq = freq;
-    save->feedback_div   = feedback_div;
-    save->reference_div  = reference_div;
-    save->post_div       = post_divider;
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
-		   (unsigned)save->dot_clock_freq,
-		   (unsigned)save->pll_output_freq,
-		   save->feedback_div,
-		   save->reference_div,
-		   save->post_div);
-
-    save->ppll_ref_div   = save->reference_div;
-
-#if defined(__powerpc__)
-    /* apparently programming this otherwise causes a hang??? */
-    if (info->MacModel == RADEON_MAC_IBOOK)
-	save->ppll_div_3 = 0x000600ad;
-    else
-#endif
-    save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
-
-    save->htotal_cntl    = mode->HTotal & 0x7;
-
-    save->vclk_ecp_cntl = (info->SavedReg->vclk_ecp_cntl &
-	    ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
-}
-
-/* Define PLL2 registers for requested video mode */
-static void
-RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
-			RADEONPLLPtr pll, DisplayModePtr mode,
-			int flags)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    CARD32 feedback_div = 0;
-    CARD32 reference_div = 0;
-    CARD32 post_divider = 0;
-    CARD32 freq = 0;
-
-    struct {
-	int divider;
-	int bitvalue;
-    } *post_div, post_divs[]   = {
-				/* From RAGE 128 VR/RAGE 128 GL Register
-				 * Reference Manual (Technical Reference
-				 * Manual P/N RRG-G04100-C Rev. 0.04), page
-				 * 3-17 (PLL_DIV_[3:0]).
-				 */
-	{  1, 0 },              /* VCLK_SRC                 */
-	{  2, 1 },              /* VCLK_SRC/2               */
-	{  4, 2 },              /* VCLK_SRC/4               */
-	{  8, 3 },              /* VCLK_SRC/8               */
-	{  3, 4 },              /* VCLK_SRC/3               */
-	{  6, 6 },              /* VCLK_SRC/6               */
-	{ 12, 7 },              /* VCLK_SRC/12              */
-	{  0, 0 }
-    };
-
-    if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
-       save->p2pll_ref_div = info->RefDivider;
-       save->p2pll_div_0   = info->FeedbackDivider | (info->PostDivider << 16);
-       save->htotal_cntl2  = 0;
-       return;
-    }
-
-    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
-
-    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
-	if (post_div->divider == post_divider)
-	    break;
-    }
-
-    if (!post_div->divider) {
-	save->pll_output_freq_2 = freq;
-	post_div = &post_divs[0];
-    }
-
-    save->dot_clock_freq_2 = freq;
-    save->feedback_div_2   = feedback_div;
-    save->reference_div_2  = reference_div;
-    save->post_div_2       = post_divider;
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
-		   (unsigned)save->dot_clock_freq_2,
-		   (unsigned)save->pll_output_freq_2,
-		   save->feedback_div_2,
-		   save->reference_div_2,
-		   save->post_div_2);
-
-    save->p2pll_ref_div    = save->reference_div_2;
-
-    save->p2pll_div_0      = (save->feedback_div_2 |
-			      (post_div->bitvalue << 16));
-
-    save->htotal_cntl2     = mode->HTotal & 0x7;
-
-    save->pixclks_cntl     = ((info->SavedReg->pixclks_cntl &
-			       ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
-			      RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
-}
-
-static void
-RADEONInitBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr  info      = RADEONPTR(pScrn);
-
-    /* tell the bios not to muck with the hardware on events */
-    save->bios_4_scratch = 0x4; /* 0x4 needed for backlight */
-    save->bios_5_scratch = (info->SavedReg->bios_5_scratch & 0xff) | 0xff00; /* bits 0-3 keep backlight level */
-    save->bios_6_scratch = info->SavedReg->bios_6_scratch | 0x40000000;
-
-}
-
-static void
-radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    /* pixclks_cntl controls tv clock routing */
-    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl);
-}
-
-static void
-legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
-		     DisplayModePtr adjusted_mode, int x, int y)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    Bool           tilingOld   = info->tilingEnabled;
-    int i = 0;
-    double dot_clock = 0;
-    int pll_flags = RADEON_PLL_LEGACY;
-    Bool update_tv_routing = FALSE;
-
-
-    if (info->allowColorTiling) {
-	info->tilingEnabled = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
-#ifdef XF86DRI
-	if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) {
-	    RADEONSAREAPrivPtr pSAREAPriv;
-	    if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_SWITCH_TILING, (info->tilingEnabled ? 1 : 0)) < 0)
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "[drm] failed changing tiling status\n");
-	    /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
-	    pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
-	    info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE;
-	}
-#endif
-    }
-
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-	RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
-	if (output->crtc == crtc) {
-	    if (radeon_output->MonType != MT_CRT)
-		pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
-	    if (radeon_output->MonType == MT_LCD)
-		pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV);
-	}
-    }
-
-    if (info->IsMobility)
-	RADEONInitBIOSRegisters(pScrn, info->ModeReg);
-
-    ErrorF("init memmap\n");
-    RADEONInitMemMapRegisters(pScrn, info->ModeReg, info);
-    ErrorF("init common\n");
-    RADEONInitCommonRegisters(info->ModeReg, info);
-
-    RADEONInitSurfaceCntl(crtc, info->ModeReg);
-
-    switch (radeon_crtc->crtc_id) {
-    case 0:
-	ErrorF("init crtc1\n");
-	RADEONInitCrtcRegisters(crtc, info->ModeReg, adjusted_mode);
-	RADEONInitCrtcBase(crtc, info->ModeReg, x, y);
-	dot_clock = adjusted_mode->Clock / 1000.0;
-	if (dot_clock) {
-	    ErrorF("init pll1\n");
-	    RADEONInitPLLRegisters(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
-	} else {
-	    info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div;
-	    info->ModeReg->ppll_div_3   = info->SavedReg->ppll_div_3;
-	    info->ModeReg->htotal_cntl  = info->SavedReg->htotal_cntl;
-	}
-	break;
-    case 1:
-	ErrorF("init crtc2\n");
-	RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode);
-	RADEONInitCrtc2Base(crtc, info->ModeReg, x, y);
-	dot_clock = adjusted_mode->Clock / 1000.0;
-	if (dot_clock) {
-	    ErrorF("init pll2\n");
-	    RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
-	}
-	break;
-    }
-
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-	RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
-	if (output->crtc == crtc) {
-	    if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) {
-		switch (radeon_crtc->crtc_id) {
-		case 0:
-		    RADEONAdjustCrtcRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
-		    RADEONAdjustPLLRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
-		    update_tv_routing = TRUE;
-		    break;
-		case 1:
-		    RADEONAdjustCrtc2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
-		    RADEONAdjustPLL2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
-		    break;
-		}
-	    }
-	}
-    }
-
-    if (info->IsMobility)
-	RADEONRestoreBIOSRegisters(pScrn, info->ModeReg);
-
-    ErrorF("restore memmap\n");
-    RADEONRestoreMemMapRegisters(pScrn, info->ModeReg);
-    ErrorF("restore common\n");
-    RADEONRestoreCommonRegisters(pScrn, info->ModeReg);
-
-    switch (radeon_crtc->crtc_id) {
-    case 0:
-	ErrorF("restore crtc1\n");
-	RADEONRestoreCrtcRegisters(pScrn, info->ModeReg);
-	ErrorF("restore pll1\n");
-	/*if (info->IsAtomBios)
-	    atombios_crtc_set_pll(crtc, adjusted_mode);
-	else*/
-	    RADEONRestorePLLRegisters(pScrn, info->ModeReg);
-	break;
-    case 1:
-	ErrorF("restore crtc2\n");
-	RADEONRestoreCrtc2Registers(pScrn, info->ModeReg);
-	ErrorF("restore pll2\n");
-	/*if (info->IsAtomBios)
-	  atombios_crtc_set_pll(crtc, adjusted_mode);
-	else*/
-	    RADEONRestorePLL2Registers(pScrn, info->ModeReg);
-	break;
-    }
-
-    /* pixclks_cntl handles tv-out clock routing */
-    if (update_tv_routing)
-	radeon_update_tv_routing(pScrn, info->ModeReg);
-
-    if (info->DispPriority)
-        RADEONInitDispBandwidth(pScrn);
-
-    if (info->tilingEnabled != tilingOld) {
-	/* need to redraw front buffer, I guess this can be considered a hack ? */
-	/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
-	if (pScrn->pScreen)
-	    xf86EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
-	RADEONChangeSurfaces(pScrn);
-	if (pScrn->pScreen)
-	    xf86EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
-	/* xf86SetRootClip would do, but can't access that here */
-    }
-
-    /* reset ecp_div for Xv */
-    info->ecp_div = -1;
-
-}
-
 static void
 radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode, int x, int y)
@@ -1066,7 +213,8 @@ radeon_crtc_mode_commit(xf86CrtcPtr crtc)
     radeon_crtc_dpms(crtc, DPMSModeOn);
 }
 
-void radeon_crtc_load_lut(xf86CrtcPtr crtc)
+void
+radeon_crtc_load_lut(xf86CrtcPtr crtc)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
@@ -1499,3 +647,47 @@ RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode)
     return pMode;
 }
 
+void
+RADEONBlank(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86OutputPtr output;
+    xf86CrtcPtr crtc;
+    int o, c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+	crtc = xf86_config->crtc[c];
+	for (o = 0; o < xf86_config->num_output; o++) {
+	    output = xf86_config->output[o];
+	    if (output->crtc != crtc)
+		continue;
+
+	    output->funcs->dpms(output, DPMSModeOff);
+	}
+	crtc->funcs->dpms(crtc, DPMSModeOff);
+    }
+}
+
+void
+RADEONUnblank(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86OutputPtr output;
+    xf86CrtcPtr crtc;
+    int o, c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+	crtc = xf86_config->crtc[c];
+	if(!crtc->enabled)
+		continue;
+	crtc->funcs->dpms(crtc, DPMSModeOn);
+	for (o = 0; o < xf86_config->num_output; o++) {
+	    output = xf86_config->output[o];
+	    if (output->crtc != crtc)
+		continue;
+
+	    output->funcs->dpms(output, DPMSModeOn);
+	}
+    }
+}
+
diff --git a/src/radeon_display.c b/src/radeon_display.c
index 2043f24..1c529cf 100644
--- a/src/radeon_display.c
+++ b/src/radeon_display.c
@@ -48,27 +48,6 @@
 
 extern int getRADEONEntityIndex(void);
 
-static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] =
-{
-    0x00000000,   /* unknown */
-    0x00000000,   /* legacy */
-    0x00000000,   /* r100 */
-    0x00280000,   /* rv100 */
-    0x00000000,   /* rs100 */
-    0x00880000,   /* rv200 */
-    0x00000000,   /* rs200 */
-    0x00000000,   /* r200 */
-    0x00770000,   /* rv250 */
-    0x00290000,   /* rs300 */
-    0x00560000,   /* rv280 */
-    0x00780000,   /* r300 */
-    0x00770000,   /* r350 */
-    0x00780000,   /* rv350 */
-    0x00780000,   /* rv380 */
-    0x01080000,   /* r420 */
-    0x01080000,   /* rv410 */ /* FIXME: just values from r420 used... */
-    0x00780000,   /* rs400 */ /* FIXME: just values from rv380 used... */
-};
 
 void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
 {
@@ -157,722 +136,3 @@ void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
 	mon->nVrefresh = i;
     }
 }
-
-void RADEONGetTVDacAdjInfo(xf86OutputPtr output)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
-    /* Todo: get this setting from BIOS */
-    radeon_output->tv_dac_adj = default_tvdac_adj[info->ChipFamily];
-    if (info->IsMobility) { /* some mobility chips may different */
-	if (info->ChipFamily == CHIP_FAMILY_RV250)
-	    radeon_output->tv_dac_adj = 0x00880000;
-    }
-}
-
-/*
- * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant).
- *
- */
-static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    if (IsPrimaryDAC) {
-	CARD32 dac_cntl;
-	CARD32 dac_macro_cntl = 0;
-	dac_cntl = INREG(RADEON_DAC_CNTL);
-	dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL);
-	if (IsOn) {
-	    dac_cntl &= ~RADEON_DAC_PDWN;
-	    dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
-				RADEON_DAC_PDWN_G |
-				RADEON_DAC_PDWN_B);
-	} else {
-	    dac_cntl |= RADEON_DAC_PDWN;
-	    dac_macro_cntl |= (RADEON_DAC_PDWN_R |
-			       RADEON_DAC_PDWN_G |
-			       RADEON_DAC_PDWN_B);
-	}
-	OUTREG(RADEON_DAC_CNTL, dac_cntl);
-	OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
-    } else {
-	CARD32 tv_dac_cntl;
-	CARD32 fp2_gen_cntl;
-
-	switch(info->ChipFamily)
-	{
-	case CHIP_FAMILY_R420:
-	case CHIP_FAMILY_RV410:
-	    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
-	    if (IsOn) {
-		tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
-				 R420_TV_DAC_GDACPD |
-				 R420_TV_DAC_BDACPD |
-				 RADEON_TV_DAC_BGSLEEP);
-	    } else {
-		tv_dac_cntl |= (R420_TV_DAC_RDACPD |
-				R420_TV_DAC_GDACPD |
-				R420_TV_DAC_BDACPD |
-				RADEON_TV_DAC_BGSLEEP);
-	    }
-	    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-	    break;
-	case CHIP_FAMILY_R200:
-	    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
-	    if (IsOn) {
-		fp2_gen_cntl |= RADEON_FP2_DVO_EN;
-	    } else {
-		fp2_gen_cntl &= ~RADEON_FP2_DVO_EN;
-	    }
-	    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
-	    break;
-
-	default:
-	    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
-	    if (IsOn) {
-		tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
-				 RADEON_TV_DAC_GDACPD |
-				 RADEON_TV_DAC_BDACPD |
-				 RADEON_TV_DAC_BGSLEEP);
-	    } else {
-		tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
-				RADEON_TV_DAC_GDACPD |
-				RADEON_TV_DAC_BDACPD |
-				RADEON_TV_DAC_BGSLEEP);
-	    }
-	    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-	    break;
-	}
-    }
-}
-
-/* disable all ouputs before enabling the ones we want */
-void RADEONDisableDisplays(ScrnInfoPtr pScrn) {
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char * RADEONMMIO = info->MMIO;
-    unsigned long tmp, tmpPixclksCntl;
-
-
-    /* primary DAC */
-    tmp = INREG(RADEON_CRTC_EXT_CNTL);
-    tmp &= ~RADEON_CRTC_CRT_ON;
-    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
-    RADEONDacPowerSet(pScrn, FALSE, TRUE);
-
-    /* Secondary DAC */
-    if (info->ChipFamily == CHIP_FAMILY_R200) {
-	tmp = INREG(RADEON_FP2_GEN_CNTL);
-	tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-	OUTREG(RADEON_FP2_GEN_CNTL, tmp);
-    } else {
-	tmp = INREG(RADEON_CRTC2_GEN_CNTL);
-	tmp &= ~RADEON_CRTC2_CRT2_ON;
-	OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
-    }
-    RADEONDacPowerSet(pScrn, FALSE, FALSE);
-
-    /* turn off tv-out */
-    if (info->InternalTVOut) {
-	tmp = INREG(RADEON_TV_MASTER_CNTL);
-	tmp &= ~RADEON_TV_ON;
-	OUTREG(RADEON_TV_MASTER_CNTL, tmp);
-    }
-
-    /* FP 1 */
-    tmp = INREG(RADEON_FP_GEN_CNTL);
-    tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
-    OUTREG(RADEON_FP_GEN_CNTL, tmp);
-
-    /* FP 2 */
-    tmp = INREG(RADEON_FP2_GEN_CNTL);
-    tmp |= RADEON_FP2_BLANK_EN;
-    tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
-
-    /* LVDS */
-    if (info->IsMobility) {
-	tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
-	if (info->IsMobility || info->IsIGP) {
-	    /* Asic bug, when turning off LVDS_ON, we have to make sure
-	       RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
-	    */
-	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
-	}
-	tmp = INREG(RADEON_LVDS_GEN_CNTL);
-	tmp |= RADEON_LVDS_DISPLAY_DIS;
-	tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
-	OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
-	if (info->IsMobility || info->IsIGP) {
-	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
-	}
-    }
-
-}
-
-/* This is to be used enable/disable displays dynamically */
-void RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    RADEONSavePtr save = info->ModeReg;
-    unsigned char * RADEONMMIO = info->MMIO;
-    unsigned long tmp;
-    RADEONOutputPrivatePtr radeon_output;
-    int tv_dac_change = 0, o;
-    radeon_output = output->driver_private;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-
-    for (o = 0; o < xf86_config->num_output; o++) {
-	if (output == xf86_config->output[o]) {
-	    break;
-	}
-    }
-
-    if (bEnable) {
-	ErrorF("enable montype: %d\n", radeon_output->MonType);
-	if (radeon_output->MonType == MT_CRT) {
-	    if (radeon_output->DACType == DAC_PRIMARY) {
-		info->output_crt1 |= (1 << o);
-		tmp = INREG(RADEON_CRTC_EXT_CNTL);
-		tmp |= RADEON_CRTC_CRT_ON;
-		OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
-		save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
-		RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
-	    } else if (radeon_output->DACType == DAC_TVDAC) {
-		info->output_crt2 |= (1 << o);
-		if (info->ChipFamily == CHIP_FAMILY_R200) {
-		    tmp = INREG(RADEON_FP2_GEN_CNTL);
-		    tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-		    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
-		    save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-		} else {
-		    tmp = INREG(RADEON_CRTC2_GEN_CNTL);
-		    tmp |= RADEON_CRTC2_CRT2_ON;
-		    OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
-		    save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
-		}
-		tv_dac_change = 1;
-	    }
-	} else if (radeon_output->MonType == MT_DFP) {
-	    if (radeon_output->TMDSType == TMDS_INT) {
-		info->output_dfp1 |= (1 << o);
-		tmp = INREG(RADEON_FP_GEN_CNTL);
-		tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
-		OUTREG(RADEON_FP_GEN_CNTL, tmp);
-		save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
-	    } else if (radeon_output->TMDSType == TMDS_EXT) {
-		info->output_dfp2 |= (1 << o);
-		tmp = INREG(RADEON_FP2_GEN_CNTL);
-		tmp &= ~RADEON_FP2_BLANK_EN;
-		tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-		OUTREG(RADEON_FP2_GEN_CNTL, tmp);
-		save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-		save->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
-	    }
-	} else if (radeon_output->MonType == MT_LCD) {
-	    info->output_lcd1 |= (1 << o);
-	    tmp = INREG(RADEON_LVDS_GEN_CNTL);
-	    tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
-	    tmp &= ~(RADEON_LVDS_DISPLAY_DIS);
-	    usleep (radeon_output->PanelPwrDly * 1000);
-	    OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
-	    save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
-	    save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
-	} else if (radeon_output->MonType == MT_STV ||
-		   radeon_output->MonType == MT_CTV) {
-	    info->output_tv1 |= (1 << o);
-	    tmp = INREG(RADEON_TV_MASTER_CNTL);
-	    tmp |= RADEON_TV_ON;
-	    OUTREG(RADEON_TV_MASTER_CNTL, tmp);
-	    tv_dac_change = 2;
-	    radeon_output->tv_on = TRUE;
-	}
-    } else {
-	ErrorF("disable montype: %d\n", radeon_output->MonType);
-	if (radeon_output->MonType == MT_CRT) {
-	    if (radeon_output->DACType == DAC_PRIMARY) {
-		info->output_crt1 &= ~(1 << o);
-		if (!info->output_crt1) {
-		    tmp = INREG(RADEON_CRTC_EXT_CNTL);
-		    tmp &= ~RADEON_CRTC_CRT_ON;
-		    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
-		    save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
-		    RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
-		}
-	    } else if (radeon_output->DACType == DAC_TVDAC) {
-		info->output_crt2 &= ~(1 << o);
-		tv_dac_change = 1;
-		if (!info->output_crt2) {
-		    if (info->ChipFamily == CHIP_FAMILY_R200) {
-			tmp = INREG(RADEON_FP2_GEN_CNTL);
-			tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-			OUTREG(RADEON_FP2_GEN_CNTL, tmp);
-			save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-		    } else {
-			tmp = INREG(RADEON_CRTC2_GEN_CNTL);
-			tmp &= ~RADEON_CRTC2_CRT2_ON;
-			OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
-			save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
-		    }
-		}
-	    }
-	} else if (radeon_output->MonType == MT_DFP) {
-	    if (radeon_output->TMDSType == TMDS_INT) {
-		info->output_dfp1 &= ~(1 << o);
-		if (!info->output_dfp1) {
-		    tmp = INREG(RADEON_FP_GEN_CNTL);
-		    tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
-		    OUTREG(RADEON_FP_GEN_CNTL, tmp);
-		    save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
-		}
-	    } else if (radeon_output->TMDSType == TMDS_EXT) {
-		info->output_dfp2 &= ~(1 << o);
-		if (!info->output_dfp2) {
-		    tmp = INREG(RADEON_FP2_GEN_CNTL);
-		    tmp |= RADEON_FP2_BLANK_EN;
-		    tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-		    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
-		    save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
-		    save->fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
-		}
-	    }
-	} else if (radeon_output->MonType == MT_LCD) {
-	    info->output_lcd1 &= ~(1 << o);
-	    if (!info->output_lcd1) {
-		unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
-		if (info->IsMobility || info->IsIGP) {
-		    /* Asic bug, when turning off LVDS_ON, we have to make sure
-		       RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
-		    */
-		    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
-		}
-		tmp = INREG(RADEON_LVDS_GEN_CNTL);
-		tmp |= RADEON_LVDS_DISPLAY_DIS;
-		tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
-		OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
-		save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
-		save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
-		if (info->IsMobility || info->IsIGP) {
-		    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
-		}
-	    }
-	} else if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) {
-	    info->output_tv1 &= ~(1 << o);
-	    tv_dac_change = 2;
-	    if (!info->output_tv1) {
-		tmp = INREG(RADEON_TV_MASTER_CNTL);
-		tmp &= ~RADEON_TV_ON;
-		OUTREG(RADEON_TV_MASTER_CNTL, tmp);
-		radeon_output->tv_on = FALSE;
-	    }
-	}
-    }
-
-    if (tv_dac_change) {
-	if (bEnable)
-	    info->tv_dac_enable_mask |= tv_dac_change;
-	else
-	    info->tv_dac_enable_mask &= ~tv_dac_change;
-
-	if (bEnable && info->tv_dac_enable_mask)
-	    RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
-	else if (!bEnable && info->tv_dac_enable_mask == 0)
-	    RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY));
-
-    }
-}
-
-/* Calculate display buffer watermark to prevent buffer underflow */
-void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2, DisplayModePtr mode1, DisplayModePtr mode2)
-{
-    RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-
-    CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0;
-    float mem_tcas;
-    int k1, c;
-    CARD32 MemTrcdExtMemCntl[4]     = {1, 2, 3, 4};
-    CARD32 MemTrpExtMemCntl[4]      = {1, 2, 3, 4};
-    CARD32 MemTrasExtMemCntl[8]     = {1, 2, 3, 4, 5, 6, 7, 8};
-
-    CARD32 MemTrcdMemTimingCntl[8]     = {1, 2, 3, 4, 5, 6, 7, 8};
-    CARD32 MemTrpMemTimingCntl[8]      = {1, 2, 3, 4, 5, 6, 7, 8};
-    CARD32 MemTrasMemTimingCntl[16]    = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
-
-    float MemTcas[8]  = {0, 1, 2, 3, 0, 1.5, 2.5, 0};
-    float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7};
-    float MemTrbs[8]  = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5};
-
-    float mem_bw, peak_disp_bw;
-    float min_mem_eff = 0.8;
-    float sclk_eff, sclk_delay;
-    float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk;
-    float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2;
-    float pix_clk, pix_clk2; /* in MHz */
-    int cur_size = 16;       /* in octawords */
-    int critical_point, critical_point2;
-    int stop_req, max_stop_req;
-    float read_return_rate, time_disp1_drop_priority;
-
-    /*
-     * Set display0/1 priority up on r3/4xx in the memory controller for
-     * high res modes if the user specifies HIGH for displaypriority
-     * option.
-     */
-    if ((info->DispPriority == 2) && IS_R300_VARIANT) {
-	CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
-	if (pRADEONEnt->pCrtc[1]->enabled) {
-	    mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */
-	} else {
-	    mc_init_misc_lat_timer |= 0x0100; /* display 0 only */
-	}
-	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
-    }
-
-
-    /* R420 and RV410 family not supported yet */
-    if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; 
-
-    /*
-     * Determine if there is enough bandwidth for current display mode
-     */
-    mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
-
-    pix_clk = mode1->Clock/1000.0;
-    if (mode2)
-	pix_clk2 = mode2->Clock/1000.0;
-    else
-	pix_clk2 = 0;
-
-    peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes);
-    if (pixel_bytes2)
-      peak_disp_bw += (pix_clk2 * pixel_bytes2);
-
-    if (peak_disp_bw >= mem_bw * min_mem_eff) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "You may not have enough display bandwidth for current mode\n"
-		   "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
-    }
-
-    /*  CRTC1
-        Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
-	GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
-    */
-    stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16;
-
-    /* setup Max GRPH_STOP_REQ default value */
-    if (IS_RV100_VARIANT)
-	max_stop_req = 0x5c;
-    else
-	max_stop_req  = 0x7c;
-    if (stop_req > max_stop_req)
-	stop_req = max_stop_req;
-
-    /*  Get values from the EXT_MEM_CNTL register...converting its contents. */
-    temp = INREG(RADEON_MEM_TIMING_CNTL);
-    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
-	mem_trcd      = MemTrcdExtMemCntl[(temp & 0x0c) >> 2];
-	mem_trp       = MemTrpExtMemCntl[ (temp & 0x03) >> 0];
-	mem_tras      = MemTrasExtMemCntl[(temp & 0x70) >> 4];
-    } else { /* RV200 and later */
-	mem_trcd      = MemTrcdMemTimingCntl[(temp & 0x07) >> 0];
-	mem_trp       = MemTrpMemTimingCntl[ (temp & 0x700) >> 8];
-	mem_tras      = MemTrasMemTimingCntl[(temp & 0xf000) >> 12];
-    }
-
-    /* Get values from the MEM_SDRAM_MODE_REG register...converting its */
-    temp = INREG(RADEON_MEM_SDRAM_MODE_REG);
-    data = (temp & (7<<20)) >> 20;
-    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
-	mem_tcas = MemTcas [data];
-    } else {
-	mem_tcas = MemTcas2 [data];
-    }
-
-    if (IS_R300_VARIANT) {
-
-	/* on the R300, Tcas is included in Trbs.
-	*/
-	temp = INREG(RADEON_MEM_CNTL);
-	data = (R300_MEM_NUM_CHANNELS_MASK & temp);
-	if (data == 1) {
-	    if (R300_MEM_USE_CD_CH_ONLY & temp) {
-		temp  = INREG(R300_MC_IND_INDEX);
-		temp &= ~R300_MC_IND_ADDR_MASK;
-		temp |= R300_MC_READ_CNTL_CD_mcind;
-		OUTREG(R300_MC_IND_INDEX, temp);
-		temp  = INREG(R300_MC_IND_DATA);
-		data = (R300_MEM_RBS_POSITION_C_MASK & temp);
-	    } else {
-		temp = INREG(R300_MC_READ_CNTL_AB);
-		data = (R300_MEM_RBS_POSITION_A_MASK & temp);
-	    }
-	} else {
-	    temp = INREG(R300_MC_READ_CNTL_AB);
-	    data = (R300_MEM_RBS_POSITION_A_MASK & temp);
-	}
-
-	mem_trbs = MemTrbs[data];
-	mem_tcas += mem_trbs;
-    }
-
-    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
-	/* DDR64 SCLK_EFF = SCLK for analysis */
-	sclk_eff = info->sclk;
-    } else {
-#ifdef XF86DRI
-	if (info->directRenderingEnabled)
-	    sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0);
-	else
-#endif
-	    sclk_eff = info->sclk;
-    }
-
-    /* Find the memory controller latency for the display client.
-    */
-    if (IS_R300_VARIANT) {
-	/*not enough for R350 ???*/
-	/*
-	if (!mode2) sclk_delay = 150;
-	else {
-	    if (info->RamWidth == 256) sclk_delay = 87;
-	    else sclk_delay = 97;
-	}
-	*/
-	sclk_delay = 250;
-    } else {
-	if ((info->ChipFamily == CHIP_FAMILY_RV100) ||
-	    info->IsIGP) {
-	    if (info->IsDDR) sclk_delay = 41;
-	    else sclk_delay = 33;
-	} else {
-	    if (info->RamWidth == 128) sclk_delay = 57;
-	    else sclk_delay = 41;
-	}
-    }
-
-    mc_latency_sclk = sclk_delay / sclk_eff;
-
-    if (info->IsDDR) {
-	if (info->RamWidth == 32) {
-	    k1 = 40;
-	    c  = 3;
-	} else {
-	    k1 = 20;
-	    c  = 1;
-	}
-    } else {
-	k1 = 40;
-	c  = 3;
-    }
-    mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) /
-		       info->mclk) + (4.0 / sclk_eff);
-
-    /*
-      HW cursor time assuming worst case of full size colour cursor.
-    */
-    cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk;
-    cur_latency_sclk = cur_size / sclk_eff;
-
-    /*
-      Find the total latency for the display data.
-    */
-    disp_latency_overhead = 8.0 / info->sclk;
-    mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk;
-    mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk;
-    disp_latency = MAX(mc_latency_mclk, mc_latency_sclk);
-
-    /*
-      Find the drain rate of the display buffer.
-    */
-    disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes);
-    if (pixel_bytes2)
-	disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2);
-    else
-	disp_drain_rate2 = 0;
-
-    /*
-      Find the critical point of the display buffer.
-    */
-    critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5);
-
-    /* ???? */
-    /*
-    temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT;
-    if (critical_point < temp) critical_point = temp;
-    */
-    if (info->DispPriority == 2) {
-	critical_point = 0;
-    }
-
-    /*
-      The critical point should never be above max_stop_req-4.  Setting
-      GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
-    */
-    if (max_stop_req - critical_point < 4) critical_point = 0;
-
-    if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) {
-	/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
-	critical_point = 0x10;
-    }
-
-    temp = info->SavedReg->grph_buffer_cntl;
-    temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
-    temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
-    temp &= ~(RADEON_GRPH_START_REQ_MASK);
-    if ((info->ChipFamily == CHIP_FAMILY_R350) &&
-	(stop_req > 0x15)) {
-	stop_req -= 0x10;
-    }
-    temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
-
-    temp |= RADEON_GRPH_BUFFER_SIZE;
-    temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
-	      RADEON_GRPH_CRITICAL_AT_SOF |
-	      RADEON_GRPH_STOP_CNTL);
-    /*
-      Write the result into the register.
-    */
-    OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
-				     (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
-
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "GRPH_BUFFER_CNTL from %x to %x\n",
-		   (unsigned int)info->SavedReg->grph_buffer_cntl,
-		   (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL));
-
-    if (mode2) {
-	stop_req = mode2->HDisplay * pixel_bytes2 / 16;
-
-	if (stop_req > max_stop_req) stop_req = max_stop_req;
-
-	temp = info->SavedReg->grph2_buffer_cntl;
-	temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
-	temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
-	temp &= ~(RADEON_GRPH_START_REQ_MASK);
-	if ((info->ChipFamily == CHIP_FAMILY_R350) &&
-	    (stop_req > 0x15)) {
-	    stop_req -= 0x10;
-	}
-	temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
-	temp |= RADEON_GRPH_BUFFER_SIZE;
-	temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
-		  RADEON_GRPH_CRITICAL_AT_SOF |
-		  RADEON_GRPH_STOP_CNTL);
-
-	if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
-	    (info->ChipFamily == CHIP_FAMILY_RS200))
-	    critical_point2 = 0;
-	else {
-	    read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128));
-	    time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate);
-
-	    critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + 
-					disp_latency) * disp_drain_rate2 + 0.5);
-
-	    if (info->DispPriority == 2) {
-		critical_point2 = 0;
-	    }
-
-	    if (max_stop_req - critical_point2 < 4) critical_point2 = 0;
-
-	}
-
-	if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) {
-	    /* some R300 cards have problem with this set to 0 */
-	    critical_point2 = 0x10;
-	}
-
-	OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
-					  (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
-
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		       "GRPH2_BUFFER_CNTL from %x to %x\n",
-		       (unsigned int)info->SavedReg->grph2_buffer_cntl,
-		       (unsigned int)INREG(RADEON_GRPH2_BUFFER_CNTL));
-    }
-}
-
-void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    DisplayModePtr mode1, mode2;
-    int pixel_bytes2 = 0;
-
-    if (info->IsPrimary || info->IsSecondary)
-	mode1 = &xf86_config->crtc[0]->mode;
-    else
-	mode1 = info->CurrentLayout.mode;
-    mode2 = NULL;
-    pixel_bytes2 = info->CurrentLayout.pixel_bytes;
-
-    if (xf86_config->num_crtc == 2) {
-      pixel_bytes2 = 0;
-      mode2 = NULL;
-
-      if (xf86_config->crtc[1]->enabled && xf86_config->crtc[0]->enabled) {
-	pixel_bytes2 = info->CurrentLayout.pixel_bytes;
-	mode1 = &xf86_config->crtc[0]->mode;
-	mode2 = &xf86_config->crtc[1]->mode;
-      } else if (xf86_config->crtc[0]->enabled) {
-	mode1 = &xf86_config->crtc[0]->mode;
-      } else if (xf86_config->crtc[1]->enabled) {
-	mode1 = &xf86_config->crtc[1]->mode;
-      } else
-	return;
-    } else {
-	if (xf86_config->crtc[0]->enabled)
-	    mode1 = &xf86_config->crtc[0]->mode;
-	else
-	    return;
-    }
-
-    RADEONInitDispBandwidth2(pScrn, info, pixel_bytes2, mode1, mode2);
-}
-
-void RADEONBlank(ScrnInfoPtr pScrn)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    xf86OutputPtr output;
-    xf86CrtcPtr crtc;
-    int o, c;
-
-    for (c = 0; c < xf86_config->num_crtc; c++) {
-	crtc = xf86_config->crtc[c];
-	for (o = 0; o < xf86_config->num_output; o++) {
-	    output = xf86_config->output[o];
-	    if (output->crtc != crtc)
-		continue;
-
-	    output->funcs->dpms(output, DPMSModeOff);
-	}
-	crtc->funcs->dpms(crtc, DPMSModeOff);
-    }
-}
-
-void RADEONUnblank(ScrnInfoPtr pScrn)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    xf86OutputPtr output;
-    xf86CrtcPtr crtc;
-    int o, c;
-
-    for (c = 0; c < xf86_config->num_crtc; c++) {
-	crtc = xf86_config->crtc[c];
-	if(!crtc->enabled)
-		continue;
-	crtc->funcs->dpms(crtc, DPMSModeOn);
-	for (o = 0; o < xf86_config->num_output; o++) {
-	    output = xf86_config->output[o];
-	    if (output->crtc != crtc)
-		continue;
-
-	    output->funcs->dpms(output, DPMSModeOn);
-	}
-    }
-}
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 30a73ab..2346932 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -136,12 +136,31 @@ static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] =
     {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */
 };
 
+static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] =
+{
+    0x00000000,   /* unknown */
+    0x00000000,   /* legacy */
+    0x00000000,   /* r100 */
+    0x00280000,   /* rv100 */
+    0x00000000,   /* rs100 */
+    0x00880000,   /* rv200 */
+    0x00000000,   /* rs200 */
+    0x00000000,   /* r200 */
+    0x00770000,   /* rv250 */
+    0x00290000,   /* rs300 */
+    0x00560000,   /* rv280 */
+    0x00780000,   /* r300 */
+    0x00770000,   /* r350 */
+    0x00780000,   /* rv350 */
+    0x00780000,   /* rv380 */
+    0x01080000,   /* r420 */
+    0x01080000,   /* rv410 */ /* FIXME: just values from r420 used... */
+    0x00780000,   /* rs400 */ /* FIXME: just values from rv380 used... */
+};
+
+
 static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output);
 static void RADEONUpdatePanelSize(xf86OutputPtr output);
-static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn);
-static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color);
-static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color);
-static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn);
 static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output);
 #define AVIVO_I2C_DISABLE 0
 #define AVIVO_I2C_ENABLE 1
@@ -150,102 +169,15 @@ static Bool AVIVOI2CDoLock(ScrnInfoPtr pScrn, int lock_state, int gpio);
 extern void atombios_output_mode_set(xf86OutputPtr output,
 				     DisplayModePtr mode,
 				     DisplayModePtr adjusted_mode);
+extern void legacy_output_mode_set(xf86OutputPtr output,
+				   DisplayModePtr mode,
+				   DisplayModePtr adjusted_mode);
 extern void atombios_output_dpms(xf86OutputPtr output, int mode);
+extern void legacy_output_dpms(xf86OutputPtr output, int mode);
 extern RADEONMonitorType atombios_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output);
+extern RADEONMonitorType legacy_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output);
 extern int atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode);
 
-Bool
-RADEONDVOReadByte(I2CDevPtr dvo, int addr, CARD8 *ch)
-{
-    if (!xf86I2CReadByte(dvo, addr, ch)) {
-	xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR,
-		   "Unable to read from %s Slave %d.\n",
-		   dvo->pI2CBus->BusName, dvo->SlaveAddr);
-	return FALSE;
-    }
-    return TRUE;
-}
-
-Bool
-RADEONDVOWriteByte(I2CDevPtr dvo, int addr, CARD8 ch)
-{
-    if (!xf86I2CWriteByte(dvo, addr, ch)) {
-	xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR,
-		   "Unable to write to %s Slave %d.\n",
-		   dvo->pI2CBus->BusName, dvo->SlaveAddr);
-	return FALSE;
-    }
-    return TRUE;
-}
-
-static I2CDevPtr
-RADEONDVODeviceInit(I2CBusPtr b, I2CSlaveAddr addr)
-{
-    I2CDevPtr dvo;
-
-    dvo = xcalloc(1, sizeof(I2CDevRec));
-    if (dvo == NULL)
-	return NULL;
-
-    dvo->DevName = "RADEON DVO Controller";
-    dvo->SlaveAddr = addr;
-    dvo->pI2CBus = b;
-    dvo->StartTimeout = b->StartTimeout;
-    dvo->BitTimeout = b->BitTimeout;
-    dvo->AcknTimeout = b->AcknTimeout;
-    dvo->ByteTimeout = b->ByteTimeout;
-
-    if (xf86I2CDevInit(dvo)) {
-	return dvo;
-    }
-
-    xfree(dvo);
-    return NULL;
-}
-
-void
-RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
-    if (!radeon_output->DVOChip)
-	return;
-
-    OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
-	   (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
-
-    if (!RADEONInitExtTMDSInfoFromBIOS(output)) {
-	if (radeon_output->DVOChip) {
-	    switch(info->ext_tmds_chip) {
-	    case RADEON_SIL_164:
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x30);
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x00);
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x90);
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0x89);
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x3b);
-		break;
-#if 0
-		/* needs work see bug 10418 */
-	    case RADEON_SIL_1178:
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x44);
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x4c);
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0e, 0x01);
-		RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x80);
-                RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x30);
-                RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0xc9);
-                RADEONDVOWriteByte(radeon_output->DVOChip, 0x0d, 0x70);
-                RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x32);
-                RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x33);
-		break;
-#endif
-	    default:
-		break;
-	    }
-	}
-    }
-}
 
 void RADEONPrintPortMap(ScrnInfoPtr pScrn)
 {
@@ -404,291 +336,6 @@ RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output)
     return MonType;
 }
 
-#if 0
-static RADEONMonitorType
-RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
-{
-    RADEONInfoPtr info       = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    int		  bConnected = 0;
-
-    /* the monitor either wasn't connected or it is a non-DDC CRT.
-     * try to probe it
-     */
-    if(IsCrtDac) {
-	unsigned long ulOrigVCLK_ECP_CNTL;
-	unsigned long ulOrigDAC_CNTL;
-	unsigned long ulOrigDAC_MACRO_CNTL;
-	unsigned long ulOrigDAC_EXT_CNTL;
-	unsigned long ulOrigCRTC_EXT_CNTL;
-	unsigned long ulData;
-	unsigned long ulMask;
-
-	ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
-
-	ulData              = ulOrigVCLK_ECP_CNTL;
-	ulData             &= ~(RADEON_PIXCLK_ALWAYS_ONb
-				| RADEON_PIXCLK_DAC_ALWAYS_ONb);
-	ulMask              = ~(RADEON_PIXCLK_ALWAYS_ONb
-				|RADEON_PIXCLK_DAC_ALWAYS_ONb);
-	OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask);
-
-	ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL);
-	ulData              = ulOrigCRTC_EXT_CNTL;
-	ulData             |= RADEON_CRTC_CRT_ON;
-	OUTREG(RADEON_CRTC_EXT_CNTL, ulData);
-
-	ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL);
-	ulData             = ulOrigDAC_EXT_CNTL;
-	ulData            &= ~RADEON_DAC_FORCE_DATA_MASK;
-	ulData            |=  (RADEON_DAC_FORCE_BLANK_OFF_EN
-			       |RADEON_DAC_FORCE_DATA_EN
-			       |RADEON_DAC_FORCE_DATA_SEL_MASK);
-	if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
-	    (info->ChipFamily == CHIP_FAMILY_RV280))
-	    ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT);
-	else
-	    ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT);
-
-	OUTREG(RADEON_DAC_EXT_CNTL, ulData);
-
-	/* turn on power so testing can go through */
-	ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL);
-	ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN;
-	OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL);
-
-	ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
-	ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
-				  RADEON_DAC_PDWN_B);
-	OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
-
-	/* Enable comparators and set DAC range to PS2 (VGA) output level */
-	ulData = ulOrigDAC_CNTL;
-	ulData |= RADEON_DAC_CMP_EN;
-	ulData &= ~RADEON_DAC_RANGE_CNTL_MASK;
-	ulData |= 0x2;
-	OUTREG(RADEON_DAC_CNTL, ulData);
-
-	/* Settle down */
-	usleep(10000);
-
-	/* Read comparators */
-	ulData     = INREG(RADEON_DAC_CNTL);
-	bConnected =  (RADEON_DAC_CMP_OUTPUT & ulData)?1:0;
-
-	/* Restore things */
-	ulData    = ulOrigVCLK_ECP_CNTL;
-	ulMask    = 0xFFFFFFFFL;
-	OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask);
-
-	OUTREG(RADEON_DAC_CNTL,      ulOrigDAC_CNTL     );
-	OUTREG(RADEON_DAC_EXT_CNTL,  ulOrigDAC_EXT_CNTL );
-	OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);
-
-	if (!bConnected) {
-	    /* Power DAC down if CRT is not connected */
-            ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
-            ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
-	    	RADEON_DAC_PDWN_B);
-            OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
-
-	    ulData = INREG(RADEON_DAC_CNTL);
-	    ulData |= RADEON_DAC_PDWN;
-	    OUTREG(RADEON_DAC_CNTL, ulData);
-    	}
-    } else { /* TV DAC */
-
-        /* This doesn't seem to work reliably (maybe worse on some OEM cards),
-           for now we always return false. If one wants to connected a
-           non-DDC monitor on the DVI port when CRT port is also connected,
-           he will need to explicitly tell the driver in the config file
-           with Option MonitorLayout.
-        */
-        bConnected = FALSE;
-
-#if 0
-	if (info->ChipFamily == CHIP_FAMILY_R200) {
-	    unsigned long ulOrigGPIO_MONID;
-	    unsigned long ulOrigFP2_GEN_CNTL;
-	    unsigned long ulOrigDISP_OUTPUT_CNTL;
-	    unsigned long ulOrigCRTC2_GEN_CNTL;
-	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_A;
-	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_B;
-	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_C;
-	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_D;
-	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_E;
-	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_F;
-	    unsigned long ulOrigCRTC2_H_TOTAL_DISP;
-	    unsigned long ulOrigCRTC2_V_TOTAL_DISP;
-	    unsigned long ulOrigCRTC2_H_SYNC_STRT_WID;
-	    unsigned long ulOrigCRTC2_V_SYNC_STRT_WID;
-	    unsigned long ulData, i;
-
-	    ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID);
-	    ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL);
-	    ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL);
-	    ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL);
-	    ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A);
-	    ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B);
-	    ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C);
-	    ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D);
-	    ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E);
-	    ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F);
-
-	    ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP);
-	    ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP);
-	    ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
-	    ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
-
-	    ulData     = INREG(RADEON_GPIO_MONID);
-	    ulData    &= ~RADEON_GPIO_A_0;
-	    OUTREG(RADEON_GPIO_MONID, ulData);
-
-	    OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c);
-
-	    OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012);
-
-	    OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
-	    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
-	    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
-	    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
-	    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
-
-	    for (i = 0; i < 200; i++) {
-		ulData     = INREG(RADEON_GPIO_MONID);
-		bConnected = (ulData & RADEON_GPIO_Y_0)?1:0;
-		if (!bConnected) break;
-
-		usleep(1000);
-	    }
-
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E);
-	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F);
-	    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP);
-	    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP);
-	    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID);
-	    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID);
-	    OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL);
-	    OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL);
-	    OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL);
-	    OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID);
-        } else {
-	    unsigned long ulOrigPIXCLKSDATA;
-	    unsigned long ulOrigTV_MASTER_CNTL;
-	    unsigned long ulOrigTV_DAC_CNTL;
-	    unsigned long ulOrigTV_PRE_DAC_MUX_CNTL;
-	    unsigned long ulOrigDAC_CNTL2;
-	    unsigned long ulData;
-	    unsigned long ulMask;
-
-	    ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
-
-	    ulData            = ulOrigPIXCLKSDATA;
-	    ulData           &= ~(RADEON_PIX2CLK_ALWAYS_ONb
-				  | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
-	    ulMask            = ~(RADEON_PIX2CLK_ALWAYS_ONb
-			  | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
-	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask);
-
-	    ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL);
-	    ulData               = ulOrigTV_MASTER_CNTL;
-	    ulData              &= ~RADEON_TVCLK_ALWAYS_ONb;
-	    OUTREG(RADEON_TV_MASTER_CNTL, ulData);
-
-	    ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2);
-	    ulData          = ulOrigDAC_CNTL2;
-	    ulData          &= ~RADEON_DAC2_DAC2_CLK_SEL;
-	    OUTREG(RADEON_DAC_CNTL2, ulData);
-
-	    ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL);
-
-	    ulData  = 0x00880213;
-	    OUTREG(RADEON_TV_DAC_CNTL, ulData);
-
-	    ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
-
-	    ulData  =  (RADEON_Y_RED_EN
-			| RADEON_C_GRN_EN
-			| RADEON_CMP_BLU_EN
-			| RADEON_RED_MX_FORCE_DAC_DATA
-			| RADEON_GRN_MX_FORCE_DAC_DATA
-			| RADEON_BLU_MX_FORCE_DAC_DATA);
-            if (IS_R300_VARIANT)
-		ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
-	    else
-		ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
-	    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData);
-
-	    usleep(10000);
-
-	    ulData     = INREG(RADEON_TV_DAC_CNTL);
-	    bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0;
-
-	    ulData    = ulOrigPIXCLKSDATA;
-	    ulMask    = 0xFFFFFFFFL;
-	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask);
-
-	    OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL);
-	    OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2);
-	    OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL);
-	    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL);
-	}
-#endif
-	return MT_UNKNOWN;
-    }
-
-    return(bConnected ? MT_CRT : MT_NONE);
-}
-#endif
-
-static RADEONMonitorType
-legacy_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output)
-{
-    RADEONInfoPtr info      = RADEONPTR(pScrn);
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    RADEONMonitorType found = MT_NONE;
-
-    if (OUTPUT_IS_TV) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
-	    if (radeon_output->type == OUTPUT_STV)
-		radeon_output->MonType = MT_STV;
-	    else
-		radeon_output->MonType = MT_CTV;
-	} else {
-	    if (info->InternalTVOut) {
-		if (radeon_output->load_detection)
-		    radeon_output->MonType = radeon_detect_tv(pScrn);
-		else
-		    radeon_output->MonType = MT_NONE;
-	    }
-	}
-    } else {
-	if (radeon_output->DACType == DAC_PRIMARY) {
-	    if (radeon_output->load_detection)
-		found = radeon_detect_primary_dac(pScrn, TRUE);
-	} else if (radeon_output->DACType == DAC_TVDAC) {
-	    if (radeon_output->load_detection) {
-		if (info->ChipFamily == CHIP_FAMILY_R200)
-		    found = radeon_detect_ext_dac(pScrn);
-		else
-		    found = radeon_detect_tv_dac(pScrn, TRUE);
-	    } else
-		found = MT_NONE;
-	}
-    }
-
-    return found;
-}
 
 /* Primary Head (DVI or Laptop Int. panel)*/
 /* A ddc capable display connected on DVI port */
@@ -818,23 +465,12 @@ static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr
 static void
 radeon_dpms(xf86OutputPtr output, int mode)
 {
-    ScrnInfoPtr pScrn  = output->scrn;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONInfoPtr info = RADEONPTR(output->scrn);
 
     if (IS_AVIVO_VARIANT) {
 	atombios_output_dpms(output, mode);
-	return;
-    }
-
-    switch(mode) {
-    case DPMSModeOn:
-	RADEONEnableDisplay(output, TRUE);
-	break;
-    case DPMSModeOff:
-    case DPMSModeSuspend:
-    case DPMSModeStandby:
-	RADEONEnableDisplay(output, FALSE);
-	break;
+    } else {
+	legacy_output_dpms(output, mode);
     }
 }
 
@@ -941,402 +577,16 @@ radeon_mode_prepare(xf86OutputPtr output)
 {
 }
 
-static void RADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save,
-				  DisplayModePtr mode, BOOL IsPrimary)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONEntPtr  pRADEONEnt = RADEONEntPriv(pScrn);
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    int i;
-    CARD32 tmp = info->SavedReg->tmds_pll_cntl & 0xfffff;
-
-    for (i=0; i<4; i++) {
-	if (radeon_output->tmds_pll[i].freq == 0) break;
-	if ((CARD32)(mode->Clock/10) < radeon_output->tmds_pll[i].freq) {
-	    tmp = radeon_output->tmds_pll[i].value ;
-	    break;
-	}
-    }
-
-    if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) {
-	if (tmp & 0xfff00000)
-	    save->tmds_pll_cntl = tmp;
-	else {
-	    save->tmds_pll_cntl = info->SavedReg->tmds_pll_cntl & 0xfff00000;
-	    save->tmds_pll_cntl |= tmp;
-	}
-    } else save->tmds_pll_cntl = tmp;
-
-    save->tmds_transmitter_cntl = info->SavedReg->tmds_transmitter_cntl &
-					~(RADEON_TMDS_TRANSMITTER_PLLRST);
-
-    if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2)
-	save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
-    else /* weird, RV chips got this bit reversed? */
-        save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN);
-
-    save->fp_gen_cntl = info->SavedReg->fp_gen_cntl |
-			 (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
-			  RADEON_FP_CRTC_DONT_SHADOW_HEND );
-
-    save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
-
-    if (pScrn->rgbBits == 8)
-        save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
-    else
-        save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
-
-
-    if (IsPrimary) {
-	if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) {
-	    save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
-	    if (mode->Flags & RADEON_USE_RMX) 
-		save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
-	    else
-		save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
-	} else 
-	    save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1;
-    } else {
-	if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) {
-	    save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
-	    save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
-	} else 
-	    save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
-    }
-
-}
-
-static void RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save,
-				   DisplayModePtr mode, BOOL IsPrimary)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-
-
-    if (pScrn->rgbBits == 8) 
-	save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl |
-				RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
-    else
-	save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
-				~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
-
-    save->fp2_gen_cntl &= ~(RADEON_FP2_ON |
-			    RADEON_FP2_DVO_EN |
-			    RADEON_FP2_DVO_RATE_SEL_SDR);
-
-
-    /* XXX: these may be oem specific */
-    if (IS_R300_VARIANT) {
-	save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
-#if 0
-	if (mode->Clock > 165000)
-	    save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;
-#endif
-    }
-
-    if (IsPrimary) {
-        if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
-            save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
-	    if (mode->Flags & RADEON_USE_RMX)
-		save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
-        } else {
-            save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
-	}
-    } else {
-        if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
-            save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
-            save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
-        } else {
-            save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
-        }
-    }
-
-}
-
-static void RADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save,
-				    DisplayModePtr mode, BOOL IsPrimary)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-
-    save->lvds_pll_cntl = (info->SavedReg->lvds_pll_cntl |
-			   RADEON_LVDS_PLL_EN);
-
-    save->lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
-
-    save->lvds_gen_cntl = info->SavedReg->lvds_gen_cntl;
-    save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
-    save->lvds_gen_cntl &= ~(RADEON_LVDS_ON |
-			     RADEON_LVDS_BLON |
-			     RADEON_LVDS_EN |
-			     RADEON_LVDS_RST_FM);
-
-    if (IS_R300_VARIANT)
-	save->lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
-
-    if (IsPrimary) {
-	if (IS_R300_VARIANT) {
-	    if (mode->Flags & RADEON_USE_RMX)
-		save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
-	} else
-	    save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
-    } else {
-	if (IS_R300_VARIANT) {
-	    save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
-	} else
-	    save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
-    }
-
-}
-
-static void RADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save,
-				   DisplayModePtr mode)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    int    xres = mode->HDisplay;
-    int    yres = mode->VDisplay;
-    float  Hratio, Vratio;
-
-    save->fp_vert_stretch = info->SavedReg->fp_vert_stretch &
-	                    RADEON_VERT_STRETCH_RESERVED;
-    save->fp_horz_stretch = info->SavedReg->fp_horz_stretch &
-	                    (RADEON_HORZ_FP_LOOP_STRETCH |
-	                     RADEON_HORZ_AUTO_RATIO_INC);
-
-    if (radeon_output->MonType != MT_LCD && radeon_output->MonType != MT_DFP)
-	return;
-
-    if (radeon_output->PanelXRes == 0 || radeon_output->PanelYRes == 0) {
-	Hratio = 1.0;
-	Vratio = 1.0;
-    } else {
-	if (xres > radeon_output->PanelXRes) xres = radeon_output->PanelXRes;
-	if (yres > radeon_output->PanelYRes) yres = radeon_output->PanelYRes;
-	    
-	Hratio = (float)xres/(float)radeon_output->PanelXRes;
-	Vratio = (float)yres/(float)radeon_output->PanelYRes;
-    }
-
-    if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) {
-	save->fp_horz_stretch |= ((xres/8-1)<<16);
-    } else {
-	save->fp_horz_stretch |= ((((unsigned long)
-				    (Hratio * RADEON_HORZ_STRETCH_RATIO_MAX)) &
-				   RADEON_HORZ_STRETCH_RATIO_MASK) |
-				  RADEON_HORZ_STRETCH_BLEND |
-				  RADEON_HORZ_STRETCH_ENABLE |
-				  ((radeon_output->PanelXRes/8-1)<<16));
-    }
-
-    if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) {
-	save->fp_vert_stretch |= ((yres-1)<<12);
-    } else {
-	save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX)) &
-				   RADEON_VERT_STRETCH_RATIO_MASK) |
-				  RADEON_VERT_STRETCH_ENABLE |
-				  RADEON_VERT_STRETCH_BLEND |
-				  ((radeon_output->PanelYRes-1)<<12));
-    }
-
-}
-
-static void RADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save,
-				  DisplayModePtr mode, BOOL IsPrimary)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-
-    if (IsPrimary) {
-	if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
-            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
-					~RADEON_DISP_DAC_SOURCE_MASK;
-        } else {
-            save->dac2_cntl = info->SavedReg->dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL);
-        }
-    } else {
-        if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
-            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
-					~RADEON_DISP_DAC_SOURCE_MASK;
-            save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
-        } else {
-            save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC_CLK_SEL;
-        }
-    }
-    save->dac_cntl = (RADEON_DAC_MASK_ALL
-		      | RADEON_DAC_VGA_ADR_EN
-		      | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN));
-
-    save->dac_macro_cntl = info->SavedReg->dac_macro_cntl;
-}
-
-static void
-RADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
-    if (info->ChipFamily == CHIP_FAMILY_R420 ||
-	info->ChipFamily == CHIP_FAMILY_RV410) {
-	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl &
-			     ~(RADEON_TV_DAC_STD_MASK |
-			       RADEON_TV_DAC_BGADJ_MASK |
-			       R420_TV_DAC_DACADJ_MASK |
-			       R420_TV_DAC_RDACPD |
-			       R420_TV_DAC_GDACPD |
-			       R420_TV_DAC_GDACPD |
-			       R420_TV_DAC_TVENABLE);
-    } else {
-	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl &
-			     ~(RADEON_TV_DAC_STD_MASK |
-			       RADEON_TV_DAC_BGADJ_MASK |
-			       RADEON_TV_DAC_DACADJ_MASK |
-			       RADEON_TV_DAC_RDACPD |
-			       RADEON_TV_DAC_GDACPD |
-			       RADEON_TV_DAC_GDACPD);
-    }
-
-    save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
-			  RADEON_TV_DAC_NHOLD |
-			  RADEON_TV_DAC_STD_PS2 |
-			  radeon_output->tv_dac_adj);
-
-}
-
-static void RADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save,
-				  DisplayModePtr mode, BOOL IsPrimary)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-
-    /*0x0028023;*/
-    RADEONInitTvDacCntl(output, save);
-
-    if (IS_R300_VARIANT)
-	save->gpiopad_a = info->SavedReg->gpiopad_a | 1;
-
-    save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL;
-
-    if (IsPrimary) {
-        if (IS_R300_VARIANT) {
-            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
-					~RADEON_DISP_TVDAC_SOURCE_MASK;
-            save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
-        } else if (info->ChipFamily == CHIP_FAMILY_R200) {
-	    save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
-				  ~(R200_FP2_SOURCE_SEL_MASK |
-				    RADEON_FP2_DVO_RATE_SEL_SDR);
-	} else {
-            save->disp_hw_debug = info->SavedReg->disp_hw_debug | RADEON_CRT2_DISP1_SEL;
-        }
-    } else {
-        if (IS_R300_VARIANT) {
-            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
-					~RADEON_DISP_TVDAC_SOURCE_MASK;
-            save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
-	} else if (info->ChipFamily == CHIP_FAMILY_R200) {
-	    save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
-				  ~(R200_FP2_SOURCE_SEL_MASK |
-				    RADEON_FP2_DVO_RATE_SEL_SDR);
-            save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
-        } else {
-            save->disp_hw_debug = info->SavedReg->disp_hw_debug &
-					~RADEON_CRT2_DISP1_SEL;
-        }
-    }
-}
-
-static void
-RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
-			  DisplayModePtr mode, xf86OutputPtr output,
-			  int crtc_num)
-{
-    Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE;
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
-    if (crtc_num == 0)
-	RADEONInitRMXRegisters(output, save, mode);
-
-    if (radeon_output->MonType == MT_CRT) {
-	if (radeon_output->DACType == DAC_PRIMARY) {
-	    RADEONInitDACRegisters(output, save, mode, IsPrimary);
-	} else {
-	    RADEONInitDAC2Registers(output, save, mode, IsPrimary);
-	}
-    } else if (radeon_output->MonType == MT_LCD) {
-	RADEONInitLVDSRegisters(output, save, mode, IsPrimary);
-    } else if (radeon_output->MonType == MT_DFP) {
-	if (radeon_output->TMDSType == TMDS_INT) {
-	    RADEONInitFPRegisters(output, save, mode, IsPrimary);
-	} else {
-	    RADEONInitFP2Registers(output, save, mode, IsPrimary);
-	}
-    } else if (radeon_output->MonType == MT_STV ||
-	       radeon_output->MonType == MT_CTV) {
-	RADEONInitTVRegisters(output, save, mode, IsPrimary);
-    }
-}
-
-static void
-legacy_mode_set(xf86OutputPtr output, DisplayModePtr mode,
-		  DisplayModePtr adjusted_mode)
-{
-    ScrnInfoPtr	    pScrn = output->scrn;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    xf86CrtcPtr	crtc = output->crtc;
-    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-
-    RADEONInitOutputRegisters(pScrn, info->ModeReg, adjusted_mode, output, radeon_crtc->crtc_id);
-
-    if (radeon_crtc->crtc_id == 0)
-	RADEONRestoreRMXRegisters(pScrn, info->ModeReg);
-
-    switch(radeon_output->MonType) {
-    case MT_LCD:
-	ErrorF("restore LVDS\n");
-	RADEONRestoreLVDSRegisters(pScrn, info->ModeReg);
-	break;
-    case MT_DFP:
-	if (radeon_output->TMDSType == TMDS_INT) {
-	    ErrorF("restore FP\n");
-	    RADEONRestoreFPRegisters(pScrn, info->ModeReg);
-	} else {
-	    ErrorF("restore FP2\n");
-	    if (info->IsAtomBios)
-		atombios_external_tmds_setup(output, mode);
-	    else
-		RADEONRestoreDVOChip(pScrn, output);
-	    RADEONRestoreFP2Registers(pScrn, info->ModeReg);
-	}
-	break;
-    case MT_STV:
-    case MT_CTV:
-	ErrorF("restore tv\n");
-	RADEONRestoreDACRegisters(pScrn, info->ModeReg);
-	RADEONRestoreTVRegisters(pScrn, info->ModeReg);
-	break;
-    default:
-	ErrorF("restore dac\n");
-	RADEONRestoreDACRegisters(pScrn, info->ModeReg);
-    }
-
-}
-
 static void
 radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode,
-		  DisplayModePtr adjusted_mode)
+		DisplayModePtr adjusted_mode)
 {
-    ScrnInfoPtr	    pScrn = output->scrn;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONInfoPtr info = RADEONPTR(output->scrn);
 
     if (IS_AVIVO_VARIANT)
 	atombios_output_mode_set(output, mode, adjusted_mode);
     else
-	legacy_mode_set(output, mode, adjusted_mode);
+	legacy_output_mode_set(output, mode, adjusted_mode);
 
 }
 
@@ -1346,423 +596,6 @@ radeon_mode_commit(xf86OutputPtr output)
     radeon_dpms(output, DPMSModeOn);
 }
 
-/* the following functions are based on the load detection code
- * in the beos radeon driver by Thomas Kurschel and the existing
- * load detection code in this driver.
- */
-static RADEONMonitorType
-radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 vclk_ecp_cntl, crtc_ext_cntl;
-    CARD32 dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
-    RADEONMonitorType found = MT_NONE;
-
-    /* save the regs we need */
-    vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
-    crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
-    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
-    dac_cntl = INREG(RADEON_DAC_CNTL);
-    dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL);
-
-    tmp = vclk_ecp_cntl &
-	~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
-    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
-
-    tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
-    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
-
-    tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
-	RADEON_DAC_FORCE_DATA_EN;
-
-    if (color)
-	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
-    else
-	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
-
-    if (IS_R300_VARIANT)
-	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
-    else
-	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
-
-    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
-
-    tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
-    tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
-    OUTREG(RADEON_DAC_CNTL, tmp);
-
-    tmp &= ~(RADEON_DAC_PDWN_R |
-	     RADEON_DAC_PDWN_G |
-	     RADEON_DAC_PDWN_B);
-
-    OUTREG(RADEON_DAC_MACRO_CNTL, tmp);
-
-    usleep(2000);
-
-    if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) {
-	found = MT_CRT;
-	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-		    "Found %s CRT connected to primary DAC\n",
-		    color ? "color" : "bw");
-    }
-
-    /* restore the regs we used */
-    OUTREG(RADEON_DAC_CNTL, dac_cntl);
-    OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
-    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
-    OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
-    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
-
-    return found;
-}
-
-static RADEONMonitorType
-radeon_detect_ext_dac(ScrnInfoPtr pScrn)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
-    CARD32 disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
-    CARD32 disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
-    CARD32 tmp, crtc2_h_total_disp, crtc2_v_total_disp;
-    CARD32 crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
-    RADEONMonitorType found = MT_NONE;
-    int connected = 0;
-    int i = 0;
-
-    /* save the regs we need */
-    gpio_monid = INREG(RADEON_GPIO_MONID);
-    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
-    disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
-    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
-    disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A);
-    disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B);
-    disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C);
-    disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D);
-    disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E);
-    disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F);
-    crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP);
-    crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP);
-    crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
-    crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
-
-    tmp = INREG(RADEON_GPIO_MONID);
-    tmp &= ~RADEON_GPIO_A_0;
-    OUTREG(RADEON_GPIO_MONID, tmp);
-
-    OUTREG(RADEON_FP2_GEN_CNTL,
-	   RADEON_FP2_ON |
-	   RADEON_FP2_PANEL_FORMAT |
-	   R200_FP2_SOURCE_SEL_TRANS_UNIT |
-	   RADEON_FP2_DVO_EN |
-	   R200_FP2_DVO_RATE_SEL_SDR);
-
-    OUTREG(RADEON_DISP_OUTPUT_CNTL,
-	   RADEON_DISP_DAC_SOURCE_RMX |
-	   RADEON_DISP_TRANS_MATRIX_GRAPHICS);
-
-    OUTREG(RADEON_CRTC2_GEN_CNTL,
-	   RADEON_CRTC2_EN |
-	   RADEON_CRTC2_DISP_REQ_EN_B);
-
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
-
-    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
-    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
-    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
-    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
-
-    for (i = 0; i < 200; i++) {
-	tmp = INREG(RADEON_GPIO_MONID);
-	if (tmp & RADEON_GPIO_Y_0)
-	    connected = 1;
-	else
-	    connected = 0;
-
-	if (!connected)
-	    break;
-
-	usleep(1000);
-    }
-
-    if (connected)
-	found = MT_CRT;
-
-    /* restore the regs we used */
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
-    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
-    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
-    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
-    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
-    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
-    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
-    OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
-    OUTREG(RADEON_GPIO_MONID, gpio_monid);
-
-    return found;
-}
-
-static RADEONMonitorType
-radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
-    CARD32 disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
-    RADEONMonitorType found = MT_NONE;
-
-    /* save the regs we need */
-    pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
-    gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0;
-    disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0;
-    disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0;
-    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
-    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
-    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
-    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
-
-    tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
-			   | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
-    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
-
-    if (IS_R300_VARIANT) {
-	OUTREGP(RADEON_GPIOPAD_A, 1, ~1 );
-    }
-
-    tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
-    tmp |= RADEON_CRTC2_CRT2_ON |
-	(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
-
-    OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
-
-    if (IS_R300_VARIANT) {
-	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
-	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
-	OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp);
-    } else {
-	tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
-	OUTREG(RADEON_DISP_HW_DEBUG, tmp);
-    }
-
-    tmp = RADEON_TV_DAC_NBLANK |
-	RADEON_TV_DAC_NHOLD |
-	RADEON_TV_MONITOR_DETECT_EN |
-	RADEON_TV_DAC_STD_PS2;
-
-    OUTREG(RADEON_TV_DAC_CNTL, tmp);
-
-    tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
-	RADEON_DAC2_FORCE_DATA_EN;
-
-    if (color)
-	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
-    else
-	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
-
-    if (IS_R300_VARIANT)
-	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
-    else
-	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
-
-    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
-
-    tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
-    OUTREG(RADEON_DAC_CNTL2, tmp);
-
-    usleep(10000);
-
-    if (IS_R300_VARIANT) {
-	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) {
-	    found = MT_CRT;
-	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-			"Found %s CRT connected to TV DAC\n",
-			color ? "color" : "bw");
-	}
-    } else {
-	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) {
-	    found = MT_CRT;
-	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-			"Found %s CRT connected to TV DAC\n",
-			color ? "color" : "bw");
-	}
-    }
-
-    /* restore regs we used */
-    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
-    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
-    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
-
-    if (IS_R300_VARIANT) {
-	OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-	OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 );
-    } else {
-	OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug);
-    }
-    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl);
-
-    return found;
-}
-
-static RADEONMonitorType
-r300_detect_tv(ScrnInfoPtr pScrn)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl;
-    CARD32 gpiopad_a, disp_output_cntl;
-    RADEONMonitorType found = MT_NONE;
-
-    /* save the regs we need */
-    gpiopad_a = INREG(RADEON_GPIOPAD_A);
-    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
-    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
-    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
-    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
-    disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
-
-    OUTREGP(RADEON_GPIOPAD_A, 0, ~1 );
-
-    OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL );
-
-    OUTREG(RADEON_CRTC2_GEN_CNTL,
-	   RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT );
-
-    tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
-    tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
-    OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp);
-
-    OUTREG(RADEON_DAC_EXT_CNTL,
-	   RADEON_DAC2_FORCE_BLANK_OFF_EN |
-	   RADEON_DAC2_FORCE_DATA_EN |
-	   RADEON_DAC_FORCE_DATA_SEL_RGB |
-	   (0xec << RADEON_DAC_FORCE_DATA_SHIFT ));
-
-    OUTREG(RADEON_TV_DAC_CNTL,
-	   RADEON_TV_DAC_STD_NTSC |
-	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
-	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
-
-    INREG(RADEON_TV_DAC_CNTL);
-
-    usleep(4000);
-
-    OUTREG(RADEON_TV_DAC_CNTL,
-	   RADEON_TV_DAC_NBLANK |
-	   RADEON_TV_DAC_NHOLD |
-	   RADEON_TV_MONITOR_DETECT_EN |
-	   RADEON_TV_DAC_STD_NTSC |
-	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
-	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
-
-    INREG(RADEON_TV_DAC_CNTL);
-
-    usleep(6000);
-
-    tmp = INREG(RADEON_TV_DAC_CNTL);
-    if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) {
-	found = MT_STV;
-	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-		    "S-Video TV connection detected\n");
-    } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) {
-	found = MT_CTV;
-	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-		    "Composite TV connection detected\n" );
-    }
-
-    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl );
-    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
-    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
-    OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
-    OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1);
-
-    return found;
-}
-
-static RADEONMonitorType
-radeon_detect_tv(ScrnInfoPtr pScrn)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 tmp, dac_cntl2, tv_master_cntl;
-    CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl;
-    RADEONMonitorType found = MT_NONE;
-
-    if (IS_R300_VARIANT)
-	return r300_detect_tv(pScrn);
-
-    /* save the regs we need */
-    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
-    tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL);
-    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
-    config_cntl = INREG(RADEON_CONFIG_CNTL);
-    tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
-
-    tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
-    OUTREG(RADEON_DAC_CNTL2, tmp);
-
-    tmp = tv_master_cntl | RADEON_TV_ON;
-    tmp &= ~(RADEON_TV_ASYNC_RST |
-	     RADEON_RESTART_PHASE_FIX |
-	     RADEON_CRT_FIFO_CE_EN |
-	     RADEON_TV_FIFO_CE_EN |
-	     RADEON_RE_SYNC_NOW_SEL_MASK);
-    tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
-
-    OUTREG(RADEON_TV_MASTER_CNTL, tmp);
-
-    tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
-	RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
-	(8 << RADEON_TV_DAC_BGADJ_SHIFT);
-
-    if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
-	tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
-    else
-	tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
-
-    OUTREG(RADEON_TV_DAC_CNTL, tmp);
-
-    tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
-	RADEON_RED_MX_FORCE_DAC_DATA |
-	RADEON_GRN_MX_FORCE_DAC_DATA |
-	RADEON_BLU_MX_FORCE_DAC_DATA |
-	(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
-
-    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
-
-    usleep(3000);
-
-    tmp = INREG(RADEON_TV_DAC_CNTL);
-    if (tmp & RADEON_TV_DAC_GDACDET) {
-	found = MT_STV;
-	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-		    "S-Video TV connection detected\n");
-    } else if (tmp & RADEON_TV_DAC_BDACDET) {
-	found = MT_CTV;
-	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-		    "Composite TV connection detected\n" );
-    }
-
-    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
-    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-    OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl);
-    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
-
-    return found;
-}
-
 static xf86OutputStatus
 radeon_detect(xf86OutputPtr output)
 {
@@ -1851,7 +684,7 @@ radeon_get_modes(xf86OutputPtr output)
 static void
 radeon_destroy (xf86OutputPtr output)
 {
-    if(output->driver_private)
+    if (output->driver_private)
         xfree(output->driver_private);
 }
 
@@ -2813,6 +1646,21 @@ RADEONGetTVInfo(xf86OutputPtr output)
 
 }
 
+static void
+RADEONGetTVDacAdjInfo(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    /* Todo: get this setting from BIOS */
+    radeon_output->tv_dac_adj = default_tvdac_adj[info->ChipFamily];
+    if (info->IsMobility) { /* some mobility chips may different */
+	if (info->ChipFamily == CHIP_FAMILY_RV250)
+	    radeon_output->tv_dac_adj = 0x00880000;
+    }
+}
+
 void RADEONInitConnector(xf86OutputPtr output)
 {
     ScrnInfoPtr	    pScrn = output->scrn;


More information about the xorg-commit mailing list