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