legacy_crtc.c revision b7e1c893
11.130Schs/*
21.36Scgd * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
31.64Sgwr *                VA Linux Systems Inc., Fremont, California.
41.64Sgwr *
51.13Sglass * All Rights Reserved.
61.13Sglass *
71.64Sgwr * Permission is hereby granted, free of charge, to any person obtaining
81.64Sgwr * a copy of this software and associated documentation files (the
91.64Sgwr * "Software"), to deal in the Software without restriction, including
101.13Sglass * without limitation on the rights to use, copy, modify, merge,
111.13Sglass * publish, distribute, sublicense, and/or sell copies of the Software,
121.13Sglass * and to permit persons to whom the Software is furnished to do so,
131.13Sglass * subject to the following conditions:
141.13Sglass *
151.13Sglass * The above copyright notice and this permission notice (including the
161.13Sglass * next paragraph) shall be included in all copies or substantial
171.13Sglass * portions of the Software.
181.13Sglass *
191.13Sglass * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
201.64Sgwr * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
211.64Sgwr * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
221.64Sgwr * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
231.64Sgwr * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
241.64Sgwr * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
251.13Sglass * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
261.64Sgwr * DEALINGS IN THE SOFTWARE.
271.64Sgwr */
281.64Sgwr
291.66Sgwr#ifdef HAVE_CONFIG_H
301.66Sgwr#include "config.h"
311.64Sgwr#endif
321.64Sgwr
331.64Sgwr#include <string.h>
341.64Sgwr#include <stdio.h>
351.64Sgwr
361.64Sgwr/* X and server generic header files */
371.13Sglass#include "xf86.h"
381.25Sgwr#include "xf86_OSproc.h"
391.3Sglass#include "vgaHW.h"
401.1Sglass#include "xf86Modes.h"
411.1Sglass
421.84Sgwr/* Driver data structures */
431.38Sgwr#include "radeon.h"
441.1Sglass#include "radeon_reg.h"
451.1Sglass#include "radeon_macros.h"
461.52Sgwr#include "radeon_probe.h"
471.1Sglass#include "radeon_version.h"
481.38Sgwr#include "radeon_atombios.h"
491.38Sgwr
501.38Sgwr#ifdef XF86DRI
511.38Sgwr#define _XF86DRI_SERVER_
521.38Sgwr#include "radeon_drm.h"
531.52Sgwr#include "sarea.h"
541.52Sgwr#ifdef DRM_IOCTL_MODESET_CTL
551.52Sgwr#include <sys/ioctl.h>
561.1Sglass#endif
571.1Sglass#endif
581.1Sglass
591.1Sglass/* Write common registers */
601.65Sgwrvoid
611.65SgwrRADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
621.65Sgwr			     RADEONSavePtr restore)
631.65Sgwr{
641.65Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
651.65Sgwr    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
661.65Sgwr    unsigned char *RADEONMMIO = info->MMIO;
671.1Sglass
681.1Sglass    if (info->IsSecondary)
691.1Sglass      return;
701.1Sglass
711.1Sglass    OUTREG(RADEON_OVR_CLR,            restore->ovr_clr);
721.1Sglass    OUTREG(RADEON_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right);
731.83Sgwr    OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom);
741.84Sgwr    OUTREG(RADEON_OV0_SCALE_CNTL,     restore->ov0_scale_cntl);
751.83Sgwr    OUTREG(RADEON_SUBPIC_CNTL,        restore->subpic_cntl);
761.83Sgwr    OUTREG(RADEON_VIPH_CONTROL,       restore->viph_control);
771.83Sgwr    OUTREG(RADEON_I2C_CNTL_1,         restore->i2c_cntl_1);
781.83Sgwr    OUTREG(RADEON_GEN_INT_CNTL,       restore->gen_int_cntl);
791.83Sgwr    OUTREG(RADEON_CAP0_TRIG_CNTL,     restore->cap0_trig_cntl);
801.83Sgwr    OUTREG(RADEON_CAP1_TRIG_CNTL,     restore->cap1_trig_cntl);
811.83Sgwr    OUTREG(RADEON_BUS_CNTL,           restore->bus_cntl);
821.83Sgwr    OUTREG(RADEON_SURFACE_CNTL,       restore->surface_cntl);
831.84Sgwr
841.84Sgwr    if ((info->ChipFamily == CHIP_FAMILY_RS400)  ||
851.84Sgwr	(info->ChipFamily == CHIP_FAMILY_RS480)) {
861.84Sgwr	OUTREG(RS400_DISP2_REQ_CNTL1, restore->disp2_req_cntl1);
871.83Sgwr	OUTREG(RS400_DISP2_REQ_CNTL2, restore->disp2_req_cntl2);
881.83Sgwr	OUTREG(RS400_DMIF_MEM_CNTL1,  restore->dmif_mem_cntl1);
891.104Sjonathan	OUTREG(RS400_DISP1_REQ_CNTL1, restore->disp1_req_cntl1);
901.103Sgwr    }
911.38Sgwr
921.38Sgwr    /* Workaround for the VT switching problem in dual-head mode.  This
931.38Sgwr     * problem only occurs on RV style chips, typically when a FP and
941.38Sgwr     * CRT are connected.
951.120Stsutsui     */
961.38Sgwr    if (pRADEONEnt->HasCRTC2 &&
971.38Sgwr	info->ChipFamily != CHIP_FAMILY_R200 &&
981.74Sgwr	!IS_R300_VARIANT) {
991.38Sgwr	uint32_t tmp;
1001.103Sgwr
1011.110Smrg	tmp = INREG(RADEON_DAC_CNTL2);
1021.107Sgwr	OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL);
1031.107Sgwr	usleep(100000);
1041.107Sgwr    }
1051.78Sgwr}
1061.74Sgwr
1071.74Sgwrvoid
1081.76SgwrRADEONRestoreCrtcBase(ScrnInfoPtr pScrn,
1091.74Sgwr		      RADEONSavePtr restore)
1101.38Sgwr{
1111.74Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1121.74Sgwr    unsigned char *RADEONMMIO = info->MMIO;
1131.38Sgwr
1141.65Sgwr    if (IS_R300_VARIANT)
1151.99Sgwr	OUTREG(R300_CRTC_TILE_X0_Y0,    restore->crtc_tile_x0_y0);
1161.99Sgwr    OUTREG(RADEON_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
1171.99Sgwr    OUTREG(RADEON_CRTC_OFFSET,          restore->crtc_offset);
1181.99Sgwr}
1191.99Sgwr
1201.99Sgwrvoid
1211.81SgwrRADEONRestoreCrtc2Base(ScrnInfoPtr pScrn,
1221.81Sgwr		       RADEONSavePtr restore)
1231.81Sgwr{
1241.81Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1251.81Sgwr    unsigned char *RADEONMMIO = info->MMIO;
1261.81Sgwr
1271.78Sgwr    if (IS_R300_VARIANT)
1281.76Sgwr	OUTREG(R300_CRTC2_TILE_X0_Y0,    restore->crtc2_tile_x0_y0);
1291.76Sgwr    OUTREG(RADEON_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
1301.76Sgwr    OUTREG(RADEON_CRTC2_OFFSET,          restore->crtc2_offset);
1311.76Sgwr}
1321.89Sgwr
1331.89Sgwr/* Write CRTC registers */
1341.75Sgwrvoid
1351.78SgwrRADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
1361.78Sgwr			   RADEONSavePtr restore)
1371.78Sgwr{
1381.78Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1391.98Sgwr    unsigned char *RADEONMMIO = info->MMIO;
1401.98Sgwr
1411.80Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1421.80Sgwr		   "Programming CRTC1, offset: 0x%08x\n",
1431.80Sgwr		   (unsigned)restore->crtc_offset);
1441.80Sgwr
1451.78Sgwr    /* We prevent the CRTC from hitting the memory controller until
1461.78Sgwr     * fully programmed
1471.50Sgwr     */
1481.76Sgwr    OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl |
1491.78Sgwr	   RADEON_CRTC_DISP_REQ_EN_B);
1501.78Sgwr
1511.78Sgwr    OUTREGP(RADEON_CRTC_EXT_CNTL,
1521.78Sgwr	    restore->crtc_ext_cntl,
1531.78Sgwr	    RADEON_CRTC_VSYNC_DIS |
1541.78Sgwr	    RADEON_CRTC_HSYNC_DIS |
1551.78Sgwr	    RADEON_CRTC_DISPLAY_DIS);
1561.78Sgwr
1571.78Sgwr    OUTREG(RADEON_CRTC_H_TOTAL_DISP,    restore->crtc_h_total_disp);
1581.78Sgwr    OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
1591.78Sgwr    OUTREG(RADEON_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
1601.78Sgwr    OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
1611.78Sgwr
1621.78Sgwr    RADEONRestoreCrtcBase(pScrn, restore);
1631.88Sgwr
1641.78Sgwr    OUTREG(RADEON_CRTC_PITCH,           restore->crtc_pitch);
1651.78Sgwr    OUTREG(RADEON_DISP_MERGE_CNTL,      restore->disp_merge_cntl);
1661.87Sgwr
1671.89Sgwr    if (info->IsDellServer) {
1681.88Sgwr	OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
1691.87Sgwr	OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
1701.78Sgwr	OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
1711.78Sgwr	OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
1721.78Sgwr    }
1731.78Sgwr
1741.78Sgwr    OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl);
1751.78Sgwr}
1761.78Sgwr
1771.78Sgwr/* Write CRTC2 registers */
1781.78Sgwrvoid
1791.78SgwrRADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
1801.78Sgwr			    RADEONSavePtr restore)
1811.78Sgwr{
1821.78Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1831.78Sgwr    unsigned char *RADEONMMIO = info->MMIO;
1841.78Sgwr    /*    uint32_t	   crtc2_gen_cntl;*/
1851.78Sgwr
1861.78Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1871.78Sgwr		   "Programming CRTC2, offset: 0x%08x\n",
1881.78Sgwr		   (unsigned)restore->crtc2_offset);
1891.78Sgwr
1901.78Sgwr    /* We prevent the CRTC from hitting the memory controller until
1911.78Sgwr     * fully programmed
1921.78Sgwr     */
1931.78Sgwr    OUTREG(RADEON_CRTC2_GEN_CNTL,
1941.78Sgwr	   restore->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS |
1951.78Sgwr	   RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS |
1961.78Sgwr	   RADEON_CRTC2_DISP_REQ_EN_B);
1971.78Sgwr
1981.78Sgwr    OUTREG(RADEON_CRTC2_H_TOTAL_DISP,    restore->crtc2_h_total_disp);
1991.78Sgwr    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
2001.78Sgwr    OUTREG(RADEON_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
2011.78Sgwr    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
2021.78Sgwr
2031.78Sgwr    OUTREG(RADEON_FP_H2_SYNC_STRT_WID,   restore->fp_h2_sync_strt_wid);
2041.78Sgwr    OUTREG(RADEON_FP_V2_SYNC_STRT_WID,   restore->fp_v2_sync_strt_wid);
2051.78Sgwr
2061.78Sgwr    RADEONRestoreCrtc2Base(pScrn, restore);
2071.76Sgwr
2081.76Sgwr    OUTREG(RADEON_CRTC2_PITCH,           restore->crtc2_pitch);
2091.76Sgwr    OUTREG(RADEON_DISP2_MERGE_CNTL,      restore->disp2_merge_cntl);
2101.76Sgwr
2111.76Sgwr    OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
2121.76Sgwr
2131.76Sgwr}
2141.78Sgwr
2151.76Sgwrstatic void
2161.76SgwrRADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2171.76Sgwr{
2181.38Sgwr    int i = 0;
2191.78Sgwr
2201.78Sgwr    /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
2211.78Sgwr       the cause yet, but this workaround will mask the problem for now.
2221.78Sgwr       Other chips usually will pass at the very first test, so the
2231.78Sgwr       workaround shouldn't have any effect on them. */
2241.78Sgwr    for (i = 0;
2251.78Sgwr	 (i < 10000 &&
2261.78Sgwr	  INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
2271.78Sgwr	 i++);
2281.78Sgwr}
2291.78Sgwr
2301.99Sgwrstatic void
2311.99SgwrRADEONPLLWriteUpdate(ScrnInfoPtr pScrn)
2321.78Sgwr{
2331.78Sgwr    while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
2341.78Sgwr
2351.78Sgwr    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
2361.78Sgwr	    RADEON_PPLL_ATOMIC_UPDATE_W,
2371.82Sgwr	    ~(RADEON_PPLL_ATOMIC_UPDATE_W));
2381.120Stsutsui}
2391.120Stsutsui
2401.120Stsutsuistatic void
2411.78SgwrRADEONPLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2421.38Sgwr{
2431.38Sgwr    int i = 0;
2441.38Sgwr
2451.38Sgwr    /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
2461.39Sgwr       the cause yet, but this workaround will mask the problem for now.
2471.39Sgwr       Other chips usually will pass at the very first test, so the
2481.40Sgwr       workaround shouldn't have any effect on them. */
2491.39Sgwr    for (i = 0;
2501.39Sgwr	 (i < 10000 &&
2511.39Sgwr	  INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
2521.39Sgwr	 i++);
2531.60Sgwr}
2541.60Sgwr
2551.38Sgwrstatic void
2561.38SgwrRADEONPLL2WriteUpdate(ScrnInfoPtr pScrn)
2571.38Sgwr{
2581.38Sgwr    while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
2591.77Sgwr
2601.77Sgwr    OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
2611.38Sgwr	    RADEON_P2PLL_ATOMIC_UPDATE_W,
2621.77Sgwr	    ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
2631.77Sgwr}
2641.2Sglass
2651.78Sgwrstatic uint8_t
2661.78SgwrRADEONComputePLLGain(uint16_t reference_freq, uint16_t ref_div,
2671.78Sgwr		     uint16_t fb_div)
2681.78Sgwr{
2691.78Sgwr    unsigned vcoFreq;
2701.78Sgwr
2711.22Sgwr    if (!ref_div)
2721.122Sthorpej	return 1;
2731.22Sgwr
2741.55Sgwr    vcoFreq = ((unsigned)reference_freq * fb_div) / ref_div;
2751.22Sgwr
2761.22Sgwr    /*
2771.77Sgwr     * This is horribly crude: the VCO frequency range is divided into
2781.77Sgwr     * 3 parts, each part having a fixed PLL gain value.
2791.77Sgwr     */
2801.77Sgwr    if (vcoFreq >= 30000)
2811.77Sgwr	/*
2821.77Sgwr	 * [300..max] MHz : 7
2831.77Sgwr	 */
2841.77Sgwr	return 7;
2851.77Sgwr    else if (vcoFreq >= 18000)
2861.77Sgwr	/*
2871.38Sgwr	 * [180..300) MHz : 4
2881.2Sglass	 */
2891.78Sgwr        return 4;
2901.78Sgwr    else
2911.5Sglass	/*
2921.5Sglass	 * [0..180) MHz : 1
2931.5Sglass	 */
2941.38Sgwr        return 1;
2951.38Sgwr}
2961.2Sglass
2971.38Sgwr/* Write PLL registers */
2981.2Sglassvoid
2991.84SgwrRADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
3001.1Sglass			  RADEONSavePtr restore)
3011.38Sgwr{
3021.38Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
3031.38Sgwr    unsigned char *RADEONMMIO = info->MMIO;
3041.1Sglass    uint8_t pllGain;
3051.38Sgwr
3061.1Sglass#if defined(__powerpc__)
3071.84Sgwr    /* apparently restoring the pll causes a hang??? */
3081.84Sgwr    if (info->MacModel == RADEON_MAC_IBOOK)
3091.84Sgwr	return;
3101.84Sgwr#endif
3111.84Sgwr
3121.84Sgwr    pllGain = RADEONComputePLLGain(info->pll.reference_freq,
3131.84Sgwr				   restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
3141.84Sgwr				   restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK);
3151.1Sglass
3161.38Sgwr    if (info->IsMobility) {
3171.38Sgwr        /* A temporal workaround for the occational blanking on certain laptop panels.
3181.38Sgwr           This appears to related to the PLL divider registers (fail to lock?).
3191.38Sgwr	   It occurs even when all dividers are the same with their old settings.
3201.38Sgwr           In this case we really don't need to fiddle with PLL registers.
3211.38Sgwr           By doing this we can avoid the blanking problem with some panels.
3221.38Sgwr        */
3231.38Sgwr        if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) &&
3241.38Sgwr	    (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) &
3251.38Sgwr				     (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) {
3261.38Sgwr	    OUTREGP(RADEON_CLOCK_CNTL_INDEX,
3271.38Sgwr		    RADEON_PLL_DIV_SEL,
3281.38Sgwr		    ~(RADEON_PLL_DIV_SEL));
3291.78Sgwr	    RADEONPllErrataAfterIndex(info);
3301.78Sgwr	    return;
3311.78Sgwr	}
3321.78Sgwr    }
3331.78Sgwr
3341.78Sgwr    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
3351.78Sgwr	    RADEON_VCLK_SRC_SEL_CPUCLK,
3361.78Sgwr	    ~(RADEON_VCLK_SRC_SEL_MASK));
3371.78Sgwr
3381.78Sgwr    OUTPLLP(pScrn,
3391.83Sgwr	    RADEON_PPLL_CNTL,
3401.83Sgwr	    RADEON_PPLL_RESET
3411.83Sgwr	    | RADEON_PPLL_ATOMIC_UPDATE_EN
3421.83Sgwr	    | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
3431.78Sgwr	    | ((uint32_t)pllGain << RADEON_PPLL_PVG_SHIFT),
3441.79Sgwr	    ~(RADEON_PPLL_RESET
3451.79Sgwr	      | RADEON_PPLL_ATOMIC_UPDATE_EN
3461.50Sgwr	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
3471.78Sgwr	      | RADEON_PPLL_PVG_MASK));
3481.1Sglass
3491.1Sglass    OUTREGP(RADEON_CLOCK_CNTL_INDEX,
3501.38Sgwr	    RADEON_PLL_DIV_SEL,
3511.81Sgwr	    ~(RADEON_PLL_DIV_SEL));
3521.38Sgwr    RADEONPllErrataAfterIndex(info);
3531.38Sgwr
3541.38Sgwr    if (IS_R300_VARIANT ||
3551.38Sgwr	(info->ChipFamily == CHIP_FAMILY_RS300) ||
3561.38Sgwr	(info->ChipFamily == CHIP_FAMILY_RS400) ||
3571.38Sgwr	(info->ChipFamily == CHIP_FAMILY_RS480)) {
3581.38Sgwr	if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
3591.38Sgwr	    /* When restoring console mode, use saved PPLL_REF_DIV
3601.38Sgwr	     * setting.
3611.38Sgwr	     */
3621.38Sgwr	    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
3631.38Sgwr		    restore->ppll_ref_div,
3641.38Sgwr		    0);
3651.38Sgwr	} else {
3661.38Sgwr	    /* R300 uses ref_div_acc field as real ref divider */
3671.38Sgwr	    OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
3681.38Sgwr		    (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
3691.38Sgwr		    ~R300_PPLL_REF_DIV_ACC_MASK);
3701.38Sgwr	}
3711.38Sgwr    } else {
3721.38Sgwr	OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
3731.38Sgwr		restore->ppll_ref_div,
3741.38Sgwr		~RADEON_PPLL_REF_DIV_MASK);
3751.38Sgwr    }
3761.38Sgwr
3771.79Sgwr    OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
3781.79Sgwr	    restore->ppll_div_3,
3791.38Sgwr	    ~RADEON_PPLL_FB3_DIV_MASK);
3801.26Sgwr
3811.26Sgwr    OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
3821.20Sglass	    restore->ppll_div_3,
3831.1Sglass	    ~RADEON_PPLL_POST3_DIV_MASK);
3841.38Sgwr
3851.38Sgwr    RADEONPLLWriteUpdate(pScrn);
3861.38Sgwr    RADEONPLLWaitForReadUpdateComplete(pScrn);
3871.38Sgwr
3881.38Sgwr    OUTPLL(pScrn, RADEON_HTOTAL_CNTL, restore->htotal_cntl);
3891.38Sgwr
3901.38Sgwr    OUTPLLP(pScrn, RADEON_PPLL_CNTL,
3911.38Sgwr	    0,
3921.38Sgwr	    ~(RADEON_PPLL_RESET
3931.38Sgwr	      | RADEON_PPLL_SLEEP
3941.76Sgwr	      | RADEON_PPLL_ATOMIC_UPDATE_EN
3951.76Sgwr	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
3961.75Sgwr
3971.38Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
3981.75Sgwr		   "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
3991.38Sgwr		   restore->ppll_ref_div,
4001.76Sgwr		   restore->ppll_div_3,
4011.38Sgwr		   (unsigned)restore->htotal_cntl,
4021.38Sgwr		   INPLL(pScrn, RADEON_PPLL_CNTL));
4031.38Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
4041.92Sgwr		   "Wrote: rd=%d, fd=%d, pd=%d\n",
4051.92Sgwr		   restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
4061.76Sgwr		   restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
4071.84Sgwr		   (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16);
4081.84Sgwr
4091.38Sgwr    usleep(50000); /* Let the clock to lock */
4101.2Sglass
4111.65Sgwr    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
4121.65Sgwr	    RADEON_VCLK_SRC_SEL_PPLLCLK,
4131.65Sgwr	    ~(RADEON_VCLK_SRC_SEL_MASK));
4141.38Sgwr
4151.82Sgwr    /*OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_ecp_cntl);*/
4161.76Sgwr
4171.101Sgwr    ErrorF("finished PLL1\n");
4181.38Sgwr
4191.92Sgwr}
4201.92Sgwr
4211.92Sgwr/* Write PLL2 registers */
4221.92Sgwrvoid
4231.38SgwrRADEONRestorePLL2Registers(ScrnInfoPtr pScrn,
4241.76Sgwr			   RADEONSavePtr restore)
4251.76Sgwr{
4261.76Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
4271.76Sgwr    uint8_t pllGain;
4281.76Sgwr
4291.76Sgwr    pllGain = RADEONComputePLLGain(info->pll.reference_freq,
4301.76Sgwr                                   restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
4311.1Sglass                                   restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK);
4321.66Sgwr
4331.66Sgwr
4341.99Sgwr    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
4351.99Sgwr	    RADEON_PIX2CLK_SRC_SEL_CPUCLK,
4361.99Sgwr	    ~(RADEON_PIX2CLK_SRC_SEL_MASK));
4371.79Sgwr
4381.79Sgwr    OUTPLLP(pScrn,
4391.79Sgwr	    RADEON_P2PLL_CNTL,
4401.79Sgwr	    RADEON_P2PLL_RESET
4411.79Sgwr	    | RADEON_P2PLL_ATOMIC_UPDATE_EN
4421.79Sgwr	    | ((uint32_t)pllGain << RADEON_P2PLL_PVG_SHIFT),
4431.102Sthorpej	    ~(RADEON_P2PLL_RESET
4441.102Sthorpej	      | RADEON_P2PLL_ATOMIC_UPDATE_EN
4451.79Sgwr	      | RADEON_P2PLL_PVG_MASK));
4461.79Sgwr
4471.79Sgwr
4481.79Sgwr    OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
4491.79Sgwr	    restore->p2pll_ref_div,
4501.83Sgwr	    ~RADEON_P2PLL_REF_DIV_MASK);
4511.83Sgwr
4521.83Sgwr    OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
4531.83Sgwr	    restore->p2pll_div_0,
4541.83Sgwr	    ~RADEON_P2PLL_FB0_DIV_MASK);
4551.130Schs
4561.83Sgwr    OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
4571.83Sgwr	    restore->p2pll_div_0,
4581.83Sgwr	    ~RADEON_P2PLL_POST0_DIV_MASK);
4591.83Sgwr
4601.83Sgwr    RADEONPLL2WriteUpdate(pScrn);
4611.83Sgwr    RADEONPLL2WaitForReadUpdateComplete(pScrn);
4621.83Sgwr
4631.83Sgwr    OUTPLL(pScrn, RADEON_HTOTAL2_CNTL, restore->htotal_cntl2);
4641.83Sgwr
4651.83Sgwr    OUTPLLP(pScrn, RADEON_P2PLL_CNTL,
4661.83Sgwr	    0,
4671.83Sgwr	    ~(RADEON_P2PLL_RESET
4681.83Sgwr	      | RADEON_P2PLL_SLEEP
4691.83Sgwr	      | RADEON_P2PLL_ATOMIC_UPDATE_EN));
4701.84Sgwr
4711.84Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
4721.84Sgwr		   "Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
4731.84Sgwr		   (unsigned)restore->p2pll_ref_div,
4741.84Sgwr		   (unsigned)restore->p2pll_div_0,
4751.84Sgwr		   (unsigned)restore->htotal_cntl2,
4761.79Sgwr		   INPLL(pScrn, RADEON_P2PLL_CNTL));
4771.88Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
4781.84Sgwr		   "Wrote2: rd=%u, fd=%u, pd=%u\n",
4791.84Sgwr		   (unsigned)restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
4801.84Sgwr		   (unsigned)restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK,
4811.84Sgwr		   (unsigned)((restore->p2pll_div_0 &
4821.84Sgwr			       RADEON_P2PLL_POST0_DIV_MASK) >>16));
4831.84Sgwr
4841.84Sgwr    usleep(5000); /* Let the clock to lock */
4851.79Sgwr
4861.84Sgwr    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
4871.84Sgwr	    RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
4881.84Sgwr	    ~(RADEON_PIX2CLK_SRC_SEL_MASK));
4891.84Sgwr
4901.88Sgwr    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl);
4911.87Sgwr
4921.84Sgwr    ErrorF("finished PLL2\n");
4931.84Sgwr
4941.79Sgwr}
4951.79Sgwr
4961.84Sgwr/* Read common registers */
4971.79Sgwrvoid
4981.79SgwrRADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
4991.84Sgwr{
5001.79Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
5011.79Sgwr    unsigned char *RADEONMMIO = info->MMIO;
5021.84Sgwr
5031.79Sgwr    save->ovr_clr            = INREG(RADEON_OVR_CLR);
5041.79Sgwr    save->ovr_wid_left_right = INREG(RADEON_OVR_WID_LEFT_RIGHT);
5051.79Sgwr    save->ovr_wid_top_bottom = INREG(RADEON_OVR_WID_TOP_BOTTOM);
5061.79Sgwr    save->ov0_scale_cntl     = INREG(RADEON_OV0_SCALE_CNTL);
5071.79Sgwr    save->subpic_cntl        = INREG(RADEON_SUBPIC_CNTL);
5081.79Sgwr    save->viph_control       = INREG(RADEON_VIPH_CONTROL);
5091.79Sgwr    save->i2c_cntl_1         = INREG(RADEON_I2C_CNTL_1);
5101.79Sgwr    save->gen_int_cntl       = INREG(RADEON_GEN_INT_CNTL);
5111.79Sgwr    save->cap0_trig_cntl     = INREG(RADEON_CAP0_TRIG_CNTL);
5121.79Sgwr    save->cap1_trig_cntl     = INREG(RADEON_CAP1_TRIG_CNTL);
5131.79Sgwr    save->bus_cntl           = INREG(RADEON_BUS_CNTL);
5141.79Sgwr    save->surface_cntl	     = INREG(RADEON_SURFACE_CNTL);
5151.79Sgwr    save->grph_buffer_cntl   = INREG(RADEON_GRPH_BUFFER_CNTL);
5161.79Sgwr    save->grph2_buffer_cntl  = INREG(RADEON_GRPH2_BUFFER_CNTL);
5171.79Sgwr
5181.79Sgwr    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
5191.79Sgwr	(info->ChipFamily == CHIP_FAMILY_RS480)) {
5201.79Sgwr	save->disp2_req_cntl1 = INREG(RS400_DISP2_REQ_CNTL1);
5211.79Sgwr	save->disp2_req_cntl2 = INREG(RS400_DISP2_REQ_CNTL2);
5221.79Sgwr	save->dmif_mem_cntl1  = INREG(RS400_DMIF_MEM_CNTL1);
5231.79Sgwr	save->disp1_req_cntl1 = INREG(RS400_DISP1_REQ_CNTL1);
5241.79Sgwr    }
5251.79Sgwr}
5261.79Sgwr
5271.79Sgwr/* Read CRTC registers */
5281.79Sgwrvoid
5291.79SgwrRADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
5301.79Sgwr{
5311.84Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
5321.79Sgwr    unsigned char *RADEONMMIO = info->MMIO;
5331.79Sgwr
5341.79Sgwr    save->crtc_gen_cntl        = INREG(RADEON_CRTC_GEN_CNTL);
5351.79Sgwr    save->crtc_ext_cntl        = INREG(RADEON_CRTC_EXT_CNTL);
5361.79Sgwr    save->crtc_h_total_disp    = INREG(RADEON_CRTC_H_TOTAL_DISP);
5371.79Sgwr    save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID);
5381.79Sgwr    save->crtc_v_total_disp    = INREG(RADEON_CRTC_V_TOTAL_DISP);
5391.79Sgwr    save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID);
5401.80Sgwr
5411.80Sgwr    save->crtc_offset          = INREG(RADEON_CRTC_OFFSET);
5421.84Sgwr    save->crtc_offset_cntl     = INREG(RADEON_CRTC_OFFSET_CNTL);
5431.84Sgwr    save->crtc_pitch           = INREG(RADEON_CRTC_PITCH);
5441.79Sgwr    save->disp_merge_cntl      = INREG(RADEON_DISP_MERGE_CNTL);
5451.79Sgwr
5461.2Sglass    if (IS_R300_VARIANT)
5471.78Sgwr	save->crtc_tile_x0_y0 =  INREG(R300_CRTC_TILE_X0_Y0);
5481.78Sgwr
5491.26Sgwr    if (info->IsDellServer) {
5501.39Sgwr	save->tv_dac_cntl      = INREG(RADEON_TV_DAC_CNTL);
5511.80Sgwr	save->dac2_cntl        = INREG(RADEON_DAC_CNTL2);
5521.78Sgwr	save->disp_hw_debug    = INREG (RADEON_DISP_HW_DEBUG);
5531.78Sgwr	save->crtc2_gen_cntl   = INREG(RADEON_CRTC2_GEN_CNTL);
5541.78Sgwr    }
5551.78Sgwr
5561.78Sgwr    /* track if the crtc is enabled for text restore */
5571.78Sgwr    if (save->crtc_ext_cntl & RADEON_CRTC_DISPLAY_DIS)
5581.78Sgwr	info->crtc_on = FALSE;
5591.26Sgwr    else
5601.83Sgwr	info->crtc_on = TRUE;
5611.83Sgwr
5621.83Sgwr}
5631.83Sgwr
5641.78Sgwr/* Read CRTC2 registers */
5651.78Sgwrvoid
5661.78SgwrRADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
5671.78Sgwr{
5681.76Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
5691.78Sgwr    unsigned char *RADEONMMIO = info->MMIO;
5701.81Sgwr
5711.81Sgwr    save->crtc2_gen_cntl        = INREG(RADEON_CRTC2_GEN_CNTL);
5721.78Sgwr    save->crtc2_h_total_disp    = INREG(RADEON_CRTC2_H_TOTAL_DISP);
5731.78Sgwr    save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
5741.78Sgwr    save->crtc2_v_total_disp    = INREG(RADEON_CRTC2_V_TOTAL_DISP);
5751.26Sgwr    save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
5761.80Sgwr
5771.38Sgwr    save->crtc2_offset          = INREG(RADEON_CRTC2_OFFSET);
5781.38Sgwr    save->crtc2_offset_cntl     = INREG(RADEON_CRTC2_OFFSET_CNTL);
5791.38Sgwr    save->crtc2_pitch           = INREG(RADEON_CRTC2_PITCH);
5801.38Sgwr
5811.38Sgwr    if (IS_R300_VARIANT)
5821.38Sgwr	save->crtc2_tile_x0_y0 =  INREG(R300_CRTC2_TILE_X0_Y0);
5831.80Sgwr
5841.77Sgwr    save->fp_h2_sync_strt_wid   = INREG (RADEON_FP_H2_SYNC_STRT_WID);
5851.80Sgwr    save->fp_v2_sync_strt_wid   = INREG (RADEON_FP_V2_SYNC_STRT_WID);
5861.50Sgwr
5871.50Sgwr    save->disp2_merge_cntl      = INREG(RADEON_DISP2_MERGE_CNTL);
5881.38Sgwr
5891.38Sgwr    /* track if the crtc is enabled for text restore */
5901.80Sgwr    if (save->crtc2_gen_cntl & RADEON_CRTC2_DISP_DIS)
5911.80Sgwr	info->crtc2_on = FALSE;
5921.80Sgwr    else
5931.65Sgwr	info->crtc2_on = TRUE;
5941.65Sgwr
5951.80Sgwr}
5961.65Sgwr
5971.65Sgwr/* Read PLL registers */
5981.38Sgwrvoid
5991.38SgwrRADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
6001.80Sgwr{
6011.80Sgwr    save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV);
6021.38Sgwr    save->ppll_div_3   = INPLL(pScrn, RADEON_PPLL_DIV_3);
6031.80Sgwr    save->htotal_cntl  = INPLL(pScrn, RADEON_HTOTAL_CNTL);
6041.80Sgwr    save->vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
6051.38Sgwr
6061.80Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
6071.80Sgwr		   "Read: 0x%08x 0x%08x 0x%08x\n",
6081.38Sgwr		   save->ppll_ref_div,
6091.38Sgwr		   save->ppll_div_3,
6101.80Sgwr		   (unsigned)save->htotal_cntl);
6111.80Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
6121.38Sgwr		   "Read: rd=%d, fd=%d, pd=%d\n",
6131.80Sgwr		   save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
6141.80Sgwr		   save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
6151.38Sgwr		   (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16);
6161.38Sgwr}
6171.38Sgwr
6181.38Sgwr/* Read PLL registers */
6191.38Sgwrvoid
6201.38SgwrRADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
6211.80Sgwr{
6221.38Sgwr    save->p2pll_ref_div = INPLL(pScrn, RADEON_P2PLL_REF_DIV);
6231.1Sglass    save->p2pll_div_0   = INPLL(pScrn, RADEON_P2PLL_DIV_0);
6241.5Sglass    save->htotal_cntl2  = INPLL(pScrn, RADEON_HTOTAL2_CNTL);
6251.80Sgwr    save->pixclks_cntl  = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
6261.80Sgwr
6271.80Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
6281.38Sgwr		   "Read: 0x%08x 0x%08x 0x%08x\n",
6291.38Sgwr		   (unsigned)save->p2pll_ref_div,
6301.38Sgwr		   (unsigned)save->p2pll_div_0,
6311.38Sgwr		   (unsigned)save->htotal_cntl2);
6321.38Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
6331.80Sgwr		   "Read: rd=%u, fd=%u, pd=%u\n",
6341.38Sgwr		   (unsigned)(save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK),
6351.38Sgwr		   (unsigned)(save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK),
6361.38Sgwr		   (unsigned)((save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK)
6371.80Sgwr			      >> 16));
6381.1Sglass}
6391.38Sgwr
6401.83Sgwrvoid
6411.80Sgwrradeon_crtc_modeset_ioctl(xf86CrtcPtr crtc, Bool post)
6421.38Sgwr{
6431.38Sgwr#if defined(XF86DRI) && defined(DRM_IOCTL_MODESET_CTL)
6441.80Sgwr    RADEONInfoPtr info = RADEONPTR(crtc->scrn);
6451.38Sgwr    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
6461.38Sgwr    struct drm_modeset_ctl modeset;
6471.38Sgwr    unsigned char *RADEONMMIO = info->MMIO;
6481.50Sgwr
6491.50Sgwr    if (!info->directRenderingEnabled)
6501.50Sgwr	return;
6511.50Sgwr
6521.50Sgwr    modeset.crtc = radeon_crtc->crtc_id;
6531.50Sgwr    modeset.cmd = post ? _DRM_POST_MODESET : _DRM_PRE_MODESET;
6541.38Sgwr
6551.80Sgwr    ioctl(info->dri->drmFD, DRM_IOCTL_MODESET_CTL, &modeset);
6561.80Sgwr
6571.80Sgwr    info->ModeReg->gen_int_cntl = INREG( RADEON_GEN_INT_CNTL );
6581.80Sgwr#endif
6591.80Sgwr}
6601.80Sgwr
6611.80Sgwrvoid
6621.80Sgwrlegacy_crtc_dpms(xf86CrtcPtr crtc, int mode)
6631.80Sgwr{
6641.80Sgwr    int mask;
6651.80Sgwr    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
6661.80Sgwr    RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
6671.80Sgwr    unsigned char *RADEONMMIO = pRADEONEnt->MMIO;
6681.80Sgwr
6691.38Sgwr    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);
6701.80Sgwr
6711.80Sgwr    if (mode == DPMSModeOff)
6721.80Sgwr	radeon_crtc_modeset_ioctl(crtc, FALSE);
6731.81Sgwr
6741.81Sgwr    switch(mode) {
6751.80Sgwr    case DPMSModeOn:
6761.80Sgwr	if (radeon_crtc->crtc_id) {
6771.80Sgwr	    OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask);
6781.80Sgwr	} else {
6791.80Sgwr	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
6801.80Sgwr	    OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask);
6811.83Sgwr	}
6821.80Sgwr	break;
6831.38Sgwr    case DPMSModeStandby:
6841.80Sgwr	if (radeon_crtc->crtc_id) {
6851.80Sgwr	    OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask);
6861.38Sgwr	} else {
6871.80Sgwr	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
6881.80Sgwr	    OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask);
6891.80Sgwr	}
6901.83Sgwr	break;
6911.38Sgwr    case DPMSModeSuspend:
6921.78Sgwr	if (radeon_crtc->crtc_id) {
6931.1Sglass	    OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask);
6941.1Sglass	} else {
6951.78Sgwr	    OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B);
6961.78Sgwr	    OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask);
6971.78Sgwr	}
6981.78Sgwr	break;
6991.78Sgwr    case DPMSModeOff:
7001.38Sgwr	if (radeon_crtc->crtc_id) {
7011.78Sgwr	    OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
7021.26Sgwr	} else {
7031.78Sgwr	    OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B);
7041.78Sgwr	    OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask);
7051.78Sgwr	}
7061.38Sgwr	break;
7071.78Sgwr    }
7081.78Sgwr
7091.78Sgwr    if (mode != DPMSModeOff) {
7101.78Sgwr	radeon_crtc_modeset_ioctl(crtc, TRUE);
7111.38Sgwr	radeon_crtc_load_lut(crtc);
7121.78Sgwr    }
7131.78Sgwr}
7141.78Sgwr
7151.78Sgwr
7161.78Sgwr/* Define common registers for requested video mode */
7171.78Sgwrvoid
7181.38SgwrRADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info)
7191.38Sgwr{
7201.78Sgwr    save->ovr_clr            = 0;
7211.78Sgwr    save->ovr_wid_left_right = 0;
7221.26Sgwr    save->ovr_wid_top_bottom = 0;
7231.26Sgwr    save->ov0_scale_cntl     = 0;
7241.38Sgwr    save->subpic_cntl        = 0;
7251.38Sgwr    save->viph_control       = 0;
7261.38Sgwr    save->i2c_cntl_1         = 0;
7271.38Sgwr    save->rbbm_soft_reset    = 0;
7281.38Sgwr    save->cap0_trig_cntl     = 0;
7291.76Sgwr    save->cap1_trig_cntl     = 0;
7301.38Sgwr    save->bus_cntl           = info->BusCntl;
7311.1Sglass
7321.38Sgwr    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
7331.1Sglass	(info->ChipFamily == CHIP_FAMILY_RS480)) {
7341.38Sgwr	save->disp2_req_cntl1 = info->SavedReg->disp2_req_cntl1;
7351.38Sgwr	save->disp2_req_cntl2 = info->SavedReg->disp2_req_cntl2;
7361.26Sgwr	save->dmif_mem_cntl1  = info->SavedReg->dmif_mem_cntl1;
7371.67Sgwr	save->disp1_req_cntl1 = info->SavedReg->disp1_req_cntl1;
7381.76Sgwr    }
7391.67Sgwr
7401.67Sgwr    /*
7411.67Sgwr     * If bursts are enabled, turn on discards
7421.76Sgwr     * Radeon doesn't have write bursts
7431.67Sgwr     */
7441.67Sgwr    if (save->bus_cntl & (RADEON_BUS_READ_BURST))
7451.38Sgwr	save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN;
7461.78Sgwr}
7471.56Sgwr
7481.38Sgwrvoid
7491.38SgwrRADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save)
7501.38Sgwr{
7511.1Sglass    save->surface_cntl = 0;
7521.1Sglass
7531.75Sgwr#if X_BYTE_ORDER == X_BIG_ENDIAN
7541.75Sgwr    /* We must set both apertures as they can be both used to map the entire
7551.75Sgwr     * video memory. -BenH.
7561.75Sgwr     */
7571.75Sgwr    switch (crtc->scrn->bitsPerPixel) {
7581.75Sgwr    case 16:
7591.75Sgwr	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP;
7601.75Sgwr	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP;
7611.75Sgwr	break;
7621.75Sgwr
7631.75Sgwr    case 32:
7641.75Sgwr	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP;
7651.75Sgwr	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP;
7661.94Sgwr	break;
7671.94Sgwr    }
7681.94Sgwr#endif
7691.94Sgwr
7701.94Sgwr}
7711.94Sgwr
7721.75Sgwrvoid
7731.75SgwrRADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save,
7741.75Sgwr		   int x, int y)
7751.75Sgwr{
7761.75Sgwr    ScrnInfoPtr pScrn = crtc->scrn;
7771.75Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
7781.75Sgwr    int    Base;
7791.75Sgwr#ifdef XF86DRI
7801.75Sgwr    drm_radeon_sarea_t *pSAREAPriv;
7811.75Sgwr    XF86DRISAREAPtr pSAREA;
7821.75Sgwr#endif
7831.75Sgwr
7841.75Sgwr    save->crtc_offset      = pScrn->fbOffset;
7851.94Sgwr#ifdef XF86DRI
7861.94Sgwr    if (info->dri && info->dri->allowPageFlip)
7871.94Sgwr	save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL;
7881.94Sgwr    else
7891.94Sgwr#endif
7901.75Sgwr	save->crtc_offset_cntl = 0;
7911.76Sgwr
7921.75Sgwr    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
7931.75Sgwr       if (IS_R300_VARIANT)
7941.75Sgwr          save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
7951.75Sgwr				     R300_CRTC_MICRO_TILE_BUFFER_DIS |
7961.75Sgwr				     R300_CRTC_MACRO_TILE_EN);
7971.75Sgwr       else
7981.81Sgwr          save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN;
7991.81Sgwr    }
8001.81Sgwr    else {
8011.81Sgwr       if (IS_R300_VARIANT)
8021.38Sgwr          save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
8031.38Sgwr				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
8041.38Sgwr				      R300_CRTC_MACRO_TILE_EN);
8051.7Sglass       else
8061.81Sgwr          save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
8071.81Sgwr    }
8081.81Sgwr
8091.81Sgwr    Base = pScrn->fbOffset;
8101.81Sgwr
8111.81Sgwr    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
8121.81Sgwr        if (IS_R300_VARIANT) {
8131.81Sgwr	/* On r300/r400 when tiling is enabled crtc_offset is set to the address of
8141.81Sgwr	 * the surface.  the x/y offsets are handled by the X_Y tile reg for each crtc
8151.81Sgwr	 * Makes tiling MUCH easier.
8161.81Sgwr	 */
8171.81Sgwr             save->crtc_tile_x0_y0 = x | (y << 16);
8181.38Sgwr             Base &= ~0x7ff;
8191.81Sgwr         } else {
8201.7Sglass	     /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the
8211.7Sglass		drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes
8221.7Sglass		flickering when scrolling vertically in a virtual screen, possibly because crtc will
8231.7Sglass		pick up the new offset value at the end of each scanline, but the new offset_cntl value
8241.7Sglass		only after a vsync. We'd probably need to wait (in drm) for vsync and only then update
8251.80Sgwr		OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */
8261.80Sgwr	     /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/
8271.7Sglass#if 0
8281.38Sgwr	     /* try to get rid of flickering when scrolling at least for 2d */
8291.38Sgwr#ifdef XF86DRI
8301.7Sglass	     if (!info->have3DWindows)
8311.38Sgwr#endif
8321.7Sglass		 save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL;
8331.80Sgwr#endif
8341.80Sgwr
8351.38Sgwr             int byteshift = info->CurrentLayout.bitsPerPixel >> 4;
8361.26Sgwr             /* crtc uses 256(bytes)x8 "half-tile" start addresses? */
8371.38Sgwr             int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11;
8381.26Sgwr             Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
8391.38Sgwr             save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16);
8401.80Sgwr         }
8411.80Sgwr    }
8421.26Sgwr    else {
8431.38Sgwr       int offset = y * info->CurrentLayout.displayWidth + x;
8441.38Sgwr       switch (info->CurrentLayout.pixel_code) {
8451.80Sgwr       case 15:
8461.26Sgwr       case 16: offset *= 2; break;
8471.38Sgwr       case 24: offset *= 3; break;
8481.26Sgwr       case 32: offset *= 4; break;
8491.38Sgwr       }
8501.38Sgwr       Base += offset;
8511.38Sgwr    }
8521.38Sgwr
8531.1Sglass    if (crtc->rotatedData != NULL) {
8541.1Sglass	Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
8551.1Sglass    }
8561.38Sgwr
8571.46Sgwr    Base &= ~7;                 /* 3 lower bits are always 0 */
8581.46Sgwr
8591.38Sgwr
8601.38Sgwr#ifdef XF86DRI
8611.38Sgwr    if (info->directRenderingInited) {
8621.38Sgwr	/* note cannot use pScrn->pScreen since this is unitialized when called from
8631.38Sgwr	   RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */
8641.1Sglass        /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for
8651.38Sgwr	 *** pageflipping!
8661.38Sgwr	 ***/
8671.38Sgwr	pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
8681.1Sglass	/* can't get at sarea in a semi-sane way? */
8691.39Sgwr	pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec));
8701.39Sgwr
8711.73Sfair	pSAREA->frame.x = (Base  / info->CurrentLayout.pixel_bytes)
8721.39Sgwr	    % info->CurrentLayout.displayWidth;
8731.39Sgwr	pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes)
8741.39Sgwr	    / info->CurrentLayout.displayWidth;
8751.38Sgwr	pSAREA->frame.width = pScrn->frameX1 - x + 1;
8761.80Sgwr	pSAREA->frame.height = pScrn->frameY1 - y + 1;
8771.38Sgwr
8781.38Sgwr	if (pSAREAPriv->pfCurrentPage == 1) {
8791.80Sgwr	    Base += info->dri->backOffset - info->dri->frontOffset;
8801.38Sgwr	}
8811.38Sgwr    }
8821.80Sgwr#endif
8831.38Sgwr    save->crtc_offset = Base;
8841.38Sgwr
8851.38Sgwr}
8861.38Sgwr
8871.40Sgwr/* Define CRTC registers for requested video mode */
8881.40Sgwrstatic Bool
8891.40SgwrRADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
8901.46Sgwr			DisplayModePtr mode)
8911.40Sgwr{
8921.76Sgwr    ScrnInfoPtr pScrn = crtc->scrn;
8931.76Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
8941.76Sgwr    int    format;
8951.38Sgwr    int    hsync_start;
8961.38Sgwr    int    hsync_wid;
8971.38Sgwr    int    vsync_wid;
8981.80Sgwr
8991.80Sgwr    switch (info->CurrentLayout.pixel_code) {
9001.80Sgwr    case 4:  format = 1; break;
9011.38Sgwr    case 8:  format = 2; break;
9021.80Sgwr    case 15: format = 3; break;      /*  555 */
9031.80Sgwr    case 16: format = 4; break;      /*  565 */
9041.80Sgwr    case 24: format = 5; break;      /*  RGB */
9051.80Sgwr    case 32: format = 6; break;      /* xRGB */
9061.26Sgwr    default:
9071.26Sgwr	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
9081.38Sgwr		   "Unsupported pixel depth (%d)\n",
9091.81Sgwr		   info->CurrentLayout.bitsPerPixel);
9101.38Sgwr	return FALSE;
9111.38Sgwr    }
9121.26Sgwr
9131.80Sgwr    /*save->bios_4_scratch = info->SavedReg->bios_4_scratch;*/
9141.80Sgwr    save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
9151.38Sgwr			   | RADEON_CRTC_EN
9161.38Sgwr			   | (format << 8)
9171.38Sgwr			   | ((mode->Flags & V_DBLSCAN)
9181.38Sgwr			      ? RADEON_CRTC_DBL_SCAN_EN
9191.38Sgwr			      : 0)
9201.38Sgwr			   | ((mode->Flags & V_CSYNC)
9211.38Sgwr			      ? RADEON_CRTC_CSYNC_EN
9221.38Sgwr			      : 0)
9231.50Sgwr			   | ((mode->Flags & V_INTERLACE)
9241.38Sgwr			      ? RADEON_CRTC_INTERLACE_EN
9251.38Sgwr			      : 0));
9261.38Sgwr
9271.38Sgwr    save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN|
9281.38Sgwr			    RADEON_CRTC_VSYNC_DIS |
9291.30Sgwr			    RADEON_CRTC_HSYNC_DIS |
9301.38Sgwr			    RADEON_CRTC_DISPLAY_DIS);
9311.38Sgwr
9321.1Sglass    save->disp_merge_cntl = info->SavedReg->disp_merge_cntl;
9331.7Sglass    save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
9341.28Sgwr
9351.38Sgwr    save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
9361.38Sgwr			       | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff)
9371.38Sgwr				  << 16));
9381.28Sgwr
9391.38Sgwr    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
9401.38Sgwr    if (!hsync_wid)       hsync_wid = 1;
9411.38Sgwr    hsync_start = mode->CrtcHSyncStart - 8;
9421.1Sglass
9431.78Sgwr    save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
9441.38Sgwr				  | ((hsync_wid & 0x3f) << 16)
9451.29Sgwr				  | ((mode->Flags & V_NHSYNC)
9461.38Sgwr				     ? RADEON_CRTC_H_SYNC_POL
9471.80Sgwr				     : 0));
9481.80Sgwr
9491.80Sgwr				/* This works for double scan mode. */
9501.38Sgwr    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
9511.38Sgwr			       | ((mode->CrtcVDisplay - 1) << 16));
9521.26Sgwr
9531.38Sgwr    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
9541.29Sgwr    if (!vsync_wid)       vsync_wid = 1;
9551.1Sglass
9561.7Sglass    save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
9571.26Sgwr				  | ((vsync_wid & 0x1f) << 16)
9581.38Sgwr				  | ((mode->Flags & V_NVSYNC)
9591.50Sgwr				     ? RADEON_CRTC_V_SYNC_POL
9601.26Sgwr				     : 0));
9611.38Sgwr
9621.76Sgwr    save->crtc_pitch  = (((pScrn->displayWidth * pScrn->bitsPerPixel) +
9631.38Sgwr			  ((pScrn->bitsPerPixel * 8) -1)) /
9641.38Sgwr			 (pScrn->bitsPerPixel * 8));
9651.78Sgwr    save->crtc_pitch |= save->crtc_pitch << 16;
9661.38Sgwr
9671.38Sgwr    if (info->IsDellServer) {
9681.80Sgwr	save->dac2_cntl = info->SavedReg->dac2_cntl;
9691.80Sgwr	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl;
9701.38Sgwr	save->crtc2_gen_cntl = info->SavedReg->crtc2_gen_cntl;
9711.38Sgwr	save->disp_hw_debug = info->SavedReg->disp_hw_debug;
9721.38Sgwr
9731.38Sgwr	save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
9741.38Sgwr	save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
9751.38Sgwr
9761.38Sgwr	/* For CRT on DAC2, don't turn it on if BIOS didn't
9771.38Sgwr	   enable it, even it's detected.
9781.38Sgwr	*/
9791.38Sgwr	save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
9801.38Sgwr	save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
9811.38Sgwr	save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
9821.38Sgwr    }
9831.38Sgwr
9841.38Sgwr    return TRUE;
9851.38Sgwr}
9861.38Sgwr
9871.38Sgwr
9881.38Sgwrvoid
9891.28SgwrRADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save,
9901.38Sgwr		    int x, int y)
9911.81Sgwr{
9921.38Sgwr    ScrnInfoPtr pScrn = crtc->scrn;
9931.38Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
9941.38Sgwr    int    Base;
9951.28Sgwr#ifdef XF86DRI
9961.28Sgwr    drm_radeon_sarea_t *pSAREAPriv;
9971.38Sgwr    XF86DRISAREAPtr pSAREA;
9981.38Sgwr#endif
9991.38Sgwr
10001.38Sgwr    /* It seems all fancy options apart from pflip can be safely disabled
10011.38Sgwr     */
10021.38Sgwr    save->crtc2_offset      = pScrn->fbOffset;
10031.38Sgwr#ifdef XF86DRI
10041.38Sgwr    if (info->dri && info->dri->allowPageFlip)
10051.38Sgwr	save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL;
10061.38Sgwr    else
10071.38Sgwr#endif
10081.38Sgwr	save->crtc2_offset_cntl = 0;
10091.38Sgwr
10101.38Sgwr    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
10111.39Sgwr       if (IS_R300_VARIANT)
10121.38Sgwr          save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
10131.38Sgwr				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
10141.38Sgwr				      R300_CRTC_MACRO_TILE_EN);
10151.26Sgwr       else
10161.80Sgwr          save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN;
10171.50Sgwr    }
10181.50Sgwr    else {
10191.39Sgwr       if (IS_R300_VARIANT)
10201.73Sfair          save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
10211.39Sgwr				      R300_CRTC_MICRO_TILE_BUFFER_DIS |
10221.39Sgwr				      R300_CRTC_MACRO_TILE_EN);
10231.39Sgwr       else
10241.38Sgwr          save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN;
10251.38Sgwr    }
10261.80Sgwr
10271.38Sgwr    Base = pScrn->fbOffset;
10281.38Sgwr
10291.38Sgwr    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
10301.80Sgwr        if (IS_R300_VARIANT) {
10311.39Sgwr	/* On r300/r400 when tiling is enabled crtc_offset is set to the address of
10321.39Sgwr	 * the surface.  the x/y offsets are handled by the X_Y tile reg for each crtc
10331.38Sgwr	 * Makes tiling MUCH easier.
10341.38Sgwr	 */
10351.39Sgwr             save->crtc2_tile_x0_y0 = x | (y << 16);
10361.38Sgwr             Base &= ~0x7ff;
10371.30Sgwr         } else {
10381.38Sgwr	     /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the
10391.81Sgwr		drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes
10401.38Sgwr		flickering when scrolling vertically in a virtual screen, possibly because crtc will
10411.30Sgwr		pick up the new offset value at the end of each scanline, but the new offset_cntl value
10421.30Sgwr		only after a vsync. We'd probably need to wait (in drm) for vsync and only then update
10431.38Sgwr		OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */
10441.38Sgwr	     /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/
10451.38Sgwr#if 0
10461.38Sgwr	     /* try to get rid of flickering when scrolling at least for 2d */
10471.38Sgwr#ifdef XF86DRI
10481.38Sgwr	     if (!info->have3DWindows)
10491.38Sgwr#endif
10501.38Sgwr		 save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL;
10511.38Sgwr#endif
10521.30Sgwr
10531.81Sgwr             int byteshift = info->CurrentLayout.bitsPerPixel >> 4;
10541.39Sgwr             /* crtc uses 256(bytes)x8 "half-tile" start addresses? */
10551.78Sgwr             int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11;
10561.38Sgwr             Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
10571.38Sgwr             save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16);
10581.38Sgwr         }
10591.30Sgwr    }
10601.38Sgwr    else {
10611.80Sgwr       int offset = y * info->CurrentLayout.displayWidth + x;
10621.38Sgwr       switch (info->CurrentLayout.pixel_code) {
10631.38Sgwr       case 15:
10641.80Sgwr       case 16: offset *= 2; break;
10651.30Sgwr       case 24: offset *= 3; break;
10661.26Sgwr       case 32: offset *= 4; break;
10671.38Sgwr       }
10681.38Sgwr       Base += offset;
10691.38Sgwr    }
10701.30Sgwr
10711.38Sgwr    if (crtc->rotatedData != NULL) {
10721.38Sgwr	Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
10731.26Sgwr    }
10741.78Sgwr
10751.75Sgwr    Base &= ~7;                 /* 3 lower bits are always 0 */
10761.78Sgwr
10771.78Sgwr#ifdef XF86DRI
10781.38Sgwr    if (info->directRenderingInited) {
10791.78Sgwr	/* note cannot use pScrn->pScreen since this is unitialized when called from
10801.78Sgwr	   RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */
10811.29Sgwr        /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for
10821.78Sgwr	 *** pageflipping!
10831.78Sgwr	 ***/
10841.78Sgwr	pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]);
10851.78Sgwr	/* can't get at sarea in a semi-sane way? */
10861.78Sgwr	pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec));
10871.78Sgwr
10881.78Sgwr	pSAREAPriv->crtc2_base = Base;
10891.1Sglass
10901.26Sgwr	if (pSAREAPriv->pfCurrentPage == 1) {
10911.78Sgwr	    Base += info->dri->backOffset - info->dri->frontOffset;
10921.78Sgwr	}
10931.84Sgwr    }
10941.84Sgwr#endif
10951.84Sgwr    save->crtc2_offset = Base;
10961.84Sgwr
10971.84Sgwr}
10981.78Sgwr
10991.78Sgwr
11001.78Sgwr/* Define CRTC2 registers for requested video mode */
11011.38Sgwrstatic Bool
11021.84SgwrRADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
11031.84Sgwr			 DisplayModePtr mode)
11041.84Sgwr{
11051.84Sgwr    ScrnInfoPtr pScrn = crtc->scrn;
11061.84Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
11071.84Sgwr    int    format;
11081.84Sgwr    int    hsync_start;
11091.84Sgwr    int    hsync_wid;
11101.84Sgwr    int    vsync_wid;
11111.84Sgwr
11121.84Sgwr    switch (info->CurrentLayout.pixel_code) {
11131.84Sgwr    case 4:  format = 1; break;
11141.84Sgwr    case 8:  format = 2; break;
11151.84Sgwr    case 15: format = 3; break;      /*  555 */
11161.84Sgwr    case 16: format = 4; break;      /*  565 */
11171.84Sgwr    case 24: format = 5; break;      /*  RGB */
11181.84Sgwr    case 32: format = 6; break;      /* xRGB */
11191.84Sgwr    default:
11201.84Sgwr	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
11211.84Sgwr		   "Unsupported pixel depth (%d)\n",
11221.84Sgwr		   info->CurrentLayout.bitsPerPixel);
11231.84Sgwr	return FALSE;
11241.84Sgwr    }
11251.38Sgwr
11261.84Sgwr    save->crtc2_h_total_disp =
11271.84Sgwr	((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
11281.110Smrg	 | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16));
11291.84Sgwr
11301.84Sgwr    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
11311.84Sgwr    if (!hsync_wid)       hsync_wid = 1;
11321.29Sgwr    hsync_start = mode->CrtcHSyncStart - 8;
11331.84Sgwr
11341.84Sgwr    save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff)
11351.84Sgwr				   | ((hsync_wid & 0x3f) << 16)
11361.84Sgwr				   | ((mode->Flags & V_NHSYNC)
11371.84Sgwr				      ? RADEON_CRTC_H_SYNC_POL
11381.84Sgwr				      : 0));
11391.84Sgwr
11401.84Sgwr				/* This works for double scan mode. */
11411.84Sgwr    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
11421.84Sgwr				| ((mode->CrtcVDisplay - 1) << 16));
11431.84Sgwr
11441.84Sgwr    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
11451.78Sgwr    if (!vsync_wid)       vsync_wid = 1;
11461.78Sgwr
11471.1Sglass    save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
11481.1Sglass				   | ((vsync_wid & 0x1f) << 16)
11491.38Sgwr				   | ((mode->Flags & V_NVSYNC)
11501.38Sgwr				      ? RADEON_CRTC2_V_SYNC_POL
11511.38Sgwr				      : 0));
11521.38Sgwr
11531.38Sgwr    save->crtc2_pitch  = ((pScrn->displayWidth * pScrn->bitsPerPixel) +
11541.84Sgwr			  ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8);
11551.84Sgwr    save->crtc2_pitch |= save->crtc2_pitch << 16;
11561.38Sgwr
11571.38Sgwr    /* check to see if TV DAC is enabled for another crtc and keep it enabled */
11581.38Sgwr    if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON)
11591.84Sgwr	save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
11601.84Sgwr    else
11611.38Sgwr	save->crtc2_gen_cntl = 0;
11621.38Sgwr
11631.80Sgwr    save->crtc2_gen_cntl |= (RADEON_CRTC2_EN
11641.38Sgwr			     | (format << 8)
11651.38Sgwr			     | RADEON_CRTC2_VSYNC_DIS
11661.80Sgwr			     | RADEON_CRTC2_HSYNC_DIS
11671.80Sgwr			     | RADEON_CRTC2_DISP_DIS
11681.80Sgwr			     | ((mode->Flags & V_DBLSCAN)
11691.38Sgwr				? RADEON_CRTC2_DBL_SCAN_EN
11701.38Sgwr				: 0)
11711.38Sgwr			     | ((mode->Flags & V_CSYNC)
11721.80Sgwr				? RADEON_CRTC2_CSYNC_EN
11731.80Sgwr				: 0)
11741.80Sgwr			     | ((mode->Flags & V_INTERLACE)
11751.84Sgwr				? RADEON_CRTC2_INTERLACE_EN
11761.84Sgwr				: 0));
11771.84Sgwr
11781.80Sgwr    save->disp2_merge_cntl = info->SavedReg->disp2_merge_cntl;
11791.84Sgwr    save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN);
11801.38Sgwr
11811.80Sgwr    save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid;
11821.50Sgwr    save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid;
11831.50Sgwr
11841.50Sgwr    return TRUE;
11851.73Sfair}
11861.50Sgwr
11871.38Sgwr
11881.80Sgwr/* Define PLL registers for requested video mode */
11891.38Sgwrstatic void
11901.84SgwrRADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
11911.38Sgwr		       RADEONPLLPtr pll, DisplayModePtr mode,
11921.38Sgwr		       int flags)
11931.65Sgwr{
11941.38Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
11951.38Sgwr    uint32_t feedback_div = 0;
11961.38Sgwr    uint32_t reference_div = 0;
11971.84Sgwr    uint32_t post_divider = 0;
11981.84Sgwr    uint32_t freq = 0;
11991.38Sgwr
12001.38Sgwr    struct {
12011.107Sgwr	int divider;
12021.107Sgwr	int bitvalue;
12031.107Sgwr    } *post_div, post_divs[]   = {
12041.107Sgwr				/* From RAGE 128 VR/RAGE 128 GL Register
12051.107Sgwr				 * Reference Manual (Technical Reference
12061.107Sgwr				 * Manual P/N RRG-G04100-C Rev. 0.04), page
12071.107Sgwr				 * 3-17 (PLL_DIV_[3:0]).
12081.107Sgwr				 */
12091.107Sgwr	{  1, 0 },              /* VCLK_SRC                 */
12101.107Sgwr	{  2, 1 },              /* VCLK_SRC/2               */
12111.107Sgwr	{  4, 2 },              /* VCLK_SRC/4               */
12121.107Sgwr	{  8, 3 },              /* VCLK_SRC/8               */
12131.38Sgwr	{  3, 4 },              /* VCLK_SRC/3               */
12141.38Sgwr	{ 16, 5 },              /* VCLK_SRC/16              */
12151.107Sgwr	{  6, 6 },              /* VCLK_SRC/6               */
12161.50Sgwr	{ 12, 7 },              /* VCLK_SRC/12              */
12171.38Sgwr	{  0, 0 }
12181.38Sgwr    };
12191.38Sgwr
12201.38Sgwr
12211.38Sgwr    if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
12221.38Sgwr       save->ppll_ref_div = info->RefDivider;
12231.38Sgwr       save->ppll_div_3   = info->FeedbackDivider | (info->PostDivider << 16);
12241.38Sgwr       save->htotal_cntl  = 0;
12251.38Sgwr       return;
12261.38Sgwr    }
12271.38Sgwr
12281.38Sgwr    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
12291.52Sgwr
12301.38Sgwr    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
12311.52Sgwr	if (post_div->divider == post_divider)
12321.52Sgwr	    break;
12331.52Sgwr    }
12341.52Sgwr
12351.38Sgwr    if (!post_div->divider) {
12361.38Sgwr	save->pll_output_freq = freq;
12371.38Sgwr	post_div = &post_divs[0];
12381.38Sgwr    }
12391.38Sgwr
12401.38Sgwr    save->dot_clock_freq = freq;
12411.38Sgwr    save->feedback_div   = feedback_div;
12421.38Sgwr    save->reference_div  = reference_div;
12431.38Sgwr    save->post_div       = post_divider;
12441.38Sgwr
12451.1Sglass    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
12461.38Sgwr		   "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
12471.92Sgwr		   (unsigned)save->dot_clock_freq,
12481.38Sgwr		   (unsigned)save->pll_output_freq,
12491.73Sfair		   save->feedback_div,
12501.38Sgwr		   save->reference_div,
12511.38Sgwr		   save->post_div);
12521.38Sgwr
12531.80Sgwr    save->ppll_ref_div   = save->reference_div;
12541.38Sgwr
12551.38Sgwr#if defined(__powerpc__)
12561.38Sgwr    /* apparently programming this otherwise causes a hang??? */
12571.38Sgwr    if (info->MacModel == RADEON_MAC_IBOOK)
12581.38Sgwr	save->ppll_div_3 = 0x000600ad;
12591.38Sgwr    else
12601.38Sgwr#endif
12611.38Sgwr    save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
12621.52Sgwr
12631.38Sgwr    save->htotal_cntl    = mode->HTotal & 0x7;
12641.38Sgwr
12651.38Sgwr    save->vclk_ecp_cntl = (info->SavedReg->vclk_ecp_cntl &
12661.38Sgwr	    ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
12671.38Sgwr}
12681.80Sgwr
12691.1Sglass/* Define PLL2 registers for requested video mode */
12701.84Sgwrstatic void
12711.38SgwrRADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
12721.1Sglass			RADEONPLLPtr pll, DisplayModePtr mode,
12731.38Sgwr			int flags)
12741.84Sgwr{
12751.84Sgwr    RADEONInfoPtr  info       = RADEONPTR(pScrn);
12761.38Sgwr    uint32_t feedback_div = 0;
12771.84Sgwr    uint32_t reference_div = 0;
12781.84Sgwr    uint32_t post_divider = 0;
12791.84Sgwr    uint32_t freq = 0;
12801.38Sgwr
12811.38Sgwr    struct {
12821.38Sgwr	int divider;
12831.80Sgwr	int bitvalue;
12841.38Sgwr    } *post_div, post_divs[]   = {
12851.38Sgwr				/* From RAGE 128 VR/RAGE 128 GL Register
12861.80Sgwr				 * Reference Manual (Technical Reference
12871.80Sgwr				 * Manual P/N RRG-G04100-C Rev. 0.04), page
12881.80Sgwr				 * 3-17 (PLL_DIV_[3:0]).
12891.38Sgwr				 */
12901.38Sgwr	{  1, 0 },              /* VCLK_SRC                 */
12911.84Sgwr	{  2, 1 },              /* VCLK_SRC/2               */
12921.80Sgwr	{  4, 2 },              /* VCLK_SRC/4               */
12931.80Sgwr	{  8, 3 },              /* VCLK_SRC/8               */
12941.84Sgwr	{  3, 4 },              /* VCLK_SRC/3               */
12951.84Sgwr	{  6, 6 },              /* VCLK_SRC/6               */
12961.38Sgwr	{ 12, 7 },              /* VCLK_SRC/12              */
12971.80Sgwr	{  0, 0 }
12981.38Sgwr    };
12991.84Sgwr
13001.38Sgwr    if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
13011.38Sgwr       save->p2pll_ref_div = info->RefDivider;
13021.65Sgwr       save->p2pll_div_0   = info->FeedbackDivider | (info->PostDivider << 16);
13031.65Sgwr       save->htotal_cntl2  = 0;
13041.38Sgwr       return;
13051.38Sgwr    }
13061.38Sgwr
13071.38Sgwr    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
13081.38Sgwr
13091.38Sgwr    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
13101.38Sgwr	if (post_div->divider == post_divider)
13111.84Sgwr	    break;
13121.84Sgwr    }
13131.38Sgwr
13141.38Sgwr    if (!post_div->divider) {
13151.38Sgwr	save->pll_output_freq_2 = freq;
13161.38Sgwr	post_div = &post_divs[0];
13171.50Sgwr    }
13181.38Sgwr
13191.38Sgwr    save->dot_clock_freq_2 = freq;
13201.38Sgwr    save->feedback_div_2   = feedback_div;
13211.38Sgwr    save->reference_div_2  = reference_div;
13221.38Sgwr    save->post_div_2       = post_divider;
13231.38Sgwr
13241.38Sgwr    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
13251.38Sgwr		   "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
13261.38Sgwr		   (unsigned)save->dot_clock_freq_2,
13271.38Sgwr		   (unsigned)save->pll_output_freq_2,
13281.38Sgwr		   save->feedback_div_2,
13291.38Sgwr		   save->reference_div_2,
13301.52Sgwr		   save->post_div_2);
13311.38Sgwr
13321.52Sgwr    save->p2pll_ref_div    = save->reference_div_2;
13331.52Sgwr
13341.52Sgwr    save->p2pll_div_0      = (save->feedback_div_2 |
13351.52Sgwr			      (post_div->bitvalue << 16));
13361.38Sgwr
13371.38Sgwr    save->htotal_cntl2     = mode->HTotal & 0x7;
13381.38Sgwr
13391.38Sgwr    save->pixclks_cntl     = ((info->SavedReg->pixclks_cntl &
13401.38Sgwr			       ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
13411.38Sgwr			      RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
13421.38Sgwr}
13431.38Sgwr
13441.38Sgwrstatic void
13451.38Sgwrradeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore)
13461.38Sgwr{
13471.38Sgwr    /* pixclks_cntl controls tv clock routing */
13481.29Sgwr    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl);
13491.38Sgwr}
13501.92Sgwr
13511.38Sgwr/* Calculate display buffer watermark to prevent buffer underflow */
13521.73Sfairvoid
13531.38SgwrRADEONInitDispBandwidthLegacy(ScrnInfoPtr pScrn,
13541.38Sgwr			      DisplayModePtr mode1, int pixel_bytes1,
13551.38Sgwr			      DisplayModePtr mode2, int pixel_bytes2)
13561.80Sgwr{
13571.38Sgwr    RADEONInfoPtr info = RADEONPTR(pScrn);
13581.38Sgwr    RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
13591.38Sgwr    unsigned char *RADEONMMIO = info->MMIO;
13601.38Sgwr
13611.52Sgwr    uint32_t temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0;
13621.38Sgwr    float mem_tcas;
13631.38Sgwr    int k1, c;
13641.38Sgwr    uint32_t MemTrcdExtMemCntl[4]     = {1, 2, 3, 4};
13651.38Sgwr    uint32_t MemTrpExtMemCntl[4]      = {1, 2, 3, 4};
13661.38Sgwr    uint32_t MemTrasExtMemCntl[8]     = {1, 2, 3, 4, 5, 6, 7, 8};
13671.38Sgwr
13681.19Sglass    uint32_t MemTrcdMemTimingCntl[8]     = {1, 2, 3, 4, 5, 6, 7, 8};
13691.84Sgwr    uint32_t MemTrpMemTimingCntl[8]      = {1, 2, 3, 4, 5, 6, 7, 8};
13701.1Sglass    uint32_t MemTrasMemTimingCntl[16]    = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
13711.1Sglass
13721.78Sgwr    float MemTcas[8]  = {0, 1, 2, 3, 0, 1.5, 2.5, 0};
13731.38Sgwr    float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7};
13741.38Sgwr    float MemTrbs[8]  = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5};
13751.38Sgwr
13761.38Sgwr    float mem_bw, peak_disp_bw;
13771.84Sgwr    float min_mem_eff = 0.8;
13781.38Sgwr    float sclk_eff, sclk_delay;
13791.38Sgwr    float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk;
13801.1Sglass    float disp_latency, disp_latency_overhead, disp_drain_rate = 0, disp_drain_rate2;
13811.78Sgwr    float pix_clk, pix_clk2; /* in MHz */
13821.78Sgwr    int cur_size = 16;       /* in octawords */
13831.19Sglass    int critical_point = 0, critical_point2;
13841.38Sgwr    int stop_req, max_stop_req;
13851.73Sfair    float read_return_rate, time_disp1_drop_priority;
13861.38Sgwr
13871.78Sgwr    /*
13881.38Sgwr     * Set display0/1 priority up on r3/4xx in the memory controller for
13891.38Sgwr     * high res modes if the user specifies HIGH for displaypriority
13901.26Sgwr     * option.
13911.84Sgwr     */
13921.84Sgwr    if ((info->DispPriority == 2) && IS_R300_VARIANT) {
13931.38Sgwr	uint32_t mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
13941.38Sgwr	mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
13951.76Sgwr	mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
13961.38Sgwr	if (pRADEONEnt->pCrtc[1]->enabled)
13971.38Sgwr	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); /* display 1 */
13981.84Sgwr	if (pRADEONEnt->pCrtc[0]->enabled)
13991.81Sgwr	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); /* display 0 */
14001.38Sgwr	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
14011.38Sgwr    }
14021.38Sgwr
14031.38Sgwr    /* R420 and RV410 family not supported yet */
14041.1Sglass    if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return;
14051.1Sglass
14061.38Sgwr    /*
14071.42Sgwr     * Determine if there is enough bandwidth for current display mode
14081.38Sgwr     */
14091.38Sgwr    mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
14101.42Sgwr
14111.38Sgwr    pix_clk = 0;
14121.38Sgwr    pix_clk2 = 0;
14131.38Sgwr    peak_disp_bw = 0;
14141.92Sgwr    if (mode1) {
14151.38Sgwr	pix_clk = mode1->Clock/1000.0;
14161.92Sgwr	peak_disp_bw += (pix_clk * pixel_bytes1);
14171.92Sgwr    }
14181.38Sgwr    if (mode2) {
14191.92Sgwr	pix_clk2 = mode2->Clock/1000.0;
14201.84Sgwr	peak_disp_bw += (pix_clk2 * pixel_bytes2);
14211.84Sgwr    }
14221.92Sgwr
14231.38Sgwr    if (peak_disp_bw >= mem_bw * min_mem_eff) {
14241.38Sgwr	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
14251.38Sgwr		   "You may not have enough display bandwidth for current mode\n"
14261.1Sglass		   "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
14271.80Sgwr    }
14281.80Sgwr
14291.92Sgwr    /*  Get values from the EXT_MEM_CNTL register...converting its contents. */
14301.92Sgwr    temp = INREG(RADEON_MEM_TIMING_CNTL);
14311.92Sgwr    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
14321.92Sgwr	mem_trcd      = MemTrcdExtMemCntl[(temp & 0x0c) >> 2];
14331.19Sglass	mem_trp       = MemTrpExtMemCntl[ (temp & 0x03) >> 0];
14341.38Sgwr	mem_tras      = MemTrasExtMemCntl[(temp & 0x70) >> 4];
14351.92Sgwr    } else { /* RV200 and later */
14361.38Sgwr	mem_trcd      = MemTrcdMemTimingCntl[(temp & 0x07) >> 0];
14371.38Sgwr	mem_trp       = MemTrpMemTimingCntl[ (temp & 0x700) >> 8];
14381.38Sgwr	mem_tras      = MemTrasMemTimingCntl[(temp & 0xf000) >> 12];
14391.1Sglass    }
14401.84Sgwr
14411.84Sgwr    /* Get values from the MEM_SDRAM_MODE_REG register...converting its */
14421.2Sglass    temp = INREG(RADEON_MEM_SDRAM_MODE_REG);
14431.84Sgwr    data = (temp & (7<<20)) >> 20;
14441.84Sgwr    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
14451.84Sgwr	mem_tcas = MemTcas [data];
14461.81Sgwr    } else {
14471.73Sfair	mem_tcas = MemTcas2 [data];
14481.38Sgwr    }
14491.19Sglass
14501.26Sgwr    if (IS_R300_VARIANT) {
14511.38Sgwr	/* on the R300, Tcas is included in Trbs.
14521.84Sgwr	 */
14531.38Sgwr	temp = INREG(RADEON_MEM_CNTL);
14541.84Sgwr	data = (R300_MEM_NUM_CHANNELS_MASK & temp);
14551.84Sgwr	if (data == 1) {
14561.84Sgwr	    if (R300_MEM_USE_CD_CH_ONLY & temp) {
14571.81Sgwr		temp  = INREG(R300_MC_IND_INDEX);
14581.84Sgwr		temp &= ~R300_MC_IND_ADDR_MASK;
14591.84Sgwr		temp |= R300_MC_READ_CNTL_CD_mcind;
14601.60Sgwr		OUTREG(R300_MC_IND_INDEX, temp);
14611.38Sgwr		temp  = INREG(R300_MC_IND_DATA);
14621.38Sgwr		data = (R300_MEM_RBS_POSITION_C_MASK & temp);
14631.38Sgwr	    } else {
14641.38Sgwr		temp = INREG(R300_MC_READ_CNTL_AB);
14651.84Sgwr		data = (R300_MEM_RBS_POSITION_A_MASK & temp);
14661.84Sgwr	    }
14671.84Sgwr	} else {
14681.84Sgwr	    temp = INREG(R300_MC_READ_CNTL_AB);
14691.84Sgwr	    data = (R300_MEM_RBS_POSITION_A_MASK & temp);
14701.84Sgwr	}
14711.84Sgwr
14721.84Sgwr	mem_trbs = MemTrbs[data];
14731.84Sgwr	mem_tcas += mem_trbs;
14741.81Sgwr    }
14751.81Sgwr
14761.84Sgwr    if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
14771.84Sgwr	/* DDR64 SCLK_EFF = SCLK for analysis */
14781.38Sgwr	sclk_eff = info->sclk;
14791.84Sgwr    } else {
14801.38Sgwr#ifdef XF86DRI
14811.38Sgwr	if (info->directRenderingEnabled)
14821.38Sgwr	    sclk_eff = info->sclk - (info->dri->agpMode * 50.0 / 3.0);
14831.38Sgwr	else
14841.38Sgwr#endif
14851.38Sgwr	    sclk_eff = info->sclk;
14861.38Sgwr    }
14871.38Sgwr
14881.38Sgwr    /*
14891.38Sgwr      Find the memory controller latency for the display client.
14901.38Sgwr    */
14911.38Sgwr    if (IS_R300_VARIANT) {
14921.38Sgwr	/*not enough for R350 ???*/
14931.92Sgwr	/*
14941.38Sgwr	if (!mode2) sclk_delay = 150;
14951.92Sgwr	else {
14961.92Sgwr	    if (info->RamWidth == 256) sclk_delay = 87;
14971.38Sgwr	    else sclk_delay = 97;
14981.92Sgwr	}
14991.84Sgwr	*/
15001.84Sgwr	sclk_delay = 250;
15011.38Sgwr    } else {
15021.38Sgwr	if ((info->ChipFamily == CHIP_FAMILY_RV100) ||
15031.38Sgwr	    info->IsIGP) {
15041.38Sgwr	    if (info->IsDDR) sclk_delay = 41;
15051.80Sgwr	    else sclk_delay = 33;
15061.80Sgwr	} else {
15071.92Sgwr	    if (info->RamWidth == 128) sclk_delay = 57;
15081.18Sglass	    else sclk_delay = 41;
15091.80Sgwr	}
15101.92Sgwr    }
15111.80Sgwr
15121.26Sgwr    mc_latency_sclk = sclk_delay / sclk_eff;
15131.18Sglass
15141.81Sgwr    if (info->IsDDR) {
15151.84Sgwr	if (info->RamWidth == 32) {
15161.84Sgwr	    k1 = 40;
15171.38Sgwr	    c  = 3;
15181.84Sgwr	} else {
15191.84Sgwr	    k1 = 20;
15201.84Sgwr	    c  = 1;
15211.84Sgwr	}
15221.84Sgwr    } else {
15231.84Sgwr	k1 = 40;
15241.84Sgwr	c  = 3;
15251.84Sgwr    }
15261.84Sgwr    mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) /
15271.84Sgwr		       info->mclk) + (4.0 / sclk_eff);
15281.84Sgwr
15291.84Sgwr    /*
15301.84Sgwr      HW cursor time assuming worst case of full size colour cursor.
15311.84Sgwr    */
15321.38Sgwr    cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk;
15331.84Sgwr    cur_latency_sclk = cur_size / sclk_eff;
15341.84Sgwr
15351.84Sgwr    /*
15361.84Sgwr      Find the total latency for the display data.
15371.84Sgwr    */
15381.84Sgwr    disp_latency_overhead = 8.0 / info->sclk;
15391.84Sgwr    mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk;
15401.84Sgwr    mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk;
15411.84Sgwr    disp_latency = MAX(mc_latency_mclk, mc_latency_sclk);
15421.84Sgwr
15431.84Sgwr    /* setup Max GRPH_STOP_REQ default value */
15441.84Sgwr    if (IS_RV100_VARIANT)
15451.84Sgwr	max_stop_req = 0x5c;
15461.84Sgwr    else
15471.84Sgwr	max_stop_req  = 0x7c;
15481.84Sgwr
15491.84Sgwr    if (mode1) {
15501.84Sgwr	/*  CRTC1
15511.1Sglass	    Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
15521.1Sglass	    GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
15531.84Sgwr	*/
15541.1Sglass	stop_req = mode1->HDisplay * pixel_bytes1 / 16;
15551.84Sgwr
15561.84Sgwr	if (stop_req > max_stop_req)
15571.84Sgwr	    stop_req = max_stop_req;
15581.98Sgwr
15591.84Sgwr	/*
15601.84Sgwr	  Find the drain rate of the display buffer.
15611.84Sgwr	*/
15621.84Sgwr	disp_drain_rate = pix_clk / (16.0/pixel_bytes1);
15631.1Sglass
15641.84Sgwr	/*
15651.84Sgwr	  Find the critical point of the display buffer.
15661.84Sgwr	*/
15671.84Sgwr	critical_point= (uint32_t)(disp_drain_rate * disp_latency + 0.5);
15681.1Sglass
15691.1Sglass	/* ???? */
15701.38Sgwr	/*
15711.78Sgwr	  temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT;
15721.78Sgwr	  if (critical_point < temp) critical_point = temp;
15731.78Sgwr	*/
15741.38Sgwr	if (info->DispPriority == 2) {
15751.38Sgwr	    critical_point = 0;
15761.38Sgwr	}
15771.38Sgwr
15781.38Sgwr	/*
15791.38Sgwr	  The critical point should never be above max_stop_req-4.  Setting
15801.38Sgwr	  GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
15811.38Sgwr	*/
15821.83Sgwr	if (max_stop_req - critical_point < 4) critical_point = 0;
15831.38Sgwr
15841.38Sgwr	if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) {
15851.38Sgwr	    /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
15861.38Sgwr	    critical_point = 0x10;
15871.38Sgwr	}
15881.99Sgwr
15891.38Sgwr	temp = info->SavedReg->grph_buffer_cntl;
15901.75Sgwr	temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
15911.38Sgwr	temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
15921.38Sgwr	temp &= ~(RADEON_GRPH_START_REQ_MASK);
15931.75Sgwr	if ((info->ChipFamily == CHIP_FAMILY_R350) &&
15941.75Sgwr	    (stop_req > 0x15)) {
15951.38Sgwr	    stop_req -= 0x10;
15961.99Sgwr	}
15971.75Sgwr	temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
15981.75Sgwr
15991.78Sgwr	temp |= RADEON_GRPH_BUFFER_SIZE;
16001.75Sgwr	temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
16011.76Sgwr		  RADEON_GRPH_CRITICAL_AT_SOF |
16021.75Sgwr		  RADEON_GRPH_STOP_CNTL);
16031.75Sgwr	/*
16041.76Sgwr	  Write the result into the register.
16051.76Sgwr	*/
16061.75Sgwr	OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
16071.75Sgwr					 (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
16081.76Sgwr
16091.75Sgwr#if 0
16101.76Sgwr	if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
16111.75Sgwr	    (info->ChipFamily == CHIP_FAMILY_RS480)) {
16121.75Sgwr	    /* attempt to program RS400 disp regs correctly ??? */
16131.75Sgwr	    temp = info->SavedReg->disp1_req_cntl1;
16141.75Sgwr	    temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
16151.75Sgwr		      RS400_DISP1_STOP_REQ_LEVEL_MASK);
16161.75Sgwr	    OUTREG(RS400_DISP1_REQ_CNTL1, (temp |
16171.76Sgwr					   (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
16181.75Sgwr					   (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
16191.75Sgwr	    temp = info->SavedReg->dmif_mem_cntl1;
16201.75Sgwr	    temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
16211.75Sgwr		      RS400_DISP1_CRITICAL_POINT_STOP_MASK);
16221.75Sgwr	    OUTREG(RS400_DMIF_MEM_CNTL1, (temp |
16231.75Sgwr					  (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
16241.75Sgwr					  (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
16251.75Sgwr	}
16261.75Sgwr#endif
16271.75Sgwr
16281.75Sgwr	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
16291.75Sgwr		       "GRPH_BUFFER_CNTL from %x to %x\n",
16301.76Sgwr		       (unsigned int)info->SavedReg->grph_buffer_cntl,
16311.76Sgwr		       (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL));
16321.75Sgwr    }
16331.76Sgwr
16341.75Sgwr    if (mode2) {
16351.75Sgwr	stop_req = mode2->HDisplay * pixel_bytes2 / 16;
16361.76Sgwr
16371.76Sgwr	if (stop_req > max_stop_req) stop_req = max_stop_req;
16381.75Sgwr
16391.76Sgwr	/*
16401.76Sgwr	  Find the drain rate of the display buffer.
16411.76Sgwr	*/
16421.91Sgwr	disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2);
16431.76Sgwr
16441.76Sgwr	temp = info->SavedReg->grph2_buffer_cntl;
16451.76Sgwr	temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
16461.76Sgwr	temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
16471.75Sgwr	temp &= ~(RADEON_GRPH_START_REQ_MASK);
16481.75Sgwr	if ((info->ChipFamily == CHIP_FAMILY_R350) &&
16491.75Sgwr	    (stop_req > 0x15)) {
16501.75Sgwr	    stop_req -= 0x10;
16511.75Sgwr	}
16521.76Sgwr	temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
16531.75Sgwr	temp |= RADEON_GRPH_BUFFER_SIZE;
16541.75Sgwr	temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
16551.75Sgwr		  RADEON_GRPH_CRITICAL_AT_SOF |
16561.75Sgwr		  RADEON_GRPH_STOP_CNTL);
16571.75Sgwr
16581.76Sgwr	if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
16591.76Sgwr	    (info->ChipFamily == CHIP_FAMILY_RS200))
16601.76Sgwr	    critical_point2 = 0;
16611.76Sgwr	else {
16621.75Sgwr	    read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128));
16631.76Sgwr	    if (mode1)
16641.76Sgwr		time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate);
16651.76Sgwr	    else
16661.76Sgwr		time_disp1_drop_priority = 0;
16671.76Sgwr
16681.76Sgwr	    critical_point2 = (uint32_t)((disp_latency + time_disp1_drop_priority +
16691.76Sgwr					disp_latency) * disp_drain_rate2 + 0.5);
16701.76Sgwr
16711.75Sgwr	    if (info->DispPriority == 2) {
16721.75Sgwr		critical_point2 = 0;
16731.75Sgwr	    }
16741.75Sgwr
16751.76Sgwr	    if (max_stop_req - critical_point2 < 4) critical_point2 = 0;
16761.75Sgwr
16771.76Sgwr	}
16781.75Sgwr
16791.75Sgwr	if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) {
16801.75Sgwr	    /* some R300 cards have problem with this set to 0 */
16811.75Sgwr	    critical_point2 = 0x10;
16821.75Sgwr	}
16831.76Sgwr
16841.75Sgwr	OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
16851.75Sgwr					  (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
16861.75Sgwr
16871.76Sgwr	if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
16881.75Sgwr	    (info->ChipFamily == CHIP_FAMILY_RS480)) {
16891.76Sgwr#if 0
16901.75Sgwr	    /* attempt to program RS400 disp2 regs correctly ??? */
16911.76Sgwr	    temp = info->SavedReg->disp2_req_cntl1;
16921.75Sgwr	    temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK |
16931.75Sgwr		      RS400_DISP2_STOP_REQ_LEVEL_MASK);
16941.75Sgwr	    OUTREG(RS400_DISP2_REQ_CNTL1, (temp |
16951.76Sgwr					   (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
16961.76Sgwr					   (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
16971.76Sgwr	    temp = info->SavedReg->disp2_req_cntl2;
16981.75Sgwr	    temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK |
16991.99Sgwr		      RS400_DISP2_CRITICAL_POINT_STOP_MASK);
17001.75Sgwr	    OUTREG(RS400_DISP2_REQ_CNTL2, (temp |
17011.75Sgwr					   (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) |
17021.76Sgwr					   (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT)));
17031.76Sgwr#endif
17041.76Sgwr	    OUTREG(RS400_DISP2_REQ_CNTL1, 0x105DC1CC);
17051.75Sgwr	    OUTREG(RS400_DISP2_REQ_CNTL2, 0x2749D000);
17061.99Sgwr	    OUTREG(RS400_DMIF_MEM_CNTL1,  0x29CA71DC);
17071.75Sgwr	    OUTREG(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC);
17081.75Sgwr	}
17091.75Sgwr
17101.76Sgwr	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
17111.76Sgwr		       "GRPH2_BUFFER_CNTL from %x to %x\n",
17121.76Sgwr		       (unsigned int)info->SavedReg->grph2_buffer_cntl,
17131.75Sgwr		       (unsigned int)INREG(RADEON_GRPH2_BUFFER_CNTL));
17141.99Sgwr    }
17151.99Sgwr}
17161.76Sgwr
17171.76Sgwrvoid
17181.76Sgwrlegacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
17191.75Sgwr		     DisplayModePtr adjusted_mode, int x, int y)
17201.75Sgwr{
17211.75Sgwr    ScrnInfoPtr pScrn = crtc->scrn;
17221.76Sgwr    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
17231.76Sgwr    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
17241.76Sgwr    RADEONInfoPtr info = RADEONPTR(pScrn);
17251.76Sgwr    int i = 0;
17261.76Sgwr    double dot_clock = 0;
17271.76Sgwr    int pll_flags = RADEON_PLL_LEGACY;
17281.75Sgwr    Bool update_tv_routing = FALSE;
17291.75Sgwr    Bool tilingChanged = FALSE;
17301.75Sgwr
17311.76Sgwr    if (adjusted_mode->Clock > 200000) /* range limits??? */
17321.76Sgwr	pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
17331.76Sgwr    else
17341.75Sgwr	pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
17351.75Sgwr
17361.75Sgwr    if (info->allowColorTiling) {
17371.76Sgwr	radeon_crtc->can_tile = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
17381.75Sgwr	tilingChanged = RADEONSetTiling(pScrn);
17391.76Sgwr    }
17401.75Sgwr
17411.75Sgwr    for (i = 0; i < xf86_config->num_output; i++) {
17421.76Sgwr	xf86OutputPtr output = xf86_config->output[i];
17431.76Sgwr	RADEONOutputPrivatePtr radeon_output = output->driver_private;
17441.76Sgwr
17451.76Sgwr	if (output->crtc == crtc) {
17461.76Sgwr	    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT |
17471.76Sgwr						ATOM_DEVICE_DFP_SUPPORT))
17481.75Sgwr		pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
17491.75Sgwr	    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT))
17501.76Sgwr		pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV);
17511.76Sgwr	}
17521.75Sgwr    }
17531.75Sgwr
17541.75Sgwr
17551.75Sgwr    ErrorF("init memmap\n");
17561.75Sgwr    RADEONInitMemMapRegisters(pScrn, info->ModeReg, info);
17571.75Sgwr    ErrorF("init common\n");
17581.75Sgwr    RADEONInitCommonRegisters(info->ModeReg, info);
17591.75Sgwr
17601.75Sgwr    RADEONInitSurfaceCntl(crtc, info->ModeReg);
17611.75Sgwr
17621.75Sgwr    switch (radeon_crtc->crtc_id) {
17631.75Sgwr    case 0:
17641.75Sgwr	ErrorF("init crtc1\n");
17651.75Sgwr	RADEONInitCrtcRegisters(crtc, info->ModeReg, adjusted_mode);
17661.75Sgwr	RADEONInitCrtcBase(crtc, info->ModeReg, x, y);
17671.75Sgwr	dot_clock = adjusted_mode->Clock / 1000.0;
17681.76Sgwr	if (dot_clock) {
17691.76Sgwr	    ErrorF("init pll1\n");
17701.75Sgwr	    RADEONInitPLLRegisters(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
17711.75Sgwr	} else {
17721.75Sgwr	    info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div;
17731.75Sgwr	    info->ModeReg->ppll_div_3   = info->SavedReg->ppll_div_3;
17741.75Sgwr	    info->ModeReg->htotal_cntl  = info->SavedReg->htotal_cntl;
17751.75Sgwr	}
17761.75Sgwr	break;
17771.75Sgwr    case 1:
17781.75Sgwr	ErrorF("init crtc2\n");
17791.75Sgwr	RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode);
17801.75Sgwr	RADEONInitCrtc2Base(crtc, info->ModeReg, x, y);
17811.75Sgwr	dot_clock = adjusted_mode->Clock / 1000.0;
17821.75Sgwr	if (dot_clock) {
17831.75Sgwr	    ErrorF("init pll2\n");
17841.76Sgwr	    RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
17851.76Sgwr	}
17861.76Sgwr	break;
17871.75Sgwr    }
17881.75Sgwr
17891.75Sgwr    for (i = 0; i < xf86_config->num_output; i++) {
17901.75Sgwr	xf86OutputPtr output = xf86_config->output[i];
17911.75Sgwr	RADEONOutputPrivatePtr radeon_output = output->driver_private;
17921.75Sgwr
17931.75Sgwr	if (output->crtc == crtc) {
17941.75Sgwr	    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
17951.75Sgwr		switch (radeon_crtc->crtc_id) {
17961.75Sgwr		case 0:
17971.75Sgwr		    RADEONAdjustCrtcRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
17981.75Sgwr		    RADEONAdjustPLLRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
17991.76Sgwr		    update_tv_routing = TRUE;
18001.75Sgwr		    break;
18011.76Sgwr		case 1:
18021.76Sgwr		    RADEONAdjustCrtc2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
18031.76Sgwr		    RADEONAdjustPLL2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output);
18041.75Sgwr		    break;
18051.75Sgwr		}
18061.75Sgwr	    }
18071.75Sgwr	}
18081.75Sgwr    }
18091.38Sgwr
18101.38Sgwr    ErrorF("restore memmap\n");
18111.38Sgwr    RADEONRestoreMemMapRegisters(pScrn, info->ModeReg);
18121.38Sgwr    ErrorF("restore common\n");
18131.83Sgwr    RADEONRestoreCommonRegisters(pScrn, info->ModeReg);
18141.83Sgwr
18151.83Sgwr    switch (radeon_crtc->crtc_id) {
18161.38Sgwr    case 0:
18171.38Sgwr	ErrorF("restore crtc1\n");
18181.38Sgwr	RADEONRestoreCrtcRegisters(pScrn, info->ModeReg);
18191.94Sgwr	ErrorF("restore pll1\n");
18201.67Sgwr	RADEONRestorePLLRegisters(pScrn, info->ModeReg);
18211.67Sgwr	break;
18221.67Sgwr    case 1:
18231.67Sgwr	ErrorF("restore crtc2\n");
18241.38Sgwr	RADEONRestoreCrtc2Registers(pScrn, info->ModeReg);
18251.38Sgwr	ErrorF("restore pll2\n");
18261.38Sgwr	RADEONRestorePLL2Registers(pScrn, info->ModeReg);
18271.38Sgwr	break;
18281.38Sgwr    }
18291.121Stsutsui
18301.110Smrg    /* pixclks_cntl handles tv-out clock routing */
18311.38Sgwr    if (update_tv_routing)
18321.38Sgwr	radeon_update_tv_routing(pScrn, info->ModeReg);
18331.38Sgwr
18341.50Sgwr    if (info->DispPriority)
18351.82Sgwr	RADEONInitDispBandwidth(pScrn);
18361.38Sgwr
18371.38Sgwr    radeon_crtc->initialized = TRUE;
18381.38Sgwr
18391.38Sgwr    if (tilingChanged) {
18401.101Sgwr	/* need to redraw front buffer, I guess this can be considered a hack ? */
18411.101Sgwr	/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
18421.38Sgwr	if (pScrn->pScreen)
18431.38Sgwr	    xf86EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
18441.82Sgwr	RADEONChangeSurfaces(pScrn);
18451.82Sgwr	if (pScrn->pScreen)
18461.82Sgwr	    xf86EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
18471.82Sgwr	/* xf86SetRootClip would do, but can't access that here */
18481.82Sgwr    }
18491.82Sgwr
18501.82Sgwr    /* reset ecp_div for Xv */
18511.82Sgwr    info->ecp_div = -1;
18521.82Sgwr
18531.82Sgwr}
18541.82Sgwr
18551.82Sgwr