1209ff23fSmrg/* 2209ff23fSmrg * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 3209ff23fSmrg * VA Linux Systems Inc., Fremont, California. 4209ff23fSmrg * 5209ff23fSmrg * All Rights Reserved. 6209ff23fSmrg * 7209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining 8209ff23fSmrg * a copy of this software and associated documentation files (the 9209ff23fSmrg * "Software"), to deal in the Software without restriction, including 10209ff23fSmrg * without limitation on the rights to use, copy, modify, merge, 11209ff23fSmrg * publish, distribute, sublicense, and/or sell copies of the Software, 12209ff23fSmrg * and to permit persons to whom the Software is furnished to do so, 13209ff23fSmrg * subject to the following conditions: 14209ff23fSmrg * 15209ff23fSmrg * The above copyright notice and this permission notice (including the 16209ff23fSmrg * next paragraph) shall be included in all copies or substantial 17209ff23fSmrg * portions of the Software. 18209ff23fSmrg * 19209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20209ff23fSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21209ff23fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22209ff23fSmrg * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 23209ff23fSmrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24209ff23fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26209ff23fSmrg * DEALINGS IN THE SOFTWARE. 27209ff23fSmrg */ 28209ff23fSmrg 29209ff23fSmrg#ifdef HAVE_CONFIG_H 30209ff23fSmrg#include "config.h" 31209ff23fSmrg#endif 32209ff23fSmrg 33209ff23fSmrg#include <string.h> 34209ff23fSmrg#include <stdio.h> 35209ff23fSmrg 36209ff23fSmrg/* X and server generic header files */ 37209ff23fSmrg#include "xf86.h" 38209ff23fSmrg#include "xf86_OSproc.h" 39209ff23fSmrg#include "vgaHW.h" 40209ff23fSmrg#include "xf86Modes.h" 41209ff23fSmrg 42209ff23fSmrg/* Driver data structures */ 43209ff23fSmrg#include "radeon.h" 44209ff23fSmrg#include "radeon_reg.h" 45209ff23fSmrg#include "radeon_macros.h" 46209ff23fSmrg#include "radeon_probe.h" 47209ff23fSmrg#include "radeon_version.h" 48b7e1c893Smrg#include "radeon_atombios.h" 49209ff23fSmrg 50209ff23fSmrg#ifdef XF86DRI 51209ff23fSmrg#define _XF86DRI_SERVER_ 52b7e1c893Smrg#include "radeon_drm.h" 53209ff23fSmrg#include "sarea.h" 54209ff23fSmrg#ifdef DRM_IOCTL_MODESET_CTL 55209ff23fSmrg#include <sys/ioctl.h> 56209ff23fSmrg#endif 57209ff23fSmrg#endif 58209ff23fSmrg 59209ff23fSmrg/* Write common registers */ 60209ff23fSmrgvoid 61209ff23fSmrgRADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, 62209ff23fSmrg RADEONSavePtr restore) 63209ff23fSmrg{ 64209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 65209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 66209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 67209ff23fSmrg 68209ff23fSmrg if (info->IsSecondary) 69209ff23fSmrg return; 70209ff23fSmrg 71209ff23fSmrg OUTREG(RADEON_OVR_CLR, restore->ovr_clr); 72209ff23fSmrg OUTREG(RADEON_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right); 73209ff23fSmrg OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom); 74209ff23fSmrg OUTREG(RADEON_OV0_SCALE_CNTL, restore->ov0_scale_cntl); 75209ff23fSmrg OUTREG(RADEON_SUBPIC_CNTL, restore->subpic_cntl); 76209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, restore->viph_control); 77209ff23fSmrg OUTREG(RADEON_I2C_CNTL_1, restore->i2c_cntl_1); 78209ff23fSmrg OUTREG(RADEON_GEN_INT_CNTL, restore->gen_int_cntl); 79209ff23fSmrg OUTREG(RADEON_CAP0_TRIG_CNTL, restore->cap0_trig_cntl); 80209ff23fSmrg OUTREG(RADEON_CAP1_TRIG_CNTL, restore->cap1_trig_cntl); 81209ff23fSmrg OUTREG(RADEON_BUS_CNTL, restore->bus_cntl); 82209ff23fSmrg OUTREG(RADEON_SURFACE_CNTL, restore->surface_cntl); 83209ff23fSmrg 84209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 85209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 86209ff23fSmrg OUTREG(RS400_DISP2_REQ_CNTL1, restore->disp2_req_cntl1); 87209ff23fSmrg OUTREG(RS400_DISP2_REQ_CNTL2, restore->disp2_req_cntl2); 88209ff23fSmrg OUTREG(RS400_DMIF_MEM_CNTL1, restore->dmif_mem_cntl1); 89209ff23fSmrg OUTREG(RS400_DISP1_REQ_CNTL1, restore->disp1_req_cntl1); 90209ff23fSmrg } 91209ff23fSmrg 92209ff23fSmrg /* Workaround for the VT switching problem in dual-head mode. This 93209ff23fSmrg * problem only occurs on RV style chips, typically when a FP and 94209ff23fSmrg * CRT are connected. 95209ff23fSmrg */ 96209ff23fSmrg if (pRADEONEnt->HasCRTC2 && 97209ff23fSmrg info->ChipFamily != CHIP_FAMILY_R200 && 98209ff23fSmrg !IS_R300_VARIANT) { 99209ff23fSmrg uint32_t tmp; 100209ff23fSmrg 101209ff23fSmrg tmp = INREG(RADEON_DAC_CNTL2); 102209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); 103209ff23fSmrg usleep(100000); 104209ff23fSmrg } 105209ff23fSmrg} 106209ff23fSmrg 107b7e1c893Smrgvoid 108b7e1c893SmrgRADEONRestoreCrtcBase(ScrnInfoPtr pScrn, 109b7e1c893Smrg RADEONSavePtr restore) 110b7e1c893Smrg{ 111b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 112b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 113b7e1c893Smrg 114b7e1c893Smrg if (IS_R300_VARIANT) 115b7e1c893Smrg OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0); 116b7e1c893Smrg OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); 117b7e1c893Smrg OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); 118b7e1c893Smrg} 119b7e1c893Smrg 120b7e1c893Smrgvoid 121b7e1c893SmrgRADEONRestoreCrtc2Base(ScrnInfoPtr pScrn, 122b7e1c893Smrg RADEONSavePtr restore) 123b7e1c893Smrg{ 124b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 125b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 126b7e1c893Smrg 127b7e1c893Smrg if (IS_R300_VARIANT) 128b7e1c893Smrg OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0); 129b7e1c893Smrg OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); 130b7e1c893Smrg OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); 131b7e1c893Smrg} 132209ff23fSmrg 133209ff23fSmrg/* Write CRTC registers */ 134209ff23fSmrgvoid 135209ff23fSmrgRADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, 136209ff23fSmrg RADEONSavePtr restore) 137209ff23fSmrg{ 138209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 139209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 140209ff23fSmrg 141209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 142209ff23fSmrg "Programming CRTC1, offset: 0x%08x\n", 143209ff23fSmrg (unsigned)restore->crtc_offset); 144209ff23fSmrg 145209ff23fSmrg /* We prevent the CRTC from hitting the memory controller until 146209ff23fSmrg * fully programmed 147209ff23fSmrg */ 148209ff23fSmrg OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl | 149209ff23fSmrg RADEON_CRTC_DISP_REQ_EN_B); 150209ff23fSmrg 151209ff23fSmrg OUTREGP(RADEON_CRTC_EXT_CNTL, 152209ff23fSmrg restore->crtc_ext_cntl, 153209ff23fSmrg RADEON_CRTC_VSYNC_DIS | 154209ff23fSmrg RADEON_CRTC_HSYNC_DIS | 155209ff23fSmrg RADEON_CRTC_DISPLAY_DIS); 156209ff23fSmrg 157209ff23fSmrg OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); 158209ff23fSmrg OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); 159209ff23fSmrg OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); 160209ff23fSmrg OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); 161209ff23fSmrg 162b7e1c893Smrg RADEONRestoreCrtcBase(pScrn, restore); 163209ff23fSmrg 164209ff23fSmrg OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); 165209ff23fSmrg OUTREG(RADEON_DISP_MERGE_CNTL, restore->disp_merge_cntl); 166209ff23fSmrg 167209ff23fSmrg if (info->IsDellServer) { 168209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); 169209ff23fSmrg OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); 170209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); 171209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); 172209ff23fSmrg } 173209ff23fSmrg 174209ff23fSmrg OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl); 175209ff23fSmrg} 176209ff23fSmrg 177209ff23fSmrg/* Write CRTC2 registers */ 178209ff23fSmrgvoid 179209ff23fSmrgRADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, 180209ff23fSmrg RADEONSavePtr restore) 181209ff23fSmrg{ 182209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 183209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 184209ff23fSmrg /* uint32_t crtc2_gen_cntl;*/ 185209ff23fSmrg 186209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 187209ff23fSmrg "Programming CRTC2, offset: 0x%08x\n", 188209ff23fSmrg (unsigned)restore->crtc2_offset); 189209ff23fSmrg 190209ff23fSmrg /* We prevent the CRTC from hitting the memory controller until 191209ff23fSmrg * fully programmed 192209ff23fSmrg */ 193209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, 194209ff23fSmrg restore->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS | 195209ff23fSmrg RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS | 196209ff23fSmrg RADEON_CRTC2_DISP_REQ_EN_B); 197209ff23fSmrg 198209ff23fSmrg OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); 199209ff23fSmrg OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); 200209ff23fSmrg OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); 201209ff23fSmrg OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); 202209ff23fSmrg 203209ff23fSmrg OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid); 204209ff23fSmrg OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid); 205209ff23fSmrg 206b7e1c893Smrg RADEONRestoreCrtc2Base(pScrn, restore); 207209ff23fSmrg 208209ff23fSmrg OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); 209209ff23fSmrg OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); 210209ff23fSmrg 211209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); 212209ff23fSmrg 213209ff23fSmrg} 214209ff23fSmrg 215209ff23fSmrgstatic void 216209ff23fSmrgRADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) 217209ff23fSmrg{ 218209ff23fSmrg int i = 0; 219209ff23fSmrg 220209ff23fSmrg /* FIXME: Certain revisions of R300 can't recover here. Not sure of 221209ff23fSmrg the cause yet, but this workaround will mask the problem for now. 222209ff23fSmrg Other chips usually will pass at the very first test, so the 223209ff23fSmrg workaround shouldn't have any effect on them. */ 224209ff23fSmrg for (i = 0; 225209ff23fSmrg (i < 10000 && 226209ff23fSmrg INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); 227209ff23fSmrg i++); 228209ff23fSmrg} 229209ff23fSmrg 230209ff23fSmrgstatic void 231209ff23fSmrgRADEONPLLWriteUpdate(ScrnInfoPtr pScrn) 232209ff23fSmrg{ 233209ff23fSmrg while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); 234209ff23fSmrg 235209ff23fSmrg OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, 236209ff23fSmrg RADEON_PPLL_ATOMIC_UPDATE_W, 237209ff23fSmrg ~(RADEON_PPLL_ATOMIC_UPDATE_W)); 238209ff23fSmrg} 239209ff23fSmrg 240209ff23fSmrgstatic void 241209ff23fSmrgRADEONPLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn) 242209ff23fSmrg{ 243209ff23fSmrg int i = 0; 244209ff23fSmrg 245209ff23fSmrg /* FIXME: Certain revisions of R300 can't recover here. Not sure of 246209ff23fSmrg the cause yet, but this workaround will mask the problem for now. 247209ff23fSmrg Other chips usually will pass at the very first test, so the 248209ff23fSmrg workaround shouldn't have any effect on them. */ 249209ff23fSmrg for (i = 0; 250209ff23fSmrg (i < 10000 && 251209ff23fSmrg INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); 252209ff23fSmrg i++); 253209ff23fSmrg} 254209ff23fSmrg 255209ff23fSmrgstatic void 256209ff23fSmrgRADEONPLL2WriteUpdate(ScrnInfoPtr pScrn) 257209ff23fSmrg{ 258209ff23fSmrg while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); 259209ff23fSmrg 260209ff23fSmrg OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV, 261209ff23fSmrg RADEON_P2PLL_ATOMIC_UPDATE_W, 262209ff23fSmrg ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); 263209ff23fSmrg} 264209ff23fSmrg 265209ff23fSmrgstatic uint8_t 266209ff23fSmrgRADEONComputePLLGain(uint16_t reference_freq, uint16_t ref_div, 267209ff23fSmrg uint16_t fb_div) 268209ff23fSmrg{ 269209ff23fSmrg unsigned vcoFreq; 270209ff23fSmrg 271209ff23fSmrg if (!ref_div) 272209ff23fSmrg return 1; 273209ff23fSmrg 274209ff23fSmrg vcoFreq = ((unsigned)reference_freq * fb_div) / ref_div; 275209ff23fSmrg 276209ff23fSmrg /* 277209ff23fSmrg * This is horribly crude: the VCO frequency range is divided into 278209ff23fSmrg * 3 parts, each part having a fixed PLL gain value. 279209ff23fSmrg */ 280209ff23fSmrg if (vcoFreq >= 30000) 281209ff23fSmrg /* 282209ff23fSmrg * [300..max] MHz : 7 283209ff23fSmrg */ 284209ff23fSmrg return 7; 285209ff23fSmrg else if (vcoFreq >= 18000) 286209ff23fSmrg /* 287209ff23fSmrg * [180..300) MHz : 4 288209ff23fSmrg */ 289209ff23fSmrg return 4; 290209ff23fSmrg else 291209ff23fSmrg /* 292209ff23fSmrg * [0..180) MHz : 1 293209ff23fSmrg */ 294209ff23fSmrg return 1; 295209ff23fSmrg} 296209ff23fSmrg 297209ff23fSmrg/* Write PLL registers */ 298209ff23fSmrgvoid 299209ff23fSmrgRADEONRestorePLLRegisters(ScrnInfoPtr pScrn, 300209ff23fSmrg RADEONSavePtr restore) 301209ff23fSmrg{ 302209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 303209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 304209ff23fSmrg uint8_t pllGain; 305209ff23fSmrg 306209ff23fSmrg#if defined(__powerpc__) 307209ff23fSmrg /* apparently restoring the pll causes a hang??? */ 3081764dec5Smacallan if ((info->MacModel == RADEON_MAC_IBOOK) || 3091764dec5Smacallan (info->MacModel == RADEON_MAC_MINI_INTERNAL)) 310209ff23fSmrg return; 311209ff23fSmrg#endif 312209ff23fSmrg 313209ff23fSmrg pllGain = RADEONComputePLLGain(info->pll.reference_freq, 314209ff23fSmrg restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, 315209ff23fSmrg restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK); 316209ff23fSmrg 317209ff23fSmrg if (info->IsMobility) { 318209ff23fSmrg /* A temporal workaround for the occational blanking on certain laptop panels. 319209ff23fSmrg This appears to related to the PLL divider registers (fail to lock?). 320209ff23fSmrg It occurs even when all dividers are the same with their old settings. 321209ff23fSmrg In this case we really don't need to fiddle with PLL registers. 322209ff23fSmrg By doing this we can avoid the blanking problem with some panels. 323209ff23fSmrg */ 324209ff23fSmrg if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && 325209ff23fSmrg (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) & 326209ff23fSmrg (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { 327209ff23fSmrg OUTREGP(RADEON_CLOCK_CNTL_INDEX, 328209ff23fSmrg RADEON_PLL_DIV_SEL, 329209ff23fSmrg ~(RADEON_PLL_DIV_SEL)); 330209ff23fSmrg RADEONPllErrataAfterIndex(info); 331209ff23fSmrg return; 332209ff23fSmrg } 333209ff23fSmrg } 334209ff23fSmrg 335209ff23fSmrg OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, 336209ff23fSmrg RADEON_VCLK_SRC_SEL_CPUCLK, 337209ff23fSmrg ~(RADEON_VCLK_SRC_SEL_MASK)); 338209ff23fSmrg 339209ff23fSmrg OUTPLLP(pScrn, 340209ff23fSmrg RADEON_PPLL_CNTL, 341209ff23fSmrg RADEON_PPLL_RESET 342209ff23fSmrg | RADEON_PPLL_ATOMIC_UPDATE_EN 343209ff23fSmrg | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN 344209ff23fSmrg | ((uint32_t)pllGain << RADEON_PPLL_PVG_SHIFT), 345209ff23fSmrg ~(RADEON_PPLL_RESET 346209ff23fSmrg | RADEON_PPLL_ATOMIC_UPDATE_EN 347209ff23fSmrg | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN 348209ff23fSmrg | RADEON_PPLL_PVG_MASK)); 349209ff23fSmrg 350209ff23fSmrg OUTREGP(RADEON_CLOCK_CNTL_INDEX, 351209ff23fSmrg RADEON_PLL_DIV_SEL, 352209ff23fSmrg ~(RADEON_PLL_DIV_SEL)); 353209ff23fSmrg RADEONPllErrataAfterIndex(info); 354209ff23fSmrg 355209ff23fSmrg if (IS_R300_VARIANT || 356209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS300) || 357209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS400) || 358209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 359209ff23fSmrg if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { 360209ff23fSmrg /* When restoring console mode, use saved PPLL_REF_DIV 361209ff23fSmrg * setting. 362209ff23fSmrg */ 363209ff23fSmrg OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, 364209ff23fSmrg restore->ppll_ref_div, 365209ff23fSmrg 0); 366209ff23fSmrg } else { 367209ff23fSmrg /* R300 uses ref_div_acc field as real ref divider */ 368209ff23fSmrg OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, 369209ff23fSmrg (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), 370209ff23fSmrg ~R300_PPLL_REF_DIV_ACC_MASK); 371209ff23fSmrg } 372209ff23fSmrg } else { 373209ff23fSmrg OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, 374209ff23fSmrg restore->ppll_ref_div, 375209ff23fSmrg ~RADEON_PPLL_REF_DIV_MASK); 376209ff23fSmrg } 377209ff23fSmrg 378209ff23fSmrg OUTPLLP(pScrn, RADEON_PPLL_DIV_3, 379209ff23fSmrg restore->ppll_div_3, 380209ff23fSmrg ~RADEON_PPLL_FB3_DIV_MASK); 381209ff23fSmrg 382209ff23fSmrg OUTPLLP(pScrn, RADEON_PPLL_DIV_3, 383209ff23fSmrg restore->ppll_div_3, 384209ff23fSmrg ~RADEON_PPLL_POST3_DIV_MASK); 385209ff23fSmrg 386209ff23fSmrg RADEONPLLWriteUpdate(pScrn); 387209ff23fSmrg RADEONPLLWaitForReadUpdateComplete(pScrn); 388209ff23fSmrg 389209ff23fSmrg OUTPLL(pScrn, RADEON_HTOTAL_CNTL, restore->htotal_cntl); 390209ff23fSmrg 391209ff23fSmrg OUTPLLP(pScrn, RADEON_PPLL_CNTL, 392209ff23fSmrg 0, 393209ff23fSmrg ~(RADEON_PPLL_RESET 394209ff23fSmrg | RADEON_PPLL_SLEEP 395209ff23fSmrg | RADEON_PPLL_ATOMIC_UPDATE_EN 396209ff23fSmrg | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); 397209ff23fSmrg 398209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 399209ff23fSmrg "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 400209ff23fSmrg restore->ppll_ref_div, 401209ff23fSmrg restore->ppll_div_3, 402209ff23fSmrg (unsigned)restore->htotal_cntl, 403209ff23fSmrg INPLL(pScrn, RADEON_PPLL_CNTL)); 404209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 405209ff23fSmrg "Wrote: rd=%d, fd=%d, pd=%d\n", 406209ff23fSmrg restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, 407209ff23fSmrg restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, 408209ff23fSmrg (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); 409209ff23fSmrg 410209ff23fSmrg usleep(50000); /* Let the clock to lock */ 411209ff23fSmrg 412209ff23fSmrg OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, 413209ff23fSmrg RADEON_VCLK_SRC_SEL_PPLLCLK, 414209ff23fSmrg ~(RADEON_VCLK_SRC_SEL_MASK)); 415209ff23fSmrg 416209ff23fSmrg /*OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_ecp_cntl);*/ 417209ff23fSmrg 418209ff23fSmrg ErrorF("finished PLL1\n"); 419209ff23fSmrg 420209ff23fSmrg} 421209ff23fSmrg 422209ff23fSmrg/* Write PLL2 registers */ 423209ff23fSmrgvoid 424209ff23fSmrgRADEONRestorePLL2Registers(ScrnInfoPtr pScrn, 425209ff23fSmrg RADEONSavePtr restore) 426209ff23fSmrg{ 427209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 428209ff23fSmrg uint8_t pllGain; 429209ff23fSmrg 430209ff23fSmrg pllGain = RADEONComputePLLGain(info->pll.reference_freq, 431209ff23fSmrg restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, 432209ff23fSmrg restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK); 433209ff23fSmrg 434209ff23fSmrg 435209ff23fSmrg OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 436209ff23fSmrg RADEON_PIX2CLK_SRC_SEL_CPUCLK, 437209ff23fSmrg ~(RADEON_PIX2CLK_SRC_SEL_MASK)); 438209ff23fSmrg 439209ff23fSmrg OUTPLLP(pScrn, 440209ff23fSmrg RADEON_P2PLL_CNTL, 441209ff23fSmrg RADEON_P2PLL_RESET 442209ff23fSmrg | RADEON_P2PLL_ATOMIC_UPDATE_EN 443209ff23fSmrg | ((uint32_t)pllGain << RADEON_P2PLL_PVG_SHIFT), 444209ff23fSmrg ~(RADEON_P2PLL_RESET 445209ff23fSmrg | RADEON_P2PLL_ATOMIC_UPDATE_EN 446209ff23fSmrg | RADEON_P2PLL_PVG_MASK)); 447209ff23fSmrg 448209ff23fSmrg 449209ff23fSmrg OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV, 450209ff23fSmrg restore->p2pll_ref_div, 451209ff23fSmrg ~RADEON_P2PLL_REF_DIV_MASK); 452209ff23fSmrg 453209ff23fSmrg OUTPLLP(pScrn, RADEON_P2PLL_DIV_0, 454209ff23fSmrg restore->p2pll_div_0, 455209ff23fSmrg ~RADEON_P2PLL_FB0_DIV_MASK); 456209ff23fSmrg 457209ff23fSmrg OUTPLLP(pScrn, RADEON_P2PLL_DIV_0, 458209ff23fSmrg restore->p2pll_div_0, 459209ff23fSmrg ~RADEON_P2PLL_POST0_DIV_MASK); 460209ff23fSmrg 461209ff23fSmrg RADEONPLL2WriteUpdate(pScrn); 462209ff23fSmrg RADEONPLL2WaitForReadUpdateComplete(pScrn); 463209ff23fSmrg 464209ff23fSmrg OUTPLL(pScrn, RADEON_HTOTAL2_CNTL, restore->htotal_cntl2); 465209ff23fSmrg 466209ff23fSmrg OUTPLLP(pScrn, RADEON_P2PLL_CNTL, 467209ff23fSmrg 0, 468209ff23fSmrg ~(RADEON_P2PLL_RESET 469209ff23fSmrg | RADEON_P2PLL_SLEEP 470209ff23fSmrg | RADEON_P2PLL_ATOMIC_UPDATE_EN)); 471209ff23fSmrg 472209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 473209ff23fSmrg "Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 474209ff23fSmrg (unsigned)restore->p2pll_ref_div, 475209ff23fSmrg (unsigned)restore->p2pll_div_0, 476209ff23fSmrg (unsigned)restore->htotal_cntl2, 477209ff23fSmrg INPLL(pScrn, RADEON_P2PLL_CNTL)); 478209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 479209ff23fSmrg "Wrote2: rd=%u, fd=%u, pd=%u\n", 480209ff23fSmrg (unsigned)restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, 481209ff23fSmrg (unsigned)restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, 482209ff23fSmrg (unsigned)((restore->p2pll_div_0 & 483209ff23fSmrg RADEON_P2PLL_POST0_DIV_MASK) >>16)); 484209ff23fSmrg 485209ff23fSmrg usleep(5000); /* Let the clock to lock */ 486209ff23fSmrg 487209ff23fSmrg OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 488209ff23fSmrg RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, 489209ff23fSmrg ~(RADEON_PIX2CLK_SRC_SEL_MASK)); 490209ff23fSmrg 491209ff23fSmrg OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); 492209ff23fSmrg 493209ff23fSmrg ErrorF("finished PLL2\n"); 494209ff23fSmrg 495209ff23fSmrg} 496209ff23fSmrg 497209ff23fSmrg/* Read common registers */ 498209ff23fSmrgvoid 499209ff23fSmrgRADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) 500209ff23fSmrg{ 501209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 502209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 503209ff23fSmrg 504209ff23fSmrg save->ovr_clr = INREG(RADEON_OVR_CLR); 505209ff23fSmrg save->ovr_wid_left_right = INREG(RADEON_OVR_WID_LEFT_RIGHT); 506209ff23fSmrg save->ovr_wid_top_bottom = INREG(RADEON_OVR_WID_TOP_BOTTOM); 507209ff23fSmrg save->ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL); 508209ff23fSmrg save->subpic_cntl = INREG(RADEON_SUBPIC_CNTL); 509209ff23fSmrg save->viph_control = INREG(RADEON_VIPH_CONTROL); 510209ff23fSmrg save->i2c_cntl_1 = INREG(RADEON_I2C_CNTL_1); 511209ff23fSmrg save->gen_int_cntl = INREG(RADEON_GEN_INT_CNTL); 512209ff23fSmrg save->cap0_trig_cntl = INREG(RADEON_CAP0_TRIG_CNTL); 513209ff23fSmrg save->cap1_trig_cntl = INREG(RADEON_CAP1_TRIG_CNTL); 514209ff23fSmrg save->bus_cntl = INREG(RADEON_BUS_CNTL); 515209ff23fSmrg save->surface_cntl = INREG(RADEON_SURFACE_CNTL); 516209ff23fSmrg save->grph_buffer_cntl = INREG(RADEON_GRPH_BUFFER_CNTL); 517209ff23fSmrg save->grph2_buffer_cntl = INREG(RADEON_GRPH2_BUFFER_CNTL); 518209ff23fSmrg 519209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 520209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 521209ff23fSmrg save->disp2_req_cntl1 = INREG(RS400_DISP2_REQ_CNTL1); 522209ff23fSmrg save->disp2_req_cntl2 = INREG(RS400_DISP2_REQ_CNTL2); 523209ff23fSmrg save->dmif_mem_cntl1 = INREG(RS400_DMIF_MEM_CNTL1); 524209ff23fSmrg save->disp1_req_cntl1 = INREG(RS400_DISP1_REQ_CNTL1); 525209ff23fSmrg } 526209ff23fSmrg} 527209ff23fSmrg 528209ff23fSmrg/* Read CRTC registers */ 529209ff23fSmrgvoid 530209ff23fSmrgRADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) 531209ff23fSmrg{ 532209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 533209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 534209ff23fSmrg 535209ff23fSmrg save->crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); 536209ff23fSmrg save->crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); 537209ff23fSmrg save->crtc_h_total_disp = INREG(RADEON_CRTC_H_TOTAL_DISP); 538209ff23fSmrg save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID); 539209ff23fSmrg save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP); 540209ff23fSmrg save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID); 541209ff23fSmrg 542209ff23fSmrg save->crtc_offset = INREG(RADEON_CRTC_OFFSET); 543209ff23fSmrg save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); 544209ff23fSmrg save->crtc_pitch = INREG(RADEON_CRTC_PITCH); 545209ff23fSmrg save->disp_merge_cntl = INREG(RADEON_DISP_MERGE_CNTL); 546209ff23fSmrg 547209ff23fSmrg if (IS_R300_VARIANT) 548209ff23fSmrg save->crtc_tile_x0_y0 = INREG(R300_CRTC_TILE_X0_Y0); 549209ff23fSmrg 550209ff23fSmrg if (info->IsDellServer) { 551209ff23fSmrg save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 552209ff23fSmrg save->dac2_cntl = INREG(RADEON_DAC_CNTL2); 553209ff23fSmrg save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); 554209ff23fSmrg save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); 555209ff23fSmrg } 556209ff23fSmrg 557209ff23fSmrg /* track if the crtc is enabled for text restore */ 558209ff23fSmrg if (save->crtc_ext_cntl & RADEON_CRTC_DISPLAY_DIS) 559209ff23fSmrg info->crtc_on = FALSE; 560209ff23fSmrg else 561209ff23fSmrg info->crtc_on = TRUE; 562209ff23fSmrg 563209ff23fSmrg} 564209ff23fSmrg 565209ff23fSmrg/* Read CRTC2 registers */ 566209ff23fSmrgvoid 567209ff23fSmrgRADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) 568209ff23fSmrg{ 569209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 570209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 571209ff23fSmrg 572209ff23fSmrg save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); 573209ff23fSmrg save->crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); 574209ff23fSmrg save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); 575209ff23fSmrg save->crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); 576209ff23fSmrg save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); 577b7e1c893Smrg 578209ff23fSmrg save->crtc2_offset = INREG(RADEON_CRTC2_OFFSET); 579209ff23fSmrg save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); 580209ff23fSmrg save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH); 581209ff23fSmrg 582209ff23fSmrg if (IS_R300_VARIANT) 583209ff23fSmrg save->crtc2_tile_x0_y0 = INREG(R300_CRTC2_TILE_X0_Y0); 584209ff23fSmrg 585209ff23fSmrg save->fp_h2_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); 586209ff23fSmrg save->fp_v2_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); 587209ff23fSmrg 588209ff23fSmrg save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL); 589209ff23fSmrg 590209ff23fSmrg /* track if the crtc is enabled for text restore */ 591209ff23fSmrg if (save->crtc2_gen_cntl & RADEON_CRTC2_DISP_DIS) 592209ff23fSmrg info->crtc2_on = FALSE; 593209ff23fSmrg else 594209ff23fSmrg info->crtc2_on = TRUE; 595209ff23fSmrg 596209ff23fSmrg} 597209ff23fSmrg 598209ff23fSmrg/* Read PLL registers */ 599209ff23fSmrgvoid 600209ff23fSmrgRADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) 601209ff23fSmrg{ 602209ff23fSmrg save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV); 603209ff23fSmrg save->ppll_div_3 = INPLL(pScrn, RADEON_PPLL_DIV_3); 604209ff23fSmrg save->htotal_cntl = INPLL(pScrn, RADEON_HTOTAL_CNTL); 605209ff23fSmrg save->vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); 606209ff23fSmrg 607209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 608209ff23fSmrg "Read: 0x%08x 0x%08x 0x%08x\n", 609209ff23fSmrg save->ppll_ref_div, 610209ff23fSmrg save->ppll_div_3, 611209ff23fSmrg (unsigned)save->htotal_cntl); 612209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 613209ff23fSmrg "Read: rd=%d, fd=%d, pd=%d\n", 614209ff23fSmrg save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, 615209ff23fSmrg save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, 616209ff23fSmrg (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); 617209ff23fSmrg} 618209ff23fSmrg 619209ff23fSmrg/* Read PLL registers */ 620209ff23fSmrgvoid 621209ff23fSmrgRADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) 622209ff23fSmrg{ 623209ff23fSmrg save->p2pll_ref_div = INPLL(pScrn, RADEON_P2PLL_REF_DIV); 624209ff23fSmrg save->p2pll_div_0 = INPLL(pScrn, RADEON_P2PLL_DIV_0); 625209ff23fSmrg save->htotal_cntl2 = INPLL(pScrn, RADEON_HTOTAL2_CNTL); 626209ff23fSmrg save->pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); 627209ff23fSmrg 628209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 629209ff23fSmrg "Read: 0x%08x 0x%08x 0x%08x\n", 630209ff23fSmrg (unsigned)save->p2pll_ref_div, 631209ff23fSmrg (unsigned)save->p2pll_div_0, 632209ff23fSmrg (unsigned)save->htotal_cntl2); 633209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 634209ff23fSmrg "Read: rd=%u, fd=%u, pd=%u\n", 635209ff23fSmrg (unsigned)(save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK), 636209ff23fSmrg (unsigned)(save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK), 637209ff23fSmrg (unsigned)((save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) 638209ff23fSmrg >> 16)); 639209ff23fSmrg} 640209ff23fSmrg 641209ff23fSmrgvoid 642209ff23fSmrgradeon_crtc_modeset_ioctl(xf86CrtcPtr crtc, Bool post) 643209ff23fSmrg{ 644209ff23fSmrg#if defined(XF86DRI) && defined(DRM_IOCTL_MODESET_CTL) 645209ff23fSmrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 646209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 647209ff23fSmrg struct drm_modeset_ctl modeset; 648b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 649b7e1c893Smrg 650b7e1c893Smrg if (!info->directRenderingEnabled) 651b7e1c893Smrg return; 652209ff23fSmrg 653c503f109Smrg if (info->ChipFamily >= CHIP_FAMILY_R600) 654c503f109Smrg return; 655c503f109Smrg 656209ff23fSmrg modeset.crtc = radeon_crtc->crtc_id; 657209ff23fSmrg modeset.cmd = post ? _DRM_POST_MODESET : _DRM_PRE_MODESET; 658209ff23fSmrg 659b7e1c893Smrg ioctl(info->dri->drmFD, DRM_IOCTL_MODESET_CTL, &modeset); 660b7e1c893Smrg 661b7e1c893Smrg info->ModeReg->gen_int_cntl = INREG( RADEON_GEN_INT_CNTL ); 662209ff23fSmrg#endif 663209ff23fSmrg} 664209ff23fSmrg 665209ff23fSmrgvoid 666209ff23fSmrglegacy_crtc_dpms(xf86CrtcPtr crtc, int mode) 667209ff23fSmrg{ 668c503f109Smrg uint32_t mask; 669209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 670209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 671209ff23fSmrg unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 672209ff23fSmrg 673c503f109Smrg if (radeon_crtc->crtc_id) 674f1bc02b7Smrg mask = (RADEON_CRTC2_DISP_DIS | 675c503f109Smrg RADEON_CRTC2_VSYNC_DIS | 676c503f109Smrg RADEON_CRTC2_HSYNC_DIS | 677c503f109Smrg RADEON_CRTC2_DISP_REQ_EN_B); 678c503f109Smrg else 679c503f109Smrg mask = (RADEON_CRTC_DISPLAY_DIS | 680c503f109Smrg RADEON_CRTC_HSYNC_DIS | 681c503f109Smrg RADEON_CRTC_VSYNC_DIS); 682209ff23fSmrg 683209ff23fSmrg switch(mode) { 684209ff23fSmrg case DPMSModeOn: 685209ff23fSmrg if (radeon_crtc->crtc_id) { 686f1bc02b7Smrg OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); 687209ff23fSmrg } else { 688c503f109Smrg OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); 689209ff23fSmrg OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask); 690209ff23fSmrg } 691209ff23fSmrg break; 692209ff23fSmrg case DPMSModeStandby: 693209ff23fSmrg case DPMSModeSuspend: 694209ff23fSmrg case DPMSModeOff: 695209ff23fSmrg if (radeon_crtc->crtc_id) { 696f1bc02b7Smrg OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask)); 697209ff23fSmrg } else { 698c503f109Smrg OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); 699209ff23fSmrg OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask); 700209ff23fSmrg } 701209ff23fSmrg break; 702209ff23fSmrg } 703209ff23fSmrg} 704209ff23fSmrg 705209ff23fSmrg 706209ff23fSmrg/* Define common registers for requested video mode */ 707b7e1c893Smrgvoid 708209ff23fSmrgRADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) 709209ff23fSmrg{ 710209ff23fSmrg save->ovr_clr = 0; 711209ff23fSmrg save->ovr_wid_left_right = 0; 712209ff23fSmrg save->ovr_wid_top_bottom = 0; 713209ff23fSmrg save->ov0_scale_cntl = 0; 714209ff23fSmrg save->subpic_cntl = 0; 715209ff23fSmrg save->viph_control = 0; 716209ff23fSmrg save->i2c_cntl_1 = 0; 717209ff23fSmrg save->rbbm_soft_reset = 0; 718209ff23fSmrg save->cap0_trig_cntl = 0; 719209ff23fSmrg save->cap1_trig_cntl = 0; 720209ff23fSmrg save->bus_cntl = info->BusCntl; 721209ff23fSmrg 722209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 723209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 724209ff23fSmrg save->disp2_req_cntl1 = info->SavedReg->disp2_req_cntl1; 725209ff23fSmrg save->disp2_req_cntl2 = info->SavedReg->disp2_req_cntl2; 726209ff23fSmrg save->dmif_mem_cntl1 = info->SavedReg->dmif_mem_cntl1; 727209ff23fSmrg save->disp1_req_cntl1 = info->SavedReg->disp1_req_cntl1; 728209ff23fSmrg } 729209ff23fSmrg 730209ff23fSmrg /* 731209ff23fSmrg * If bursts are enabled, turn on discards 732209ff23fSmrg * Radeon doesn't have write bursts 733209ff23fSmrg */ 734209ff23fSmrg if (save->bus_cntl & (RADEON_BUS_READ_BURST)) 735209ff23fSmrg save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; 736209ff23fSmrg} 737209ff23fSmrg 738b7e1c893Smrgvoid 739209ff23fSmrgRADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save) 740209ff23fSmrg{ 741209ff23fSmrg save->surface_cntl = 0; 742209ff23fSmrg 743209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 744209ff23fSmrg /* We must set both apertures as they can be both used to map the entire 745209ff23fSmrg * video memory. -BenH. 746209ff23fSmrg */ 747209ff23fSmrg switch (crtc->scrn->bitsPerPixel) { 748209ff23fSmrg case 16: 749209ff23fSmrg save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; 750209ff23fSmrg save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; 751209ff23fSmrg break; 752209ff23fSmrg 753209ff23fSmrg case 32: 754209ff23fSmrg save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; 755209ff23fSmrg save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; 756209ff23fSmrg break; 757209ff23fSmrg } 758209ff23fSmrg#endif 759209ff23fSmrg 760209ff23fSmrg} 761209ff23fSmrg 762b7e1c893Smrgvoid 763209ff23fSmrgRADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save, 764209ff23fSmrg int x, int y) 765209ff23fSmrg{ 766209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 767209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 768209ff23fSmrg int Base; 769209ff23fSmrg#ifdef XF86DRI 770b7e1c893Smrg drm_radeon_sarea_t *pSAREAPriv; 771209ff23fSmrg XF86DRISAREAPtr pSAREA; 772209ff23fSmrg#endif 773209ff23fSmrg 774209ff23fSmrg save->crtc_offset = pScrn->fbOffset; 775209ff23fSmrg#ifdef XF86DRI 776b7e1c893Smrg if (info->dri && info->dri->allowPageFlip) 777209ff23fSmrg save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; 778209ff23fSmrg else 779209ff23fSmrg#endif 780209ff23fSmrg save->crtc_offset_cntl = 0; 781209ff23fSmrg 782209ff23fSmrg if (info->tilingEnabled && (crtc->rotatedData == NULL)) { 783209ff23fSmrg if (IS_R300_VARIANT) 784209ff23fSmrg save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | 785209ff23fSmrg R300_CRTC_MICRO_TILE_BUFFER_DIS | 786209ff23fSmrg R300_CRTC_MACRO_TILE_EN); 787209ff23fSmrg else 788209ff23fSmrg save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; 789209ff23fSmrg } 790209ff23fSmrg else { 791209ff23fSmrg if (IS_R300_VARIANT) 792209ff23fSmrg save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | 793209ff23fSmrg R300_CRTC_MICRO_TILE_BUFFER_DIS | 794209ff23fSmrg R300_CRTC_MACRO_TILE_EN); 795209ff23fSmrg else 796209ff23fSmrg save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; 797209ff23fSmrg } 798209ff23fSmrg 799209ff23fSmrg Base = pScrn->fbOffset; 800209ff23fSmrg 801209ff23fSmrg if (info->tilingEnabled && (crtc->rotatedData == NULL)) { 802209ff23fSmrg if (IS_R300_VARIANT) { 803209ff23fSmrg /* On r300/r400 when tiling is enabled crtc_offset is set to the address of 804209ff23fSmrg * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc 805209ff23fSmrg * Makes tiling MUCH easier. 806209ff23fSmrg */ 807209ff23fSmrg save->crtc_tile_x0_y0 = x | (y << 16); 808209ff23fSmrg Base &= ~0x7ff; 809209ff23fSmrg } else { 810209ff23fSmrg /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the 811209ff23fSmrg drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes 812209ff23fSmrg flickering when scrolling vertically in a virtual screen, possibly because crtc will 813209ff23fSmrg pick up the new offset value at the end of each scanline, but the new offset_cntl value 814209ff23fSmrg only after a vsync. We'd probably need to wait (in drm) for vsync and only then update 815209ff23fSmrg OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ 816209ff23fSmrg /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/ 817209ff23fSmrg#if 0 818209ff23fSmrg /* try to get rid of flickering when scrolling at least for 2d */ 819209ff23fSmrg#ifdef XF86DRI 820209ff23fSmrg if (!info->have3DWindows) 821209ff23fSmrg#endif 822209ff23fSmrg save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; 823209ff23fSmrg#endif 824209ff23fSmrg 825209ff23fSmrg int byteshift = info->CurrentLayout.bitsPerPixel >> 4; 826209ff23fSmrg /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ 827209ff23fSmrg int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; 828209ff23fSmrg Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); 829209ff23fSmrg save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16); 830209ff23fSmrg } 831209ff23fSmrg } 832209ff23fSmrg else { 833209ff23fSmrg int offset = y * info->CurrentLayout.displayWidth + x; 834209ff23fSmrg switch (info->CurrentLayout.pixel_code) { 835209ff23fSmrg case 15: 836209ff23fSmrg case 16: offset *= 2; break; 837209ff23fSmrg case 24: offset *= 3; break; 838209ff23fSmrg case 32: offset *= 4; break; 839209ff23fSmrg } 840209ff23fSmrg Base += offset; 841209ff23fSmrg } 842209ff23fSmrg 843209ff23fSmrg if (crtc->rotatedData != NULL) { 844209ff23fSmrg Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; 845209ff23fSmrg } 846209ff23fSmrg 847209ff23fSmrg Base &= ~7; /* 3 lower bits are always 0 */ 848209ff23fSmrg 849209ff23fSmrg 850209ff23fSmrg#ifdef XF86DRI 851209ff23fSmrg if (info->directRenderingInited) { 852209ff23fSmrg /* note cannot use pScrn->pScreen since this is unitialized when called from 853209ff23fSmrg RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ 854209ff23fSmrg /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for 855209ff23fSmrg *** pageflipping! 856209ff23fSmrg ***/ 857c135ecebSveego pSAREAPriv = DRIGetSAREAPrivate(xf86ScrnToScreen(pScrn)); 858209ff23fSmrg /* can't get at sarea in a semi-sane way? */ 859209ff23fSmrg pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); 860209ff23fSmrg 861209ff23fSmrg pSAREA->frame.x = (Base / info->CurrentLayout.pixel_bytes) 862209ff23fSmrg % info->CurrentLayout.displayWidth; 863209ff23fSmrg pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes) 864209ff23fSmrg / info->CurrentLayout.displayWidth; 865209ff23fSmrg pSAREA->frame.width = pScrn->frameX1 - x + 1; 866209ff23fSmrg pSAREA->frame.height = pScrn->frameY1 - y + 1; 867209ff23fSmrg 868209ff23fSmrg if (pSAREAPriv->pfCurrentPage == 1) { 869b7e1c893Smrg Base += info->dri->backOffset - info->dri->frontOffset; 870209ff23fSmrg } 871209ff23fSmrg } 872209ff23fSmrg#endif 873209ff23fSmrg save->crtc_offset = Base; 874209ff23fSmrg 875209ff23fSmrg} 876209ff23fSmrg 877209ff23fSmrg/* Define CRTC registers for requested video mode */ 878209ff23fSmrgstatic Bool 879209ff23fSmrgRADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save, 880209ff23fSmrg DisplayModePtr mode) 881209ff23fSmrg{ 882209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 883209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 884209ff23fSmrg int format; 885209ff23fSmrg int hsync_start; 886209ff23fSmrg int hsync_wid; 887209ff23fSmrg int vsync_wid; 888209ff23fSmrg 889209ff23fSmrg switch (info->CurrentLayout.pixel_code) { 890209ff23fSmrg case 4: format = 1; break; 891209ff23fSmrg case 8: format = 2; break; 892209ff23fSmrg case 15: format = 3; break; /* 555 */ 893209ff23fSmrg case 16: format = 4; break; /* 565 */ 894209ff23fSmrg case 24: format = 5; break; /* RGB */ 895209ff23fSmrg case 32: format = 6; break; /* xRGB */ 896209ff23fSmrg default: 897209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 898209ff23fSmrg "Unsupported pixel depth (%d)\n", 899209ff23fSmrg info->CurrentLayout.bitsPerPixel); 900209ff23fSmrg return FALSE; 901209ff23fSmrg } 902209ff23fSmrg 903209ff23fSmrg /*save->bios_4_scratch = info->SavedReg->bios_4_scratch;*/ 904209ff23fSmrg save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN 905209ff23fSmrg | (format << 8) 906209ff23fSmrg | ((mode->Flags & V_DBLSCAN) 907209ff23fSmrg ? RADEON_CRTC_DBL_SCAN_EN 908209ff23fSmrg : 0) 909209ff23fSmrg | ((mode->Flags & V_CSYNC) 910209ff23fSmrg ? RADEON_CRTC_CSYNC_EN 911209ff23fSmrg : 0) 912209ff23fSmrg | ((mode->Flags & V_INTERLACE) 913209ff23fSmrg ? RADEON_CRTC_INTERLACE_EN 914209ff23fSmrg : 0)); 915209ff23fSmrg 916f1bc02b7Smrg /* 200M freezes on VT switch sometimes if CRTC is disabled */ 917f1bc02b7Smrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 918f1bc02b7Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) 919f1bc02b7Smrg save->crtc_gen_cntl |= RADEON_CRTC_EN; 920f1bc02b7Smrg 921209ff23fSmrg save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| 922209ff23fSmrg RADEON_CRTC_VSYNC_DIS | 923209ff23fSmrg RADEON_CRTC_HSYNC_DIS | 924209ff23fSmrg RADEON_CRTC_DISPLAY_DIS); 925209ff23fSmrg 926209ff23fSmrg save->disp_merge_cntl = info->SavedReg->disp_merge_cntl; 927209ff23fSmrg save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; 928209ff23fSmrg 929209ff23fSmrg save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) 930209ff23fSmrg | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) 931209ff23fSmrg << 16)); 932209ff23fSmrg 933209ff23fSmrg hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 934209ff23fSmrg if (!hsync_wid) hsync_wid = 1; 935209ff23fSmrg hsync_start = mode->CrtcHSyncStart - 8; 936209ff23fSmrg 937209ff23fSmrg save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) 938209ff23fSmrg | ((hsync_wid & 0x3f) << 16) 939209ff23fSmrg | ((mode->Flags & V_NHSYNC) 940209ff23fSmrg ? RADEON_CRTC_H_SYNC_POL 941209ff23fSmrg : 0)); 942209ff23fSmrg 943209ff23fSmrg /* This works for double scan mode. */ 944209ff23fSmrg save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 945209ff23fSmrg | ((mode->CrtcVDisplay - 1) << 16)); 946209ff23fSmrg 947209ff23fSmrg vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 948209ff23fSmrg if (!vsync_wid) vsync_wid = 1; 949209ff23fSmrg 950209ff23fSmrg save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 951209ff23fSmrg | ((vsync_wid & 0x1f) << 16) 952209ff23fSmrg | ((mode->Flags & V_NVSYNC) 953209ff23fSmrg ? RADEON_CRTC_V_SYNC_POL 954209ff23fSmrg : 0)); 955209ff23fSmrg 956209ff23fSmrg save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + 957209ff23fSmrg ((pScrn->bitsPerPixel * 8) -1)) / 958209ff23fSmrg (pScrn->bitsPerPixel * 8)); 959209ff23fSmrg save->crtc_pitch |= save->crtc_pitch << 16; 960209ff23fSmrg 961209ff23fSmrg if (info->IsDellServer) { 962209ff23fSmrg save->dac2_cntl = info->SavedReg->dac2_cntl; 963209ff23fSmrg save->tv_dac_cntl = info->SavedReg->tv_dac_cntl; 964209ff23fSmrg save->crtc2_gen_cntl = info->SavedReg->crtc2_gen_cntl; 965209ff23fSmrg save->disp_hw_debug = info->SavedReg->disp_hw_debug; 966209ff23fSmrg 967209ff23fSmrg save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; 968209ff23fSmrg save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; 969209ff23fSmrg 970209ff23fSmrg /* For CRT on DAC2, don't turn it on if BIOS didn't 971209ff23fSmrg enable it, even it's detected. 972209ff23fSmrg */ 973209ff23fSmrg save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; 974209ff23fSmrg save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); 975209ff23fSmrg save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); 976209ff23fSmrg } 977209ff23fSmrg 978209ff23fSmrg return TRUE; 979209ff23fSmrg} 980209ff23fSmrg 981209ff23fSmrg 982b7e1c893Smrgvoid 983209ff23fSmrgRADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save, 984209ff23fSmrg int x, int y) 985209ff23fSmrg{ 986209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 987209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 988209ff23fSmrg int Base; 989209ff23fSmrg#ifdef XF86DRI 990b7e1c893Smrg drm_radeon_sarea_t *pSAREAPriv; 991209ff23fSmrg XF86DRISAREAPtr pSAREA; 992209ff23fSmrg#endif 993209ff23fSmrg 994209ff23fSmrg /* It seems all fancy options apart from pflip can be safely disabled 995209ff23fSmrg */ 996209ff23fSmrg save->crtc2_offset = pScrn->fbOffset; 997209ff23fSmrg#ifdef XF86DRI 998b7e1c893Smrg if (info->dri && info->dri->allowPageFlip) 999209ff23fSmrg save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; 1000209ff23fSmrg else 1001209ff23fSmrg#endif 1002209ff23fSmrg save->crtc2_offset_cntl = 0; 1003209ff23fSmrg 1004209ff23fSmrg if (info->tilingEnabled && (crtc->rotatedData == NULL)) { 1005209ff23fSmrg if (IS_R300_VARIANT) 1006209ff23fSmrg save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | 1007209ff23fSmrg R300_CRTC_MICRO_TILE_BUFFER_DIS | 1008209ff23fSmrg R300_CRTC_MACRO_TILE_EN); 1009209ff23fSmrg else 1010209ff23fSmrg save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; 1011209ff23fSmrg } 1012209ff23fSmrg else { 1013209ff23fSmrg if (IS_R300_VARIANT) 1014209ff23fSmrg save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | 1015209ff23fSmrg R300_CRTC_MICRO_TILE_BUFFER_DIS | 1016209ff23fSmrg R300_CRTC_MACRO_TILE_EN); 1017209ff23fSmrg else 1018209ff23fSmrg save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; 1019209ff23fSmrg } 1020209ff23fSmrg 1021209ff23fSmrg Base = pScrn->fbOffset; 1022209ff23fSmrg 1023209ff23fSmrg if (info->tilingEnabled && (crtc->rotatedData == NULL)) { 1024209ff23fSmrg if (IS_R300_VARIANT) { 1025209ff23fSmrg /* On r300/r400 when tiling is enabled crtc_offset is set to the address of 1026209ff23fSmrg * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc 1027209ff23fSmrg * Makes tiling MUCH easier. 1028209ff23fSmrg */ 1029209ff23fSmrg save->crtc2_tile_x0_y0 = x | (y << 16); 1030209ff23fSmrg Base &= ~0x7ff; 1031209ff23fSmrg } else { 1032209ff23fSmrg /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the 1033209ff23fSmrg drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes 1034209ff23fSmrg flickering when scrolling vertically in a virtual screen, possibly because crtc will 1035209ff23fSmrg pick up the new offset value at the end of each scanline, but the new offset_cntl value 1036209ff23fSmrg only after a vsync. We'd probably need to wait (in drm) for vsync and only then update 1037209ff23fSmrg OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ 1038209ff23fSmrg /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/ 1039209ff23fSmrg#if 0 1040209ff23fSmrg /* try to get rid of flickering when scrolling at least for 2d */ 1041209ff23fSmrg#ifdef XF86DRI 1042209ff23fSmrg if (!info->have3DWindows) 1043209ff23fSmrg#endif 1044209ff23fSmrg save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; 1045209ff23fSmrg#endif 1046209ff23fSmrg 1047209ff23fSmrg int byteshift = info->CurrentLayout.bitsPerPixel >> 4; 1048209ff23fSmrg /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ 1049209ff23fSmrg int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; 1050209ff23fSmrg Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); 1051209ff23fSmrg save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16); 1052209ff23fSmrg } 1053209ff23fSmrg } 1054209ff23fSmrg else { 1055209ff23fSmrg int offset = y * info->CurrentLayout.displayWidth + x; 1056209ff23fSmrg switch (info->CurrentLayout.pixel_code) { 1057209ff23fSmrg case 15: 1058209ff23fSmrg case 16: offset *= 2; break; 1059209ff23fSmrg case 24: offset *= 3; break; 1060209ff23fSmrg case 32: offset *= 4; break; 1061209ff23fSmrg } 1062209ff23fSmrg Base += offset; 1063209ff23fSmrg } 1064209ff23fSmrg 1065209ff23fSmrg if (crtc->rotatedData != NULL) { 1066209ff23fSmrg Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; 1067209ff23fSmrg } 1068209ff23fSmrg 1069209ff23fSmrg Base &= ~7; /* 3 lower bits are always 0 */ 1070209ff23fSmrg 1071209ff23fSmrg#ifdef XF86DRI 1072209ff23fSmrg if (info->directRenderingInited) { 1073209ff23fSmrg /* note cannot use pScrn->pScreen since this is unitialized when called from 1074209ff23fSmrg RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ 1075209ff23fSmrg /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for 1076209ff23fSmrg *** pageflipping! 1077209ff23fSmrg ***/ 1078c135ecebSveego pSAREAPriv = DRIGetSAREAPrivate(xf86ScrnToScreen(pScrn)); 1079209ff23fSmrg /* can't get at sarea in a semi-sane way? */ 1080209ff23fSmrg pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); 1081209ff23fSmrg 1082209ff23fSmrg pSAREAPriv->crtc2_base = Base; 1083209ff23fSmrg 1084209ff23fSmrg if (pSAREAPriv->pfCurrentPage == 1) { 1085b7e1c893Smrg Base += info->dri->backOffset - info->dri->frontOffset; 1086209ff23fSmrg } 1087209ff23fSmrg } 1088209ff23fSmrg#endif 1089209ff23fSmrg save->crtc2_offset = Base; 1090209ff23fSmrg 1091209ff23fSmrg} 1092209ff23fSmrg 1093209ff23fSmrg 1094209ff23fSmrg/* Define CRTC2 registers for requested video mode */ 1095209ff23fSmrgstatic Bool 1096209ff23fSmrgRADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save, 1097209ff23fSmrg DisplayModePtr mode) 1098209ff23fSmrg{ 1099209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 1100209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1101209ff23fSmrg int format; 1102209ff23fSmrg int hsync_start; 1103209ff23fSmrg int hsync_wid; 1104209ff23fSmrg int vsync_wid; 1105209ff23fSmrg 1106209ff23fSmrg switch (info->CurrentLayout.pixel_code) { 1107209ff23fSmrg case 4: format = 1; break; 1108209ff23fSmrg case 8: format = 2; break; 1109209ff23fSmrg case 15: format = 3; break; /* 555 */ 1110209ff23fSmrg case 16: format = 4; break; /* 565 */ 1111209ff23fSmrg case 24: format = 5; break; /* RGB */ 1112209ff23fSmrg case 32: format = 6; break; /* xRGB */ 1113209ff23fSmrg default: 1114209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1115209ff23fSmrg "Unsupported pixel depth (%d)\n", 1116209ff23fSmrg info->CurrentLayout.bitsPerPixel); 1117209ff23fSmrg return FALSE; 1118209ff23fSmrg } 1119209ff23fSmrg 1120209ff23fSmrg save->crtc2_h_total_disp = 1121209ff23fSmrg ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) 1122209ff23fSmrg | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); 1123209ff23fSmrg 1124209ff23fSmrg hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 1125209ff23fSmrg if (!hsync_wid) hsync_wid = 1; 1126209ff23fSmrg hsync_start = mode->CrtcHSyncStart - 8; 1127209ff23fSmrg 1128209ff23fSmrg save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) 1129209ff23fSmrg | ((hsync_wid & 0x3f) << 16) 1130209ff23fSmrg | ((mode->Flags & V_NHSYNC) 1131209ff23fSmrg ? RADEON_CRTC_H_SYNC_POL 1132209ff23fSmrg : 0)); 1133209ff23fSmrg 1134209ff23fSmrg /* This works for double scan mode. */ 1135209ff23fSmrg save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 1136209ff23fSmrg | ((mode->CrtcVDisplay - 1) << 16)); 1137209ff23fSmrg 1138209ff23fSmrg vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 1139209ff23fSmrg if (!vsync_wid) vsync_wid = 1; 1140209ff23fSmrg 1141209ff23fSmrg save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 1142209ff23fSmrg | ((vsync_wid & 0x1f) << 16) 1143209ff23fSmrg | ((mode->Flags & V_NVSYNC) 1144209ff23fSmrg ? RADEON_CRTC2_V_SYNC_POL 1145209ff23fSmrg : 0)); 1146209ff23fSmrg 1147209ff23fSmrg save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + 1148209ff23fSmrg ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); 1149209ff23fSmrg save->crtc2_pitch |= save->crtc2_pitch << 16; 1150209ff23fSmrg 1151209ff23fSmrg /* check to see if TV DAC is enabled for another crtc and keep it enabled */ 1152209ff23fSmrg if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON) 1153209ff23fSmrg save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; 1154209ff23fSmrg else 1155209ff23fSmrg save->crtc2_gen_cntl = 0; 1156209ff23fSmrg 1157c503f109Smrg save->crtc2_gen_cntl |= ((format << 8) 1158209ff23fSmrg | RADEON_CRTC2_VSYNC_DIS 1159209ff23fSmrg | RADEON_CRTC2_HSYNC_DIS 1160209ff23fSmrg | RADEON_CRTC2_DISP_DIS 1161209ff23fSmrg | ((mode->Flags & V_DBLSCAN) 1162209ff23fSmrg ? RADEON_CRTC2_DBL_SCAN_EN 1163209ff23fSmrg : 0) 1164209ff23fSmrg | ((mode->Flags & V_CSYNC) 1165209ff23fSmrg ? RADEON_CRTC2_CSYNC_EN 1166209ff23fSmrg : 0) 1167209ff23fSmrg | ((mode->Flags & V_INTERLACE) 1168209ff23fSmrg ? RADEON_CRTC2_INTERLACE_EN 1169209ff23fSmrg : 0)); 1170209ff23fSmrg 1171f1bc02b7Smrg /* 200M freezes on VT switch sometimes if CRTC is disabled */ 1172f1bc02b7Smrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 1173f1bc02b7Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) 1174f1bc02b7Smrg save->crtc2_gen_cntl |= RADEON_CRTC2_EN; 1175f1bc02b7Smrg 1176209ff23fSmrg save->disp2_merge_cntl = info->SavedReg->disp2_merge_cntl; 1177209ff23fSmrg save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); 1178209ff23fSmrg 1179209ff23fSmrg save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; 1180209ff23fSmrg save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; 1181209ff23fSmrg 1182209ff23fSmrg return TRUE; 1183209ff23fSmrg} 1184209ff23fSmrg 1185209ff23fSmrg 1186209ff23fSmrg/* Define PLL registers for requested video mode */ 1187209ff23fSmrgstatic void 118851b40f85SmrgRADEONInitPLLRegisters(xf86CrtcPtr crtc, RADEONSavePtr save, 1189209ff23fSmrg RADEONPLLPtr pll, DisplayModePtr mode, 1190209ff23fSmrg int flags) 1191209ff23fSmrg{ 119251b40f85Smrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 119351b40f85Smrg ScrnInfoPtr pScrn = crtc->scrn; 1194209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1195209ff23fSmrg uint32_t feedback_div = 0; 1196f1bc02b7Smrg uint32_t frac_fb_div = 0; 1197209ff23fSmrg uint32_t reference_div = 0; 1198209ff23fSmrg uint32_t post_divider = 0; 1199209ff23fSmrg uint32_t freq = 0; 1200209ff23fSmrg 1201209ff23fSmrg struct { 1202209ff23fSmrg int divider; 1203209ff23fSmrg int bitvalue; 1204209ff23fSmrg } *post_div, post_divs[] = { 1205209ff23fSmrg /* From RAGE 128 VR/RAGE 128 GL Register 1206209ff23fSmrg * Reference Manual (Technical Reference 1207209ff23fSmrg * Manual P/N RRG-G04100-C Rev. 0.04), page 1208209ff23fSmrg * 3-17 (PLL_DIV_[3:0]). 1209209ff23fSmrg */ 1210209ff23fSmrg { 1, 0 }, /* VCLK_SRC */ 1211209ff23fSmrg { 2, 1 }, /* VCLK_SRC/2 */ 1212209ff23fSmrg { 4, 2 }, /* VCLK_SRC/4 */ 1213209ff23fSmrg { 8, 3 }, /* VCLK_SRC/8 */ 1214209ff23fSmrg { 3, 4 }, /* VCLK_SRC/3 */ 1215209ff23fSmrg { 16, 5 }, /* VCLK_SRC/16 */ 1216209ff23fSmrg { 6, 6 }, /* VCLK_SRC/6 */ 1217209ff23fSmrg { 12, 7 }, /* VCLK_SRC/12 */ 1218209ff23fSmrg { 0, 0 } 1219209ff23fSmrg }; 1220209ff23fSmrg 1221209ff23fSmrg 1222209ff23fSmrg if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { 1223209ff23fSmrg save->ppll_ref_div = info->RefDivider; 1224209ff23fSmrg save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); 1225209ff23fSmrg save->htotal_cntl = 0; 1226209ff23fSmrg return; 1227209ff23fSmrg } 1228209ff23fSmrg 122951b40f85Smrg if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE)) 123051b40f85Smrg radeon_crtc->pll_algo = RADEON_PLL_NEW; 123151b40f85Smrg else 123251b40f85Smrg radeon_crtc->pll_algo = RADEON_PLL_OLD; 123351b40f85Smrg 123451b40f85Smrg RADEONComputePLL(crtc, pll, mode->Clock, &freq, 123551b40f85Smrg &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags); 1236209ff23fSmrg 1237209ff23fSmrg for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 1238209ff23fSmrg if (post_div->divider == post_divider) 1239209ff23fSmrg break; 1240209ff23fSmrg } 1241209ff23fSmrg 1242209ff23fSmrg if (!post_div->divider) { 1243209ff23fSmrg save->pll_output_freq = freq; 1244209ff23fSmrg post_div = &post_divs[0]; 1245209ff23fSmrg } 1246209ff23fSmrg 1247209ff23fSmrg save->dot_clock_freq = freq; 1248209ff23fSmrg save->feedback_div = feedback_div; 1249209ff23fSmrg save->reference_div = reference_div; 1250209ff23fSmrg save->post_div = post_divider; 1251209ff23fSmrg 1252209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1253209ff23fSmrg "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", 1254209ff23fSmrg (unsigned)save->dot_clock_freq, 1255209ff23fSmrg (unsigned)save->pll_output_freq, 1256209ff23fSmrg save->feedback_div, 1257209ff23fSmrg save->reference_div, 1258209ff23fSmrg save->post_div); 1259209ff23fSmrg 1260209ff23fSmrg save->ppll_ref_div = save->reference_div; 1261209ff23fSmrg 1262209ff23fSmrg#if defined(__powerpc__) 1263209ff23fSmrg /* apparently programming this otherwise causes a hang??? */ 12641764dec5Smacallan if ((info->MacModel == RADEON_MAC_IBOOK) || 12651764dec5Smacallan (info->MacModel == RADEON_MAC_MINI_INTERNAL)) 1266209ff23fSmrg save->ppll_div_3 = 0x000600ad; 1267209ff23fSmrg else 1268209ff23fSmrg#endif 1269209ff23fSmrg save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); 1270209ff23fSmrg 1271209ff23fSmrg save->htotal_cntl = mode->HTotal & 0x7; 1272209ff23fSmrg 1273209ff23fSmrg save->vclk_ecp_cntl = (info->SavedReg->vclk_ecp_cntl & 1274209ff23fSmrg ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; 1275209ff23fSmrg} 1276209ff23fSmrg 1277209ff23fSmrg/* Define PLL2 registers for requested video mode */ 1278209ff23fSmrgstatic void 127951b40f85SmrgRADEONInitPLL2Registers(xf86CrtcPtr crtc, RADEONSavePtr save, 1280209ff23fSmrg RADEONPLLPtr pll, DisplayModePtr mode, 1281209ff23fSmrg int flags) 1282209ff23fSmrg{ 128351b40f85Smrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 128451b40f85Smrg ScrnInfoPtr pScrn = crtc->scrn; 1285209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1286209ff23fSmrg uint32_t feedback_div = 0; 1287f1bc02b7Smrg uint32_t frac_fb_div = 0; 1288209ff23fSmrg uint32_t reference_div = 0; 1289209ff23fSmrg uint32_t post_divider = 0; 1290209ff23fSmrg uint32_t freq = 0; 1291209ff23fSmrg 1292209ff23fSmrg struct { 1293209ff23fSmrg int divider; 1294209ff23fSmrg int bitvalue; 1295209ff23fSmrg } *post_div, post_divs[] = { 1296209ff23fSmrg /* From RAGE 128 VR/RAGE 128 GL Register 1297209ff23fSmrg * Reference Manual (Technical Reference 1298209ff23fSmrg * Manual P/N RRG-G04100-C Rev. 0.04), page 1299209ff23fSmrg * 3-17 (PLL_DIV_[3:0]). 1300209ff23fSmrg */ 1301209ff23fSmrg { 1, 0 }, /* VCLK_SRC */ 1302209ff23fSmrg { 2, 1 }, /* VCLK_SRC/2 */ 1303209ff23fSmrg { 4, 2 }, /* VCLK_SRC/4 */ 1304209ff23fSmrg { 8, 3 }, /* VCLK_SRC/8 */ 1305209ff23fSmrg { 3, 4 }, /* VCLK_SRC/3 */ 1306209ff23fSmrg { 6, 6 }, /* VCLK_SRC/6 */ 1307209ff23fSmrg { 12, 7 }, /* VCLK_SRC/12 */ 1308209ff23fSmrg { 0, 0 } 1309209ff23fSmrg }; 1310209ff23fSmrg 1311209ff23fSmrg if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { 1312209ff23fSmrg save->p2pll_ref_div = info->RefDivider; 1313209ff23fSmrg save->p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16); 1314209ff23fSmrg save->htotal_cntl2 = 0; 1315209ff23fSmrg return; 1316209ff23fSmrg } 1317209ff23fSmrg 131851b40f85Smrg if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE)) 131951b40f85Smrg radeon_crtc->pll_algo = RADEON_PLL_NEW; 132051b40f85Smrg else 132151b40f85Smrg radeon_crtc->pll_algo = RADEON_PLL_OLD; 132251b40f85Smrg 132351b40f85Smrg RADEONComputePLL(crtc, pll, mode->Clock, &freq, 132451b40f85Smrg &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags); 1325209ff23fSmrg 1326209ff23fSmrg for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 1327209ff23fSmrg if (post_div->divider == post_divider) 1328209ff23fSmrg break; 1329209ff23fSmrg } 1330209ff23fSmrg 1331209ff23fSmrg if (!post_div->divider) { 1332209ff23fSmrg save->pll_output_freq_2 = freq; 1333209ff23fSmrg post_div = &post_divs[0]; 1334209ff23fSmrg } 1335209ff23fSmrg 1336209ff23fSmrg save->dot_clock_freq_2 = freq; 1337209ff23fSmrg save->feedback_div_2 = feedback_div; 1338209ff23fSmrg save->reference_div_2 = reference_div; 1339209ff23fSmrg save->post_div_2 = post_divider; 1340209ff23fSmrg 1341209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1342209ff23fSmrg "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", 1343209ff23fSmrg (unsigned)save->dot_clock_freq_2, 1344209ff23fSmrg (unsigned)save->pll_output_freq_2, 1345209ff23fSmrg save->feedback_div_2, 1346209ff23fSmrg save->reference_div_2, 1347209ff23fSmrg save->post_div_2); 1348209ff23fSmrg 1349209ff23fSmrg save->p2pll_ref_div = save->reference_div_2; 1350209ff23fSmrg 1351209ff23fSmrg save->p2pll_div_0 = (save->feedback_div_2 | 1352209ff23fSmrg (post_div->bitvalue << 16)); 1353209ff23fSmrg 1354209ff23fSmrg save->htotal_cntl2 = mode->HTotal & 0x7; 1355209ff23fSmrg 1356209ff23fSmrg save->pixclks_cntl = ((info->SavedReg->pixclks_cntl & 1357209ff23fSmrg ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | 1358209ff23fSmrg RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); 1359209ff23fSmrg} 1360209ff23fSmrg 1361209ff23fSmrgstatic void 1362209ff23fSmrgradeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore) 1363209ff23fSmrg{ 1364209ff23fSmrg /* pixclks_cntl controls tv clock routing */ 1365209ff23fSmrg OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); 1366209ff23fSmrg} 1367209ff23fSmrg 1368209ff23fSmrg/* Calculate display buffer watermark to prevent buffer underflow */ 1369b7e1c893Smrgvoid 1370b7e1c893SmrgRADEONInitDispBandwidthLegacy(ScrnInfoPtr pScrn, 1371b7e1c893Smrg DisplayModePtr mode1, int pixel_bytes1, 1372b7e1c893Smrg DisplayModePtr mode2, int pixel_bytes2) 1373209ff23fSmrg{ 1374b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 1375209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1376209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1377209ff23fSmrg 1378209ff23fSmrg uint32_t temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; 1379209ff23fSmrg float mem_tcas; 1380209ff23fSmrg int k1, c; 1381209ff23fSmrg 1382f1bc02b7Smrg float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0.0}; 1383f1bc02b7Smrg float MemTcas_rs480[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 3.5}; 1384209ff23fSmrg float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 1385209ff23fSmrg float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; 1386f1bc02b7Smrg float MemTrbs_r4xx[8] = {4, 5, 6, 7, 8, 9, 10, 11}; 1387209ff23fSmrg 1388209ff23fSmrg float mem_bw, peak_disp_bw; 1389209ff23fSmrg float min_mem_eff = 0.8; 1390209ff23fSmrg float sclk_eff, sclk_delay; 1391209ff23fSmrg float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; 1392b7e1c893Smrg float disp_latency, disp_latency_overhead, disp_drain_rate = 0, disp_drain_rate2; 1393209ff23fSmrg float pix_clk, pix_clk2; /* in MHz */ 1394209ff23fSmrg int cur_size = 16; /* in octawords */ 1395b7e1c893Smrg int critical_point = 0, critical_point2; 1396209ff23fSmrg int stop_req, max_stop_req; 1397209ff23fSmrg float read_return_rate, time_disp1_drop_priority; 1398209ff23fSmrg 1399209ff23fSmrg /* 1400209ff23fSmrg * Set display0/1 priority up on r3/4xx in the memory controller for 1401209ff23fSmrg * high res modes if the user specifies HIGH for displaypriority 1402209ff23fSmrg * option. 1403209ff23fSmrg */ 1404209ff23fSmrg if ((info->DispPriority == 2) && IS_R300_VARIANT) { 1405209ff23fSmrg uint32_t mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); 1406b7e1c893Smrg mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); 1407b7e1c893Smrg mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); 1408b7e1c893Smrg if (pRADEONEnt->pCrtc[1]->enabled) 1409b7e1c893Smrg mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); /* display 1 */ 1410b7e1c893Smrg if (pRADEONEnt->pCrtc[0]->enabled) 1411b7e1c893Smrg mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); /* display 0 */ 1412209ff23fSmrg OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); 1413209ff23fSmrg } 1414209ff23fSmrg 1415209ff23fSmrg /* 1416209ff23fSmrg * Determine if there is enough bandwidth for current display mode 1417209ff23fSmrg */ 1418209ff23fSmrg mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); 1419209ff23fSmrg 1420b7e1c893Smrg pix_clk = 0; 1421b7e1c893Smrg pix_clk2 = 0; 1422b7e1c893Smrg peak_disp_bw = 0; 1423b7e1c893Smrg if (mode1) { 1424b7e1c893Smrg pix_clk = mode1->Clock/1000.0; 1425b7e1c893Smrg peak_disp_bw += (pix_clk * pixel_bytes1); 1426b7e1c893Smrg } 1427b7e1c893Smrg if (mode2) { 1428209ff23fSmrg pix_clk2 = mode2->Clock/1000.0; 1429b7e1c893Smrg peak_disp_bw += (pix_clk2 * pixel_bytes2); 1430b7e1c893Smrg } 1431209ff23fSmrg 1432209ff23fSmrg if (peak_disp_bw >= mem_bw * min_mem_eff) { 1433209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1434209ff23fSmrg "You may not have enough display bandwidth for current mode\n" 1435209ff23fSmrg "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); 1436209ff23fSmrg } 1437209ff23fSmrg 1438209ff23fSmrg /* Get values from the EXT_MEM_CNTL register...converting its contents. */ 1439209ff23fSmrg temp = INREG(RADEON_MEM_TIMING_CNTL); 1440209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ 1441f1bc02b7Smrg mem_trcd = ((temp >> 2) & 0x3) + 1; 1442f1bc02b7Smrg mem_trp = ((temp & 0x3)) + 1; 1443f1bc02b7Smrg mem_tras = ((temp & 0x70) >> 4) + 1; 1444f1bc02b7Smrg } else if (info->ChipFamily == CHIP_FAMILY_R300 || 1445f1bc02b7Smrg info->ChipFamily == CHIP_FAMILY_R350) { /* r300, r350 */ 1446f1bc02b7Smrg mem_trcd = (temp & 0x7) + 1; 1447f1bc02b7Smrg mem_trp = ((temp >> 8) & 0x7) + 1; 1448f1bc02b7Smrg mem_tras = ((temp >> 11) & 0xf) + 4; 1449f1bc02b7Smrg } else if (info->ChipFamily == CHIP_FAMILY_RV350 || 1450f1bc02b7Smrg info->ChipFamily <= CHIP_FAMILY_RV380) { 1451f1bc02b7Smrg /* rv3x0 */ 1452f1bc02b7Smrg mem_trcd = (temp & 0x7) + 3; 1453f1bc02b7Smrg mem_trp = ((temp >> 8) & 0x7) + 3; 1454f1bc02b7Smrg mem_tras = ((temp >> 11) & 0xf) + 6; 1455f1bc02b7Smrg } else if (info->ChipFamily == CHIP_FAMILY_R420 || 1456f1bc02b7Smrg info->ChipFamily == CHIP_FAMILY_RV410) { 1457f1bc02b7Smrg /* r4xx */ 1458f1bc02b7Smrg mem_trcd = (temp & 0xf) + 3; 1459f1bc02b7Smrg if (mem_trcd > 15) 1460f1bc02b7Smrg mem_trcd = 15; 1461f1bc02b7Smrg mem_trp = ((temp >> 8) & 0xf) + 3; 1462f1bc02b7Smrg if (mem_trp > 15) 1463f1bc02b7Smrg mem_trp = 15; 1464f1bc02b7Smrg mem_tras = ((temp >> 12) & 0x1f) + 6; 1465f1bc02b7Smrg if (mem_tras > 31) 1466f1bc02b7Smrg mem_tras = 31; 1467f1bc02b7Smrg } else { /* RV200, R200 */ 1468f1bc02b7Smrg mem_trcd = (temp & 0x7) + 1; 1469f1bc02b7Smrg mem_trp = ((temp >> 8) & 0x7) + 1; 1470f1bc02b7Smrg mem_tras = ((temp >> 12) & 0xf) + 4; 1471209ff23fSmrg } 1472209ff23fSmrg 1473209ff23fSmrg /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ 1474209ff23fSmrg temp = INREG(RADEON_MEM_SDRAM_MODE_REG); 1475209ff23fSmrg data = (temp & (7<<20)) >> 20; 1476209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ 1477f1bc02b7Smrg if (info->ChipFamily == CHIP_FAMILY_RS480) /* don't think rs400 */ 1478f1bc02b7Smrg mem_tcas = MemTcas_rs480[data]; 1479f1bc02b7Smrg else 1480f1bc02b7Smrg mem_tcas = MemTcas[data]; 1481209ff23fSmrg } else { 1482209ff23fSmrg mem_tcas = MemTcas2 [data]; 1483209ff23fSmrg } 1484f1bc02b7Smrg if (info->ChipFamily == CHIP_FAMILY_RS400 || 1485f1bc02b7Smrg info->ChipFamily == CHIP_FAMILY_RS480) { 1486f1bc02b7Smrg /* extra cas latency stored in bits 23-25 0-4 clocks */ 1487f1bc02b7Smrg data = (temp >> 23) & 0x7; 1488f1bc02b7Smrg if (data < 5) 1489f1bc02b7Smrg mem_tcas += data; 1490f1bc02b7Smrg } 1491209ff23fSmrg 1492f1bc02b7Smrg if (IS_R300_VARIANT && !info->IsIGP) { 1493209ff23fSmrg /* on the R300, Tcas is included in Trbs. 1494b7e1c893Smrg */ 1495209ff23fSmrg temp = INREG(RADEON_MEM_CNTL); 1496209ff23fSmrg data = (R300_MEM_NUM_CHANNELS_MASK & temp); 1497209ff23fSmrg if (data == 1) { 1498209ff23fSmrg if (R300_MEM_USE_CD_CH_ONLY & temp) { 1499209ff23fSmrg temp = INREG(R300_MC_IND_INDEX); 1500209ff23fSmrg temp &= ~R300_MC_IND_ADDR_MASK; 1501209ff23fSmrg temp |= R300_MC_READ_CNTL_CD_mcind; 1502209ff23fSmrg OUTREG(R300_MC_IND_INDEX, temp); 1503209ff23fSmrg temp = INREG(R300_MC_IND_DATA); 1504209ff23fSmrg data = (R300_MEM_RBS_POSITION_C_MASK & temp); 1505209ff23fSmrg } else { 1506209ff23fSmrg temp = INREG(R300_MC_READ_CNTL_AB); 1507209ff23fSmrg data = (R300_MEM_RBS_POSITION_A_MASK & temp); 1508209ff23fSmrg } 1509209ff23fSmrg } else { 1510209ff23fSmrg temp = INREG(R300_MC_READ_CNTL_AB); 1511209ff23fSmrg data = (R300_MEM_RBS_POSITION_A_MASK & temp); 1512209ff23fSmrg } 1513209ff23fSmrg 1514f1bc02b7Smrg if (info->ChipFamily == CHIP_FAMILY_RV410 || 1515f1bc02b7Smrg info->ChipFamily == CHIP_FAMILY_R420) 1516f1bc02b7Smrg mem_trbs = MemTrbs_r4xx[data]; 1517f1bc02b7Smrg else 1518f1bc02b7Smrg mem_trbs = MemTrbs[data]; 1519209ff23fSmrg mem_tcas += mem_trbs; 1520209ff23fSmrg } 1521209ff23fSmrg 1522209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ 1523209ff23fSmrg /* DDR64 SCLK_EFF = SCLK for analysis */ 1524209ff23fSmrg sclk_eff = info->sclk; 1525209ff23fSmrg } else { 1526209ff23fSmrg#ifdef XF86DRI 1527209ff23fSmrg if (info->directRenderingEnabled) 1528b7e1c893Smrg sclk_eff = info->sclk - (info->dri->agpMode * 50.0 / 3.0); 1529209ff23fSmrg else 1530209ff23fSmrg#endif 1531209ff23fSmrg sclk_eff = info->sclk; 1532209ff23fSmrg } 1533209ff23fSmrg 1534b7e1c893Smrg /* 1535b7e1c893Smrg Find the memory controller latency for the display client. 1536209ff23fSmrg */ 1537209ff23fSmrg if (IS_R300_VARIANT) { 1538209ff23fSmrg /*not enough for R350 ???*/ 1539209ff23fSmrg /* 1540209ff23fSmrg if (!mode2) sclk_delay = 150; 1541209ff23fSmrg else { 1542209ff23fSmrg if (info->RamWidth == 256) sclk_delay = 87; 1543209ff23fSmrg else sclk_delay = 97; 1544209ff23fSmrg } 1545209ff23fSmrg */ 1546209ff23fSmrg sclk_delay = 250; 1547209ff23fSmrg } else { 1548209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RV100) || 1549209ff23fSmrg info->IsIGP) { 1550209ff23fSmrg if (info->IsDDR) sclk_delay = 41; 1551209ff23fSmrg else sclk_delay = 33; 1552209ff23fSmrg } else { 1553209ff23fSmrg if (info->RamWidth == 128) sclk_delay = 57; 1554209ff23fSmrg else sclk_delay = 41; 1555209ff23fSmrg } 1556209ff23fSmrg } 1557209ff23fSmrg 1558209ff23fSmrg mc_latency_sclk = sclk_delay / sclk_eff; 1559209ff23fSmrg 1560209ff23fSmrg if (info->IsDDR) { 1561209ff23fSmrg if (info->RamWidth == 32) { 1562209ff23fSmrg k1 = 40; 1563209ff23fSmrg c = 3; 1564209ff23fSmrg } else { 1565209ff23fSmrg k1 = 20; 1566209ff23fSmrg c = 1; 1567209ff23fSmrg } 1568209ff23fSmrg } else { 1569209ff23fSmrg k1 = 40; 1570209ff23fSmrg c = 3; 1571209ff23fSmrg } 1572209ff23fSmrg mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / 1573209ff23fSmrg info->mclk) + (4.0 / sclk_eff); 1574209ff23fSmrg 1575209ff23fSmrg /* 1576209ff23fSmrg HW cursor time assuming worst case of full size colour cursor. 1577209ff23fSmrg */ 1578209ff23fSmrg cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; 1579209ff23fSmrg cur_latency_sclk = cur_size / sclk_eff; 1580209ff23fSmrg 1581209ff23fSmrg /* 1582209ff23fSmrg Find the total latency for the display data. 1583209ff23fSmrg */ 1584209ff23fSmrg disp_latency_overhead = 8.0 / info->sclk; 1585209ff23fSmrg mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; 1586209ff23fSmrg mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; 1587209ff23fSmrg disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); 1588209ff23fSmrg 1589b7e1c893Smrg /* setup Max GRPH_STOP_REQ default value */ 1590b7e1c893Smrg if (IS_RV100_VARIANT) 1591b7e1c893Smrg max_stop_req = 0x5c; 1592209ff23fSmrg else 1593b7e1c893Smrg max_stop_req = 0x7c; 1594209ff23fSmrg 1595b7e1c893Smrg if (mode1) { 1596b7e1c893Smrg /* CRTC1 1597b7e1c893Smrg Set GRPH_BUFFER_CNTL register using h/w defined optimal values. 1598b7e1c893Smrg GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] 1599b7e1c893Smrg */ 1600b7e1c893Smrg stop_req = mode1->HDisplay * pixel_bytes1 / 16; 1601209ff23fSmrg 1602b7e1c893Smrg if (stop_req > max_stop_req) 1603b7e1c893Smrg stop_req = max_stop_req; 1604209ff23fSmrg 1605b7e1c893Smrg /* 1606b7e1c893Smrg Find the drain rate of the display buffer. 1607b7e1c893Smrg */ 1608b7e1c893Smrg disp_drain_rate = pix_clk / (16.0/pixel_bytes1); 1609209ff23fSmrg 1610b7e1c893Smrg /* 1611b7e1c893Smrg Find the critical point of the display buffer. 1612b7e1c893Smrg */ 1613b7e1c893Smrg critical_point= (uint32_t)(disp_drain_rate * disp_latency + 0.5); 1614209ff23fSmrg 1615b7e1c893Smrg /* ???? */ 1616b7e1c893Smrg /* 1617b7e1c893Smrg temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; 1618b7e1c893Smrg if (critical_point < temp) critical_point = temp; 1619b7e1c893Smrg */ 1620b7e1c893Smrg if (info->DispPriority == 2) { 1621b7e1c893Smrg critical_point = 0; 1622b7e1c893Smrg } 1623209ff23fSmrg 1624b7e1c893Smrg /* 1625b7e1c893Smrg The critical point should never be above max_stop_req-4. Setting 1626b7e1c893Smrg GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. 1627b7e1c893Smrg */ 1628b7e1c893Smrg if (max_stop_req - critical_point < 4) critical_point = 0; 1629b7e1c893Smrg 1630b7e1c893Smrg if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) { 1631b7e1c893Smrg /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ 1632b7e1c893Smrg critical_point = 0x10; 1633b7e1c893Smrg } 1634b7e1c893Smrg 1635b7e1c893Smrg temp = info->SavedReg->grph_buffer_cntl; 1636b7e1c893Smrg temp &= ~(RADEON_GRPH_STOP_REQ_MASK); 1637b7e1c893Smrg temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 1638b7e1c893Smrg temp &= ~(RADEON_GRPH_START_REQ_MASK); 1639b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_R350) && 1640b7e1c893Smrg (stop_req > 0x15)) { 1641b7e1c893Smrg stop_req -= 0x10; 1642b7e1c893Smrg } 1643b7e1c893Smrg temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 1644b7e1c893Smrg 1645b7e1c893Smrg temp |= RADEON_GRPH_BUFFER_SIZE; 1646b7e1c893Smrg temp &= ~(RADEON_GRPH_CRITICAL_CNTL | 1647b7e1c893Smrg RADEON_GRPH_CRITICAL_AT_SOF | 1648b7e1c893Smrg RADEON_GRPH_STOP_CNTL); 1649b7e1c893Smrg /* 1650b7e1c893Smrg Write the result into the register. 1651b7e1c893Smrg */ 1652b7e1c893Smrg OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 1653b7e1c893Smrg (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 1654209ff23fSmrg 1655209ff23fSmrg#if 0 1656b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 1657b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 1658b7e1c893Smrg /* attempt to program RS400 disp regs correctly ??? */ 1659b7e1c893Smrg temp = info->SavedReg->disp1_req_cntl1; 1660b7e1c893Smrg temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | 1661b7e1c893Smrg RS400_DISP1_STOP_REQ_LEVEL_MASK); 1662b7e1c893Smrg OUTREG(RS400_DISP1_REQ_CNTL1, (temp | 1663b7e1c893Smrg (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 1664b7e1c893Smrg (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 1665b7e1c893Smrg temp = info->SavedReg->dmif_mem_cntl1; 1666b7e1c893Smrg temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | 1667b7e1c893Smrg RS400_DISP1_CRITICAL_POINT_STOP_MASK); 1668b7e1c893Smrg OUTREG(RS400_DMIF_MEM_CNTL1, (temp | 1669b7e1c893Smrg (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | 1670b7e1c893Smrg (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); 1671b7e1c893Smrg } 1672209ff23fSmrg#endif 1673209ff23fSmrg 1674b7e1c893Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1675b7e1c893Smrg "GRPH_BUFFER_CNTL from %x to %x\n", 1676b7e1c893Smrg (unsigned int)info->SavedReg->grph_buffer_cntl, 1677b7e1c893Smrg (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL)); 1678b7e1c893Smrg } 1679209ff23fSmrg 1680209ff23fSmrg if (mode2) { 1681209ff23fSmrg stop_req = mode2->HDisplay * pixel_bytes2 / 16; 1682209ff23fSmrg 1683209ff23fSmrg if (stop_req > max_stop_req) stop_req = max_stop_req; 1684209ff23fSmrg 1685b7e1c893Smrg /* 1686b7e1c893Smrg Find the drain rate of the display buffer. 1687b7e1c893Smrg */ 1688b7e1c893Smrg disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2); 1689b7e1c893Smrg 1690209ff23fSmrg temp = info->SavedReg->grph2_buffer_cntl; 1691209ff23fSmrg temp &= ~(RADEON_GRPH_STOP_REQ_MASK); 1692209ff23fSmrg temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 1693209ff23fSmrg temp &= ~(RADEON_GRPH_START_REQ_MASK); 1694209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_R350) && 1695209ff23fSmrg (stop_req > 0x15)) { 1696209ff23fSmrg stop_req -= 0x10; 1697209ff23fSmrg } 1698209ff23fSmrg temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 1699209ff23fSmrg temp |= RADEON_GRPH_BUFFER_SIZE; 1700209ff23fSmrg temp &= ~(RADEON_GRPH_CRITICAL_CNTL | 1701209ff23fSmrg RADEON_GRPH_CRITICAL_AT_SOF | 1702209ff23fSmrg RADEON_GRPH_STOP_CNTL); 1703209ff23fSmrg 1704209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS100) || 1705209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS200)) 1706209ff23fSmrg critical_point2 = 0; 1707209ff23fSmrg else { 1708209ff23fSmrg read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); 1709b7e1c893Smrg if (mode1) 1710b7e1c893Smrg time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); 1711b7e1c893Smrg else 1712b7e1c893Smrg time_disp1_drop_priority = 0; 1713209ff23fSmrg 1714209ff23fSmrg critical_point2 = (uint32_t)((disp_latency + time_disp1_drop_priority + 1715209ff23fSmrg disp_latency) * disp_drain_rate2 + 0.5); 1716209ff23fSmrg 1717209ff23fSmrg if (info->DispPriority == 2) { 1718209ff23fSmrg critical_point2 = 0; 1719209ff23fSmrg } 1720209ff23fSmrg 1721209ff23fSmrg if (max_stop_req - critical_point2 < 4) critical_point2 = 0; 1722209ff23fSmrg 1723209ff23fSmrg } 1724209ff23fSmrg 1725209ff23fSmrg if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) { 1726209ff23fSmrg /* some R300 cards have problem with this set to 0 */ 1727209ff23fSmrg critical_point2 = 0x10; 1728209ff23fSmrg } 1729209ff23fSmrg 1730209ff23fSmrg OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 1731209ff23fSmrg (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 1732209ff23fSmrg 1733209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 1734209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 1735209ff23fSmrg#if 0 1736209ff23fSmrg /* attempt to program RS400 disp2 regs correctly ??? */ 1737209ff23fSmrg temp = info->SavedReg->disp2_req_cntl1; 1738209ff23fSmrg temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | 1739209ff23fSmrg RS400_DISP2_STOP_REQ_LEVEL_MASK); 1740209ff23fSmrg OUTREG(RS400_DISP2_REQ_CNTL1, (temp | 1741209ff23fSmrg (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 1742209ff23fSmrg (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 1743209ff23fSmrg temp = info->SavedReg->disp2_req_cntl2; 1744209ff23fSmrg temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | 1745209ff23fSmrg RS400_DISP2_CRITICAL_POINT_STOP_MASK); 1746209ff23fSmrg OUTREG(RS400_DISP2_REQ_CNTL2, (temp | 1747209ff23fSmrg (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | 1748209ff23fSmrg (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); 1749209ff23fSmrg#endif 1750209ff23fSmrg OUTREG(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); 1751209ff23fSmrg OUTREG(RS400_DISP2_REQ_CNTL2, 0x2749D000); 1752209ff23fSmrg OUTREG(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); 1753209ff23fSmrg OUTREG(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); 1754209ff23fSmrg } 1755209ff23fSmrg 1756209ff23fSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1757209ff23fSmrg "GRPH2_BUFFER_CNTL from %x to %x\n", 1758209ff23fSmrg (unsigned int)info->SavedReg->grph2_buffer_cntl, 1759209ff23fSmrg (unsigned int)INREG(RADEON_GRPH2_BUFFER_CNTL)); 1760209ff23fSmrg } 1761209ff23fSmrg} 1762209ff23fSmrg 1763209ff23fSmrgvoid 1764209ff23fSmrglegacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, 1765209ff23fSmrg DisplayModePtr adjusted_mode, int x, int y) 1766209ff23fSmrg{ 1767209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 1768209ff23fSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1769209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 1770209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1771209ff23fSmrg int i = 0; 1772209ff23fSmrg double dot_clock = 0; 1773b7e1c893Smrg int pll_flags = RADEON_PLL_LEGACY; 1774209ff23fSmrg Bool update_tv_routing = FALSE; 1775209ff23fSmrg Bool tilingChanged = FALSE; 1776209ff23fSmrg 1777b7e1c893Smrg if (adjusted_mode->Clock > 200000) /* range limits??? */ 1778b7e1c893Smrg pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; 1779b7e1c893Smrg else 1780b7e1c893Smrg pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; 1781b7e1c893Smrg 1782209ff23fSmrg if (info->allowColorTiling) { 1783209ff23fSmrg radeon_crtc->can_tile = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; 1784209ff23fSmrg tilingChanged = RADEONSetTiling(pScrn); 1785209ff23fSmrg } 1786209ff23fSmrg 1787209ff23fSmrg for (i = 0; i < xf86_config->num_output; i++) { 1788209ff23fSmrg xf86OutputPtr output = xf86_config->output[i]; 1789209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1790209ff23fSmrg 1791209ff23fSmrg if (output->crtc == crtc) { 1792b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | 1793b7e1c893Smrg ATOM_DEVICE_DFP_SUPPORT)) 1794209ff23fSmrg pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; 1795b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 1796209ff23fSmrg pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV); 1797209ff23fSmrg } 1798209ff23fSmrg } 1799209ff23fSmrg 1800209ff23fSmrg 1801209ff23fSmrg ErrorF("init memmap\n"); 1802209ff23fSmrg RADEONInitMemMapRegisters(pScrn, info->ModeReg, info); 1803209ff23fSmrg ErrorF("init common\n"); 1804209ff23fSmrg RADEONInitCommonRegisters(info->ModeReg, info); 1805209ff23fSmrg 1806209ff23fSmrg RADEONInitSurfaceCntl(crtc, info->ModeReg); 1807209ff23fSmrg 1808209ff23fSmrg switch (radeon_crtc->crtc_id) { 1809209ff23fSmrg case 0: 1810209ff23fSmrg ErrorF("init crtc1\n"); 1811209ff23fSmrg RADEONInitCrtcRegisters(crtc, info->ModeReg, adjusted_mode); 1812209ff23fSmrg RADEONInitCrtcBase(crtc, info->ModeReg, x, y); 1813209ff23fSmrg dot_clock = adjusted_mode->Clock / 1000.0; 1814209ff23fSmrg if (dot_clock) { 1815209ff23fSmrg ErrorF("init pll1\n"); 181651b40f85Smrg RADEONInitPLLRegisters(crtc, info->ModeReg, &info->pll, adjusted_mode, pll_flags); 1817209ff23fSmrg } else { 1818209ff23fSmrg info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div; 1819209ff23fSmrg info->ModeReg->ppll_div_3 = info->SavedReg->ppll_div_3; 1820209ff23fSmrg info->ModeReg->htotal_cntl = info->SavedReg->htotal_cntl; 1821209ff23fSmrg } 1822209ff23fSmrg break; 1823209ff23fSmrg case 1: 1824209ff23fSmrg ErrorF("init crtc2\n"); 1825209ff23fSmrg RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode); 1826209ff23fSmrg RADEONInitCrtc2Base(crtc, info->ModeReg, x, y); 1827209ff23fSmrg dot_clock = adjusted_mode->Clock / 1000.0; 1828209ff23fSmrg if (dot_clock) { 1829209ff23fSmrg ErrorF("init pll2\n"); 183051b40f85Smrg RADEONInitPLL2Registers(crtc, info->ModeReg, &info->pll, adjusted_mode, pll_flags); 1831209ff23fSmrg } 1832209ff23fSmrg break; 1833209ff23fSmrg } 1834209ff23fSmrg 1835209ff23fSmrg for (i = 0; i < xf86_config->num_output; i++) { 1836209ff23fSmrg xf86OutputPtr output = xf86_config->output[i]; 1837209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1838209ff23fSmrg 1839209ff23fSmrg if (output->crtc == crtc) { 1840b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 1841209ff23fSmrg switch (radeon_crtc->crtc_id) { 1842209ff23fSmrg case 0: 1843209ff23fSmrg RADEONAdjustCrtcRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); 1844209ff23fSmrg RADEONAdjustPLLRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); 1845209ff23fSmrg update_tv_routing = TRUE; 1846209ff23fSmrg break; 1847209ff23fSmrg case 1: 1848209ff23fSmrg RADEONAdjustCrtc2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); 1849209ff23fSmrg RADEONAdjustPLL2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); 1850209ff23fSmrg break; 1851209ff23fSmrg } 1852209ff23fSmrg } 1853209ff23fSmrg } 1854209ff23fSmrg } 1855209ff23fSmrg 1856209ff23fSmrg ErrorF("restore memmap\n"); 1857209ff23fSmrg RADEONRestoreMemMapRegisters(pScrn, info->ModeReg); 1858209ff23fSmrg ErrorF("restore common\n"); 1859209ff23fSmrg RADEONRestoreCommonRegisters(pScrn, info->ModeReg); 1860209ff23fSmrg 1861209ff23fSmrg switch (radeon_crtc->crtc_id) { 1862209ff23fSmrg case 0: 1863209ff23fSmrg ErrorF("restore crtc1\n"); 1864209ff23fSmrg RADEONRestoreCrtcRegisters(pScrn, info->ModeReg); 1865209ff23fSmrg ErrorF("restore pll1\n"); 1866209ff23fSmrg RADEONRestorePLLRegisters(pScrn, info->ModeReg); 1867209ff23fSmrg break; 1868209ff23fSmrg case 1: 1869209ff23fSmrg ErrorF("restore crtc2\n"); 1870209ff23fSmrg RADEONRestoreCrtc2Registers(pScrn, info->ModeReg); 1871209ff23fSmrg ErrorF("restore pll2\n"); 1872209ff23fSmrg RADEONRestorePLL2Registers(pScrn, info->ModeReg); 1873209ff23fSmrg break; 1874209ff23fSmrg } 1875209ff23fSmrg 1876209ff23fSmrg /* pixclks_cntl handles tv-out clock routing */ 1877209ff23fSmrg if (update_tv_routing) 1878209ff23fSmrg radeon_update_tv_routing(pScrn, info->ModeReg); 1879209ff23fSmrg 1880209ff23fSmrg if (info->DispPriority) 1881b7e1c893Smrg RADEONInitDispBandwidth(pScrn); 1882b7e1c893Smrg 1883b7e1c893Smrg radeon_crtc->initialized = TRUE; 1884209ff23fSmrg 1885209ff23fSmrg if (tilingChanged) { 1886209ff23fSmrg /* need to redraw front buffer, I guess this can be considered a hack ? */ 1887209ff23fSmrg /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ 1888209ff23fSmrg if (pScrn->pScreen) 1889c135ecebSveego xf86EnableDisableFBAccess(XF86_ENABLEDISABLEFB_ARG(pScrn), FALSE); 1890209ff23fSmrg RADEONChangeSurfaces(pScrn); 1891209ff23fSmrg if (pScrn->pScreen) 1892c135ecebSveego xf86EnableDisableFBAccess(XF86_ENABLEDISABLEFB_ARG(pScrn), TRUE); 1893209ff23fSmrg /* xf86SetRootClip would do, but can't access that here */ 1894209ff23fSmrg } 1895209ff23fSmrg 1896209ff23fSmrg /* reset ecp_div for Xv */ 1897209ff23fSmrg info->ecp_div = -1; 1898209ff23fSmrg 1899209ff23fSmrg} 1900209ff23fSmrg 1901