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" 48209ff23fSmrg#include "radeon_tv.h" 49209ff23fSmrg#include "radeon_atombios.h" 50209ff23fSmrg 51b7e1c893Smrg#include "ati_pciids_gen.h" 52b7e1c893Smrg 53209ff23fSmrgstatic RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn); 54209ff23fSmrgstatic RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color); 55209ff23fSmrgstatic RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color); 56209ff23fSmrgstatic RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn); 57209ff23fSmrg 58b7e1c893Smrgextern Bool 59b7e1c893SmrgRADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, RADEONI2CBusPtr pRADEONI2CBus); 60b7e1c893Smrg 61b7e1c893Smrgstatic const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = 62b7e1c893Smrg{ 63b7e1c893Smrg {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ 64b7e1c893Smrg {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ 65b7e1c893Smrg {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ 66b7e1c893Smrg {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ 67b7e1c893Smrg {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ 68b7e1c893Smrg {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ 69b7e1c893Smrg {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ 70b7e1c893Smrg {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ 71b7e1c893Smrg {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ 72b7e1c893Smrg {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ 73b7e1c893Smrg {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ 74b7e1c893Smrg {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ 75b7e1c893Smrg {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ 76b7e1c893Smrg {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ 77b7e1c893Smrg {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ 78b7e1c893Smrg {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ 79b7e1c893Smrg {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ 80b7e1c893Smrg {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ 81b7e1c893Smrg {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS480*/ /* FIXME: just values from rv380 used... */ 82b7e1c893Smrg}; 83b7e1c893Smrg 84b7e1c893Smrgstatic const uint32_t default_tvdac_adj [CHIP_FAMILY_LAST] = 85b7e1c893Smrg{ 86b7e1c893Smrg 0x00000000, /* unknown */ 87b7e1c893Smrg 0x00000000, /* legacy */ 88b7e1c893Smrg 0x00000000, /* r100 */ 89b7e1c893Smrg 0x00280000, /* rv100 */ 90b7e1c893Smrg 0x00000000, /* rs100 */ 91b7e1c893Smrg 0x00880000, /* rv200 */ 92b7e1c893Smrg 0x00000000, /* rs200 */ 93b7e1c893Smrg 0x00000000, /* r200 */ 94b7e1c893Smrg 0x00770000, /* rv250 */ 95b7e1c893Smrg 0x00290000, /* rs300 */ 96b7e1c893Smrg 0x00560000, /* rv280 */ 97b7e1c893Smrg 0x00780000, /* r300 */ 98b7e1c893Smrg 0x00770000, /* r350 */ 99b7e1c893Smrg 0x00780000, /* rv350 */ 100b7e1c893Smrg 0x00780000, /* rv380 */ 101b7e1c893Smrg 0x01080000, /* r420 */ 102b7e1c893Smrg 0x01080000, /* rv410 */ /* FIXME: just values from r420 used... */ 103b7e1c893Smrg 0x00780000, /* rs400 */ /* FIXME: just values from rv380 used... */ 104b7e1c893Smrg 0x00780000, /* rs480 */ /* FIXME: just values from rv380 used... */ 105b7e1c893Smrg}; 106b7e1c893Smrg 107b7e1c893Smrgvoid 108b7e1c893SmrgRADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn, radeon_tvdac_ptr tvdac) 109b7e1c893Smrg{ 110b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 111b7e1c893Smrg 112b7e1c893Smrg if (!RADEONGetDAC2InfoFromBIOS(pScrn, tvdac)) { 113b7e1c893Smrg tvdac->ps2_tvdac_adj = default_tvdac_adj[info->ChipFamily]; 114b7e1c893Smrg if (info->IsMobility) { /* some mobility chips may different */ 115b7e1c893Smrg if (info->ChipFamily == CHIP_FAMILY_RV250) 116b7e1c893Smrg tvdac->ps2_tvdac_adj = 0x00880000; 117b7e1c893Smrg } 118b7e1c893Smrg tvdac->pal_tvdac_adj = tvdac->ps2_tvdac_adj; 119b7e1c893Smrg tvdac->ntsc_tvdac_adj = tvdac->ps2_tvdac_adj; 120b7e1c893Smrg } 121b7e1c893Smrg} 122b7e1c893Smrg 123b7e1c893Smrgvoid 124b7e1c893SmrgRADEONGetTMDSInfoFromTable(ScrnInfoPtr pScrn, radeon_tmds_ptr tmds) 125b7e1c893Smrg{ 126b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 127b7e1c893Smrg int i; 128b7e1c893Smrg 129b7e1c893Smrg for (i = 0; i < 4; i++) { 130b7e1c893Smrg tmds->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; 131b7e1c893Smrg tmds->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; 132b7e1c893Smrg } 133b7e1c893Smrg} 134b7e1c893Smrg 135b7e1c893Smrgvoid 136b7e1c893SmrgRADEONGetTMDSInfo(ScrnInfoPtr pScrn, radeon_tmds_ptr tmds) 137b7e1c893Smrg{ 138b7e1c893Smrg int i; 139b7e1c893Smrg 140b7e1c893Smrg for (i = 0; i < 4; i++) { 141b7e1c893Smrg tmds->tmds_pll[i].value = 0; 142b7e1c893Smrg tmds->tmds_pll[i].freq = 0; 143b7e1c893Smrg } 144b7e1c893Smrg 145b7e1c893Smrg if (!RADEONGetTMDSInfoFromBIOS(pScrn, tmds)) 146b7e1c893Smrg RADEONGetTMDSInfoFromTable(pScrn, tmds); 147b7e1c893Smrg} 148b7e1c893Smrg 149b7e1c893Smrgvoid 150b7e1c893SmrgRADEONGetExtTMDSInfo(ScrnInfoPtr pScrn, radeon_dvo_ptr dvo) 151b7e1c893Smrg{ 152b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 153b7e1c893Smrg 154b7e1c893Smrg if (!info->IsAtomBios) { 155b7e1c893Smrg#if defined(__powerpc__) 156b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 157b7e1c893Smrg dvo->dvo_i2c_slave_addr = 0x70; 158b7e1c893Smrg#else 159b7e1c893Smrg if (!RADEONGetExtTMDSInfoFromBIOS(pScrn, dvo)) { 160b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); 161b7e1c893Smrg dvo->dvo_i2c_slave_addr = 0x70; 162b7e1c893Smrg } 163b7e1c893Smrg#endif 164c503f109Smrg if (RADEONI2CInit(pScrn, &dvo->pI2CBus, "DVO", &dvo->dvo_i2c)) { 165b7e1c893Smrg dvo->DVOChip = 166c503f109Smrg RADEONDVODeviceInit(dvo->pI2CBus, dvo->dvo_i2c_slave_addr); 167b7e1c893Smrg if (!dvo->DVOChip) 1682f39173dSmrg free(dvo->pI2CBus); 169b7e1c893Smrg } 170b7e1c893Smrg } 171b7e1c893Smrg} 172b7e1c893Smrg 173b7e1c893Smrgstatic void 174b7e1c893SmrgRADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 175b7e1c893Smrg{ 176b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 177b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 178b7e1c893Smrg radeon_native_mode_ptr native_mode = &lvds->native_mode; 179b7e1c893Smrg uint32_t fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); 180b7e1c893Smrg uint32_t fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); 181b7e1c893Smrg 182b7e1c893Smrg lvds->PanelPwrDly = 200; 183b7e1c893Smrg if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { 184b7e1c893Smrg native_mode->PanelYRes = ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >> 185b7e1c893Smrg RADEON_VERT_PANEL_SHIFT) + 1; 186b7e1c893Smrg } else { 187b7e1c893Smrg native_mode->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; 188b7e1c893Smrg } 189b7e1c893Smrg if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { 190b7e1c893Smrg native_mode->PanelXRes = (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >> 191b7e1c893Smrg RADEON_HORZ_PANEL_SHIFT) + 1) * 8; 192b7e1c893Smrg } else { 193b7e1c893Smrg native_mode->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; 194b7e1c893Smrg } 195b7e1c893Smrg 196b7e1c893Smrg if ((native_mode->PanelXRes < 640) || (native_mode->PanelYRes < 480)) { 197b7e1c893Smrg native_mode->PanelXRes = 640; 198b7e1c893Smrg native_mode->PanelYRes = 480; 199b7e1c893Smrg } 200b7e1c893Smrg 201b7e1c893Smrg // move this to crtc function 202b7e1c893Smrg if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { 203b7e1c893Smrg uint32_t ppll_div_sel, ppll_val; 204b7e1c893Smrg 205b7e1c893Smrg ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; 206b7e1c893Smrg RADEONPllErrataAfterIndex(info); 207b7e1c893Smrg ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); 208b7e1c893Smrg if ((ppll_val & 0x000707ff) == 0x1bb) 209b7e1c893Smrg goto noprobe; 210b7e1c893Smrg info->FeedbackDivider = ppll_val & 0x7ff; 211b7e1c893Smrg info->PostDivider = (ppll_val >> 16) & 0x7; 212b7e1c893Smrg info->RefDivider = info->pll.reference_div; 213b7e1c893Smrg info->UseBiosDividers = TRUE; 214b7e1c893Smrg 215b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 216b7e1c893Smrg "Existing panel PLL dividers will be used.\n"); 217b7e1c893Smrg } 218b7e1c893Smrg noprobe: 219b7e1c893Smrg 220b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 221b7e1c893Smrg "Panel size %dx%d is derived, this may not be correct.\n" 222b7e1c893Smrg "If not, use PanelSize option to overwrite this setting\n", 223b7e1c893Smrg native_mode->PanelXRes, native_mode->PanelYRes); 224b7e1c893Smrg} 225b7e1c893Smrg 226b7e1c893Smrgvoid 227b7e1c893SmrgRADEONGetLVDSInfo (ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 228b7e1c893Smrg{ 229b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 230b7e1c893Smrg radeon_native_mode_ptr native_mode = &lvds->native_mode; 231861b9feeSmrg const char* s; 232b7e1c893Smrg 233b7e1c893Smrg if (!RADEONGetLVDSInfoFromBIOS(pScrn, lvds)) 234b7e1c893Smrg RADEONGetPanelInfoFromReg(pScrn, lvds); 235b7e1c893Smrg 236b7e1c893Smrg if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { 237b7e1c893Smrg lvds->PanelPwrDly = 200; 238b7e1c893Smrg if (sscanf (s, "%dx%d", &native_mode->PanelXRes, &native_mode->PanelYRes) != 2) { 239b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); 240b7e1c893Smrg RADEONGetPanelInfoFromReg(pScrn, lvds); 241b7e1c893Smrg } 242b7e1c893Smrg } 243b7e1c893Smrg} 244b7e1c893Smrg 245209ff23fSmrgvoid 246209ff23fSmrgRADEONRestoreDACRegisters(ScrnInfoPtr pScrn, 247209ff23fSmrg RADEONSavePtr restore) 248209ff23fSmrg{ 249209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 250209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 251209ff23fSmrg 252209ff23fSmrg if (IS_R300_VARIANT) 253209ff23fSmrg OUTREGP(RADEON_GPIOPAD_A, restore->gpiopad_a, ~1); 254209ff23fSmrg 255209ff23fSmrg OUTREGP(RADEON_DAC_CNTL, 256209ff23fSmrg restore->dac_cntl, 257209ff23fSmrg RADEON_DAC_RANGE_CNTL | 258209ff23fSmrg RADEON_DAC_BLANKING); 259209ff23fSmrg 260209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); 261209ff23fSmrg 262209ff23fSmrg if ((info->ChipFamily != CHIP_FAMILY_RADEON) && 263209ff23fSmrg (info->ChipFamily != CHIP_FAMILY_R200)) 264209ff23fSmrg OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); 265209ff23fSmrg 266209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); 267209ff23fSmrg 268209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_R200) || 269209ff23fSmrg IS_R300_VARIANT) { 270209ff23fSmrg OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl); 271209ff23fSmrg } else { 272209ff23fSmrg OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); 273209ff23fSmrg } 274209ff23fSmrg 275209ff23fSmrg OUTREG(RADEON_DAC_MACRO_CNTL, restore->dac_macro_cntl); 276209ff23fSmrg 277209ff23fSmrg /* R200 DAC connected via DVO */ 278209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_R200) 279209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); 280209ff23fSmrg} 281209ff23fSmrg 282209ff23fSmrg 283209ff23fSmrg/* Write TMDS registers */ 284209ff23fSmrgvoid 285209ff23fSmrgRADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) 286209ff23fSmrg{ 287209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 288209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 289209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 290209ff23fSmrg 291209ff23fSmrg OUTREG(RADEON_TMDS_PLL_CNTL, restore->tmds_pll_cntl); 292209ff23fSmrg OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl); 293209ff23fSmrg OUTREG(RADEON_FP_GEN_CNTL, restore->fp_gen_cntl); 294209ff23fSmrg 295209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 296209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 297209ff23fSmrg OUTREG(RS400_FP_2ND_GEN_CNTL, restore->fp_2nd_gen_cntl); 298209ff23fSmrg /*OUTREG(RS400_TMDS2_CNTL, restore->tmds2_cntl);*/ 299209ff23fSmrg OUTREG(RS400_TMDS2_TRANSMITTER_CNTL, restore->tmds2_transmitter_cntl); 300209ff23fSmrg } 301209ff23fSmrg 302209ff23fSmrg /* old AIW Radeon has some BIOS initialization problem 303209ff23fSmrg * with display buffer underflow, only occurs to DFP 304209ff23fSmrg */ 305209ff23fSmrg if (!pRADEONEnt->HasCRTC2) 306209ff23fSmrg OUTREG(RADEON_GRPH_BUFFER_CNTL, 307209ff23fSmrg INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); 308209ff23fSmrg 309209ff23fSmrg} 310209ff23fSmrg 311209ff23fSmrg/* Write FP2 registers */ 312209ff23fSmrgvoid 313209ff23fSmrgRADEONRestoreFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) 314209ff23fSmrg{ 315209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 316209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 317209ff23fSmrg 318209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); 319209ff23fSmrg 320209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 321209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) 322209ff23fSmrg OUTREG(RS400_FP2_2_GEN_CNTL, restore->fp2_2_gen_cntl); 323209ff23fSmrg} 324209ff23fSmrg 325209ff23fSmrg/* Write RMX registers */ 326209ff23fSmrgvoid 327209ff23fSmrgRADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) 328209ff23fSmrg{ 329209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 330209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 331209ff23fSmrg 332209ff23fSmrg OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch); 333209ff23fSmrg OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch); 334209ff23fSmrg OUTREG(RADEON_CRTC_MORE_CNTL, restore->crtc_more_cntl); 335209ff23fSmrg OUTREG(RADEON_FP_HORZ_VERT_ACTIVE, restore->fp_horz_vert_active); 336209ff23fSmrg OUTREG(RADEON_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); 337209ff23fSmrg OUTREG(RADEON_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); 338209ff23fSmrg OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); 339209ff23fSmrg OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); 340209ff23fSmrg 341209ff23fSmrg} 342209ff23fSmrg 343209ff23fSmrg/* Write LVDS registers */ 344209ff23fSmrgvoid 345209ff23fSmrgRADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) 346209ff23fSmrg{ 347209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 348209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 349209ff23fSmrg 350209ff23fSmrg if (info->IsMobility) { 351209ff23fSmrg OUTREG(RADEON_LVDS_GEN_CNTL, restore->lvds_gen_cntl); 352209ff23fSmrg /*OUTREG(RADEON_LVDS_PLL_CNTL, restore->lvds_pll_cntl);*/ 353209ff23fSmrg 354209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_RV410) { 355209ff23fSmrg OUTREG(RADEON_CLOCK_CNTL_INDEX, 0); 356209ff23fSmrg } 357209ff23fSmrg } 358209ff23fSmrg 359209ff23fSmrg} 360209ff23fSmrg 361209ff23fSmrgvoid 362209ff23fSmrgRADEONSaveDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) 363209ff23fSmrg{ 364209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 365209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 366209ff23fSmrg 367209ff23fSmrg save->dac_cntl = INREG(RADEON_DAC_CNTL); 368209ff23fSmrg save->dac2_cntl = INREG(RADEON_DAC_CNTL2); 369209ff23fSmrg save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 370209ff23fSmrg save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); 371209ff23fSmrg save->disp_tv_out_cntl = INREG(RADEON_DISP_TV_OUT_CNTL); 372209ff23fSmrg save->disp_hw_debug = INREG(RADEON_DISP_HW_DEBUG); 373209ff23fSmrg save->dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); 374209ff23fSmrg save->gpiopad_a = INREG(RADEON_GPIOPAD_A); 375209ff23fSmrg 376209ff23fSmrg} 377209ff23fSmrg 378209ff23fSmrg/* Read flat panel registers */ 379209ff23fSmrgvoid 380209ff23fSmrgRADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) 381209ff23fSmrg{ 382209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 383209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 384209ff23fSmrg 385209ff23fSmrg save->fp_gen_cntl = INREG(RADEON_FP_GEN_CNTL); 386209ff23fSmrg save->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL); 387209ff23fSmrg save->fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); 388209ff23fSmrg save->fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); 389209ff23fSmrg save->fp_horz_vert_active = INREG(RADEON_FP_HORZ_VERT_ACTIVE); 390209ff23fSmrg save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); 391209ff23fSmrg save->lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL); 392209ff23fSmrg save->lvds_pll_cntl = INREG(RADEON_LVDS_PLL_CNTL); 393209ff23fSmrg save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL); 394209ff23fSmrg save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL); 395209ff23fSmrg 396209ff23fSmrg save->fp_h_sync_strt_wid = INREG(RADEON_FP_H_SYNC_STRT_WID); 397209ff23fSmrg save->fp_v_sync_strt_wid = INREG(RADEON_FP_V_SYNC_STRT_WID); 398209ff23fSmrg save->fp_crtc_h_total_disp = INREG(RADEON_FP_CRTC_H_TOTAL_DISP); 399209ff23fSmrg save->fp_crtc_v_total_disp = INREG(RADEON_FP_CRTC_V_TOTAL_DISP); 400209ff23fSmrg 401209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_RV280) { 402209ff23fSmrg /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ 403209ff23fSmrg save->tmds_pll_cntl ^= (1 << 22); 404209ff23fSmrg } 405209ff23fSmrg 406209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 407209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 408209ff23fSmrg save->fp_2nd_gen_cntl = INREG(RS400_FP_2ND_GEN_CNTL); 409209ff23fSmrg save->fp2_2_gen_cntl = INREG(RS400_FP2_2_GEN_CNTL); 410209ff23fSmrg save->tmds2_cntl = INREG(RS400_TMDS2_CNTL); 411209ff23fSmrg save->tmds2_transmitter_cntl = INREG(RS400_TMDS2_TRANSMITTER_CNTL); 412209ff23fSmrg } 413209ff23fSmrg 414209ff23fSmrg} 415209ff23fSmrg 416209ff23fSmrgBool 417209ff23fSmrgRADEONDVOReadByte(I2CDevPtr dvo, int addr, uint8_t *ch) 418209ff23fSmrg{ 419209ff23fSmrg if (!xf86I2CReadByte(dvo, addr, ch)) { 420209ff23fSmrg xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, 421209ff23fSmrg "Unable to read from %s Slave %d.\n", 422209ff23fSmrg dvo->pI2CBus->BusName, dvo->SlaveAddr); 423209ff23fSmrg return FALSE; 424209ff23fSmrg } 425209ff23fSmrg return TRUE; 426209ff23fSmrg} 427209ff23fSmrg 428209ff23fSmrgBool 429209ff23fSmrgRADEONDVOWriteByte(I2CDevPtr dvo, int addr, uint8_t ch) 430209ff23fSmrg{ 431209ff23fSmrg if (!xf86I2CWriteByte(dvo, addr, ch)) { 432209ff23fSmrg xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, 433209ff23fSmrg "Unable to write to %s Slave %d.\n", 434209ff23fSmrg dvo->pI2CBus->BusName, dvo->SlaveAddr); 435209ff23fSmrg return FALSE; 436209ff23fSmrg } 437209ff23fSmrg return TRUE; 438209ff23fSmrg} 439209ff23fSmrg 440209ff23fSmrgI2CDevPtr 441209ff23fSmrgRADEONDVODeviceInit(I2CBusPtr b, I2CSlaveAddr addr) 442209ff23fSmrg{ 443209ff23fSmrg I2CDevPtr dvo; 444209ff23fSmrg 4452f39173dSmrg dvo = calloc(1, sizeof(I2CDevRec)); 446209ff23fSmrg if (dvo == NULL) 447209ff23fSmrg return NULL; 448209ff23fSmrg 449209ff23fSmrg dvo->DevName = "RADEON DVO Controller"; 450209ff23fSmrg dvo->SlaveAddr = addr; 451209ff23fSmrg dvo->pI2CBus = b; 452209ff23fSmrg dvo->StartTimeout = b->StartTimeout; 453209ff23fSmrg dvo->BitTimeout = b->BitTimeout; 454209ff23fSmrg dvo->AcknTimeout = b->AcknTimeout; 455209ff23fSmrg dvo->ByteTimeout = b->ByteTimeout; 456209ff23fSmrg 457209ff23fSmrg if (xf86I2CDevInit(dvo)) { 458209ff23fSmrg return dvo; 459209ff23fSmrg } 460209ff23fSmrg 4612f39173dSmrg free(dvo); 462209ff23fSmrg return NULL; 463209ff23fSmrg} 464209ff23fSmrg 465209ff23fSmrgstatic void 466209ff23fSmrgRADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output) 467209ff23fSmrg{ 468209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 469b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 470b7e1c893Smrg radeon_dvo_ptr dvo = NULL; 471209ff23fSmrg 472b7e1c893Smrg if (radeon_encoder == NULL) 473209ff23fSmrg return; 474209ff23fSmrg 475b7e1c893Smrg dvo = (radeon_dvo_ptr)radeon_encoder->dev_priv; 476b7e1c893Smrg 477b7e1c893Smrg if (dvo == NULL) 478b7e1c893Smrg return; 479209ff23fSmrg 480b7e1c893Smrg if (!dvo->DVOChip) 481b7e1c893Smrg return; 482b7e1c893Smrg 483c503f109Smrg RADEONI2CDoLock(output, dvo->pI2CBus, TRUE); 484209ff23fSmrg if (!RADEONInitExtTMDSInfoFromBIOS(output)) { 485b7e1c893Smrg if (dvo->DVOChip) { 486209ff23fSmrg switch(info->ext_tmds_chip) { 487209ff23fSmrg case RADEON_SIL_164: 488b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x30); 489b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x09, 0x00); 490b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0a, 0x90); 491b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0c, 0x89); 492b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x3b); 493209ff23fSmrg break; 494209ff23fSmrg#if 0 495209ff23fSmrg /* needs work see bug 10418 */ 496209ff23fSmrg case RADEON_SIL_1178: 497b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0f, 0x44); 498b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0f, 0x4c); 499b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0e, 0x01); 500b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0a, 0x80); 501b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x09, 0x30); 502b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0c, 0xc9); 503b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x0d, 0x70); 504b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x32); 505b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x33); 506209ff23fSmrg break; 507209ff23fSmrg#endif 508209ff23fSmrg default: 509209ff23fSmrg break; 510209ff23fSmrg } 511209ff23fSmrg } 512209ff23fSmrg } 513c503f109Smrg RADEONI2CDoLock(output, dvo->pI2CBus, FALSE); 514209ff23fSmrg} 515209ff23fSmrg 516209ff23fSmrg#if 0 517209ff23fSmrgstatic RADEONMonitorType 518209ff23fSmrgRADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) 519209ff23fSmrg{ 520209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 521209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 522209ff23fSmrg int bConnected = 0; 523209ff23fSmrg 524209ff23fSmrg /* the monitor either wasn't connected or it is a non-DDC CRT. 525209ff23fSmrg * try to probe it 526209ff23fSmrg */ 527209ff23fSmrg if(IsCrtDac) { 528209ff23fSmrg unsigned long ulOrigVCLK_ECP_CNTL; 529209ff23fSmrg unsigned long ulOrigDAC_CNTL; 530209ff23fSmrg unsigned long ulOrigDAC_MACRO_CNTL; 531209ff23fSmrg unsigned long ulOrigDAC_EXT_CNTL; 532209ff23fSmrg unsigned long ulOrigCRTC_EXT_CNTL; 533209ff23fSmrg unsigned long ulData; 534209ff23fSmrg unsigned long ulMask; 535209ff23fSmrg 536209ff23fSmrg ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); 537209ff23fSmrg 538209ff23fSmrg ulData = ulOrigVCLK_ECP_CNTL; 539209ff23fSmrg ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb 540209ff23fSmrg | RADEON_PIXCLK_DAC_ALWAYS_ONb); 541209ff23fSmrg ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb 542209ff23fSmrg |RADEON_PIXCLK_DAC_ALWAYS_ONb); 543209ff23fSmrg OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); 544209ff23fSmrg 545209ff23fSmrg ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); 546209ff23fSmrg ulData = ulOrigCRTC_EXT_CNTL; 547209ff23fSmrg ulData |= RADEON_CRTC_CRT_ON; 548209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, ulData); 549209ff23fSmrg 550209ff23fSmrg ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); 551209ff23fSmrg ulData = ulOrigDAC_EXT_CNTL; 552209ff23fSmrg ulData &= ~RADEON_DAC_FORCE_DATA_MASK; 553209ff23fSmrg ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN 554209ff23fSmrg |RADEON_DAC_FORCE_DATA_EN 555209ff23fSmrg |RADEON_DAC_FORCE_DATA_SEL_MASK); 556209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RV250) || 557209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RV280)) 558209ff23fSmrg ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); 559209ff23fSmrg else 560209ff23fSmrg ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); 561209ff23fSmrg 562209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, ulData); 563209ff23fSmrg 564209ff23fSmrg /* turn on power so testing can go through */ 565209ff23fSmrg ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); 566209ff23fSmrg ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN; 567209ff23fSmrg OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL); 568209ff23fSmrg 569209ff23fSmrg ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); 570209ff23fSmrg ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | 571209ff23fSmrg RADEON_DAC_PDWN_B); 572209ff23fSmrg OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); 573209ff23fSmrg 574209ff23fSmrg /* Enable comparators and set DAC range to PS2 (VGA) output level */ 575209ff23fSmrg ulData = ulOrigDAC_CNTL; 576209ff23fSmrg ulData |= RADEON_DAC_CMP_EN; 577209ff23fSmrg ulData &= ~RADEON_DAC_RANGE_CNTL_MASK; 578209ff23fSmrg ulData |= 0x2; 579209ff23fSmrg OUTREG(RADEON_DAC_CNTL, ulData); 580209ff23fSmrg 581209ff23fSmrg /* Settle down */ 582209ff23fSmrg usleep(10000); 583209ff23fSmrg 584209ff23fSmrg /* Read comparators */ 585209ff23fSmrg ulData = INREG(RADEON_DAC_CNTL); 586209ff23fSmrg bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; 587209ff23fSmrg 588209ff23fSmrg /* Restore things */ 589209ff23fSmrg ulData = ulOrigVCLK_ECP_CNTL; 590209ff23fSmrg ulMask = 0xFFFFFFFFL; 591209ff23fSmrg OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); 592209ff23fSmrg 593209ff23fSmrg OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); 594209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); 595209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); 596209ff23fSmrg 597209ff23fSmrg if (!bConnected) { 598209ff23fSmrg /* Power DAC down if CRT is not connected */ 599209ff23fSmrg ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); 600209ff23fSmrg ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | 601209ff23fSmrg RADEON_DAC_PDWN_B); 602209ff23fSmrg OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); 603209ff23fSmrg 604209ff23fSmrg ulData = INREG(RADEON_DAC_CNTL); 605209ff23fSmrg ulData |= RADEON_DAC_PDWN; 606209ff23fSmrg OUTREG(RADEON_DAC_CNTL, ulData); 607209ff23fSmrg } 608209ff23fSmrg } else { /* TV DAC */ 609209ff23fSmrg 610209ff23fSmrg /* This doesn't seem to work reliably (maybe worse on some OEM cards), 611209ff23fSmrg for now we always return false. If one wants to connected a 612209ff23fSmrg non-DDC monitor on the DVI port when CRT port is also connected, 613209ff23fSmrg he will need to explicitly tell the driver in the config file 614209ff23fSmrg with Option MonitorLayout. 615209ff23fSmrg */ 616209ff23fSmrg bConnected = FALSE; 617209ff23fSmrg 618209ff23fSmrg#if 0 619209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_R200) { 620209ff23fSmrg unsigned long ulOrigGPIO_MONID; 621209ff23fSmrg unsigned long ulOrigFP2_GEN_CNTL; 622209ff23fSmrg unsigned long ulOrigDISP_OUTPUT_CNTL; 623209ff23fSmrg unsigned long ulOrigCRTC2_GEN_CNTL; 624209ff23fSmrg unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; 625209ff23fSmrg unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; 626209ff23fSmrg unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; 627209ff23fSmrg unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; 628209ff23fSmrg unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; 629209ff23fSmrg unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; 630209ff23fSmrg unsigned long ulOrigCRTC2_H_TOTAL_DISP; 631209ff23fSmrg unsigned long ulOrigCRTC2_V_TOTAL_DISP; 632209ff23fSmrg unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; 633209ff23fSmrg unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; 634209ff23fSmrg unsigned long ulData, i; 635209ff23fSmrg 636209ff23fSmrg ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); 637209ff23fSmrg ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); 638209ff23fSmrg ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); 639209ff23fSmrg ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); 640209ff23fSmrg ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); 641209ff23fSmrg ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); 642209ff23fSmrg ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); 643209ff23fSmrg ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); 644209ff23fSmrg ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); 645209ff23fSmrg ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); 646209ff23fSmrg 647209ff23fSmrg ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); 648209ff23fSmrg ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); 649209ff23fSmrg ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); 650209ff23fSmrg ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); 651209ff23fSmrg 652209ff23fSmrg ulData = INREG(RADEON_GPIO_MONID); 653209ff23fSmrg ulData &= ~RADEON_GPIO_A_0; 654209ff23fSmrg OUTREG(RADEON_GPIO_MONID, ulData); 655209ff23fSmrg 656209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); 657209ff23fSmrg 658209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); 659209ff23fSmrg 660209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); 661209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); 662209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); 663209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); 664209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); 665209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); 666209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); 667209ff23fSmrg OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); 668209ff23fSmrg OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); 669209ff23fSmrg OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); 670209ff23fSmrg OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); 671209ff23fSmrg 672209ff23fSmrg for (i = 0; i < 200; i++) { 673209ff23fSmrg ulData = INREG(RADEON_GPIO_MONID); 674209ff23fSmrg bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; 675209ff23fSmrg if (!bConnected) break; 676209ff23fSmrg 677209ff23fSmrg usleep(1000); 678209ff23fSmrg } 679209ff23fSmrg 680209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); 681209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); 682209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); 683209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); 684209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); 685209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); 686209ff23fSmrg OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); 687209ff23fSmrg OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); 688209ff23fSmrg OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); 689209ff23fSmrg OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); 690209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); 691209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); 692209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); 693209ff23fSmrg OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); 694209ff23fSmrg } else { 695209ff23fSmrg unsigned long ulOrigPIXCLKSDATA; 696209ff23fSmrg unsigned long ulOrigTV_MASTER_CNTL; 697209ff23fSmrg unsigned long ulOrigTV_DAC_CNTL; 698209ff23fSmrg unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; 699209ff23fSmrg unsigned long ulOrigDAC_CNTL2; 700209ff23fSmrg unsigned long ulData; 701209ff23fSmrg unsigned long ulMask; 702209ff23fSmrg 703209ff23fSmrg ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); 704209ff23fSmrg 705209ff23fSmrg ulData = ulOrigPIXCLKSDATA; 706209ff23fSmrg ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb 707209ff23fSmrg | RADEON_PIX2CLK_DAC_ALWAYS_ONb); 708209ff23fSmrg ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb 709209ff23fSmrg | RADEON_PIX2CLK_DAC_ALWAYS_ONb); 710209ff23fSmrg OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); 711209ff23fSmrg 712209ff23fSmrg ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); 713209ff23fSmrg ulData = ulOrigTV_MASTER_CNTL; 714209ff23fSmrg ulData &= ~RADEON_TVCLK_ALWAYS_ONb; 715209ff23fSmrg OUTREG(RADEON_TV_MASTER_CNTL, ulData); 716209ff23fSmrg 717209ff23fSmrg ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); 718209ff23fSmrg ulData = ulOrigDAC_CNTL2; 719209ff23fSmrg ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; 720209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, ulData); 721209ff23fSmrg 722209ff23fSmrg ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); 723209ff23fSmrg 724209ff23fSmrg ulData = 0x00880213; 725209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, ulData); 726209ff23fSmrg 727209ff23fSmrg ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); 728209ff23fSmrg 729209ff23fSmrg ulData = (RADEON_Y_RED_EN 730209ff23fSmrg | RADEON_C_GRN_EN 731209ff23fSmrg | RADEON_CMP_BLU_EN 732209ff23fSmrg | RADEON_RED_MX_FORCE_DAC_DATA 733209ff23fSmrg | RADEON_GRN_MX_FORCE_DAC_DATA 734209ff23fSmrg | RADEON_BLU_MX_FORCE_DAC_DATA); 735209ff23fSmrg if (IS_R300_VARIANT) 736209ff23fSmrg ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; 737209ff23fSmrg else 738209ff23fSmrg ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; 739209ff23fSmrg OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); 740209ff23fSmrg 741209ff23fSmrg usleep(10000); 742209ff23fSmrg 743209ff23fSmrg ulData = INREG(RADEON_TV_DAC_CNTL); 744209ff23fSmrg bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; 745209ff23fSmrg 746209ff23fSmrg ulData = ulOrigPIXCLKSDATA; 747209ff23fSmrg ulMask = 0xFFFFFFFFL; 748209ff23fSmrg OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); 749209ff23fSmrg 750209ff23fSmrg OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); 751209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); 752209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); 753209ff23fSmrg OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); 754209ff23fSmrg } 755209ff23fSmrg#endif 756209ff23fSmrg return MT_UNKNOWN; 757209ff23fSmrg } 758209ff23fSmrg 759209ff23fSmrg return(bConnected ? MT_CRT : MT_NONE); 760209ff23fSmrg} 761209ff23fSmrg#endif 762209ff23fSmrg 763209ff23fSmrgRADEONMonitorType 764b7e1c893Smrglegacy_dac_detect(xf86OutputPtr output) 765209ff23fSmrg{ 766b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 767209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 768209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 769209ff23fSmrg RADEONMonitorType found = MT_NONE; 770209ff23fSmrg 771b7e1c893Smrg if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT)) { 772209ff23fSmrg if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) { 773b7e1c893Smrg if (radeon_output->ConnectorType == CONNECTOR_STV) 774209ff23fSmrg found = MT_STV; 775209ff23fSmrg else 776209ff23fSmrg found = MT_CTV; 777209ff23fSmrg } else { 778b7e1c893Smrg if (radeon_output->load_detection) 779b7e1c893Smrg found = radeon_detect_tv(pScrn); 780b7e1c893Smrg } 781b7e1c893Smrg } else if (radeon_output->devices & (ATOM_DEVICE_CRT2_SUPPORT)) { 782b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT2_INDEX] && 783b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) { 784b7e1c893Smrg if (radeon_output->load_detection) 785b7e1c893Smrg found = radeon_detect_primary_dac(pScrn, TRUE); 786b7e1c893Smrg } else { 787b7e1c893Smrg if (radeon_output->load_detection) { 788b7e1c893Smrg if (info->ChipFamily == CHIP_FAMILY_R200) 789b7e1c893Smrg found = radeon_detect_ext_dac(pScrn); 790209ff23fSmrg else 791b7e1c893Smrg found = radeon_detect_tv_dac(pScrn, TRUE); 792209ff23fSmrg } 793209ff23fSmrg } 794b7e1c893Smrg } else if (radeon_output->devices & (ATOM_DEVICE_CRT1_SUPPORT)) { 795b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT1_INDEX] && 796b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) { 797209ff23fSmrg if (radeon_output->load_detection) 798209ff23fSmrg found = radeon_detect_primary_dac(pScrn, TRUE); 799b7e1c893Smrg } else { 800209ff23fSmrg if (radeon_output->load_detection) { 801209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_R200) 802209ff23fSmrg found = radeon_detect_ext_dac(pScrn); 803209ff23fSmrg else 804209ff23fSmrg found = radeon_detect_tv_dac(pScrn, TRUE); 805b7e1c893Smrg } 806209ff23fSmrg } 807209ff23fSmrg } 808209ff23fSmrg 809209ff23fSmrg return found; 810209ff23fSmrg} 811209ff23fSmrg 812209ff23fSmrg/* 813209ff23fSmrg * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). 814209ff23fSmrg * 815209ff23fSmrg */ 816209ff23fSmrgstatic void 817209ff23fSmrgRADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) 818209ff23fSmrg{ 819209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 820209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 821209ff23fSmrg 822209ff23fSmrg if (IsPrimaryDAC) { 823209ff23fSmrg uint32_t dac_cntl; 824209ff23fSmrg uint32_t dac_macro_cntl = 0; 825209ff23fSmrg dac_cntl = INREG(RADEON_DAC_CNTL); 826209ff23fSmrg dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); 827209ff23fSmrg if (IsOn) { 828209ff23fSmrg dac_cntl &= ~RADEON_DAC_PDWN; 829209ff23fSmrg dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | 830209ff23fSmrg RADEON_DAC_PDWN_G | 831209ff23fSmrg RADEON_DAC_PDWN_B); 832209ff23fSmrg } else { 833209ff23fSmrg dac_cntl |= RADEON_DAC_PDWN; 834209ff23fSmrg dac_macro_cntl |= (RADEON_DAC_PDWN_R | 835209ff23fSmrg RADEON_DAC_PDWN_G | 836209ff23fSmrg RADEON_DAC_PDWN_B); 837209ff23fSmrg } 838209ff23fSmrg OUTREG(RADEON_DAC_CNTL, dac_cntl); 839209ff23fSmrg OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); 840209ff23fSmrg } else { 841209ff23fSmrg uint32_t tv_dac_cntl; 842209ff23fSmrg uint32_t fp2_gen_cntl; 843209ff23fSmrg 844b7e1c893Smrg switch(info->ChipFamily) { 845209ff23fSmrg case CHIP_FAMILY_R420: 846209ff23fSmrg case CHIP_FAMILY_RV410: 847209ff23fSmrg tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 848209ff23fSmrg if (IsOn) { 849209ff23fSmrg tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | 850209ff23fSmrg R420_TV_DAC_GDACPD | 851209ff23fSmrg R420_TV_DAC_BDACPD | 852209ff23fSmrg RADEON_TV_DAC_BGSLEEP); 853209ff23fSmrg } else { 854209ff23fSmrg tv_dac_cntl |= (R420_TV_DAC_RDACPD | 855209ff23fSmrg R420_TV_DAC_GDACPD | 856209ff23fSmrg R420_TV_DAC_BDACPD | 857209ff23fSmrg RADEON_TV_DAC_BGSLEEP); 858209ff23fSmrg } 859209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); 860209ff23fSmrg break; 861209ff23fSmrg case CHIP_FAMILY_R200: 862209ff23fSmrg fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); 863209ff23fSmrg if (IsOn) { 864209ff23fSmrg fp2_gen_cntl |= RADEON_FP2_DVO_EN; 865209ff23fSmrg } else { 866209ff23fSmrg fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; 867209ff23fSmrg } 868209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 869209ff23fSmrg break; 870209ff23fSmrg default: 871209ff23fSmrg tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 872209ff23fSmrg if (IsOn) { 873209ff23fSmrg tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | 874209ff23fSmrg RADEON_TV_DAC_GDACPD | 875209ff23fSmrg RADEON_TV_DAC_BDACPD | 876209ff23fSmrg RADEON_TV_DAC_BGSLEEP); 877209ff23fSmrg } else { 878209ff23fSmrg tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | 879209ff23fSmrg RADEON_TV_DAC_GDACPD | 880209ff23fSmrg RADEON_TV_DAC_BDACPD | 881209ff23fSmrg RADEON_TV_DAC_BGSLEEP); 882209ff23fSmrg } 883209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); 884209ff23fSmrg break; 885209ff23fSmrg } 886209ff23fSmrg } 887209ff23fSmrg} 888209ff23fSmrg 889b7e1c893Smrgvoid 890b7e1c893Smrglegacy_output_dpms(xf86OutputPtr output, int mode) 891209ff23fSmrg{ 892209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 893209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 894209ff23fSmrg RADEONSavePtr save = info->ModeReg; 895209ff23fSmrg unsigned char * RADEONMMIO = info->MMIO; 896209ff23fSmrg unsigned long tmp; 897b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 898b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 899209ff23fSmrg 900b7e1c893Smrg if (radeon_encoder == NULL) 901b7e1c893Smrg return; 902209ff23fSmrg 903b7e1c893Smrg switch(mode) { 904b7e1c893Smrg case DPMSModeOn: 905b7e1c893Smrg radeon_encoder->devices |= radeon_output->active_device; 906b7e1c893Smrg switch (radeon_encoder->encoder_id) { 907b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 908b7e1c893Smrg { 909b7e1c893Smrg radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv; 910b7e1c893Smrg if (lvds == NULL) 911b7e1c893Smrg return; 912b7e1c893Smrg ErrorF("enable LVDS\n"); 913b7e1c893Smrg tmp = INREG(RADEON_LVDS_GEN_CNTL); 914b7e1c893Smrg tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); 915ad43ddacSmrg#if defined(__powerpc__) 916ad43ddacSmrg /* not sure if this is needed on non-Macs */ 917ad43ddacSmrg if (info->MacModel) 918ad43ddacSmrg tmp |= RADEON_LVDS_BL_MOD_EN; 919ad43ddacSmrg#endif 920b7e1c893Smrg tmp &= ~(RADEON_LVDS_DISPLAY_DIS); 921b7e1c893Smrg usleep (lvds->PanelPwrDly * 1000); 922b7e1c893Smrg OUTREG(RADEON_LVDS_GEN_CNTL, tmp); 923b7e1c893Smrg save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); 924b7e1c893Smrg save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); 925b7e1c893Smrg } 926b7e1c893Smrg break; 927b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 928b7e1c893Smrg ErrorF("enable FP1\n"); 929b7e1c893Smrg tmp = INREG(RADEON_FP_GEN_CNTL); 930b7e1c893Smrg tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); 931b7e1c893Smrg OUTREG(RADEON_FP_GEN_CNTL, tmp); 932b7e1c893Smrg save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); 933b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 934b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 935b7e1c893Smrg tmp = INREG(RS400_FP_2ND_GEN_CNTL); 936b7e1c893Smrg tmp |= (RS400_FP_2ND_ON | RS400_TMDS_2ND_EN); 937b7e1c893Smrg OUTREG(RS400_FP_2ND_GEN_CNTL, tmp); 938b7e1c893Smrg save->fp_2nd_gen_cntl |= (RS400_FP_2ND_ON | 939b7e1c893Smrg RS400_TMDS_2ND_EN); 940b7e1c893Smrg } 941b7e1c893Smrg break; 942b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 943b7e1c893Smrg ErrorF("enable FP2\n"); 944b7e1c893Smrg tmp = INREG(RADEON_FP2_GEN_CNTL); 945b7e1c893Smrg tmp &= ~RADEON_FP2_BLANK_EN; 946b7e1c893Smrg tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); 947b7e1c893Smrg OUTREG(RADEON_FP2_GEN_CNTL, tmp); 948b7e1c893Smrg save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); 949b7e1c893Smrg save->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; 950b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 951b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 952b7e1c893Smrg tmp = INREG(RS400_FP2_2_GEN_CNTL); 953b7e1c893Smrg tmp &= ~RS400_FP2_2_BLANK_EN; 954b7e1c893Smrg tmp |= (RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN); 955b7e1c893Smrg OUTREG(RS400_FP2_2_GEN_CNTL, tmp); 956b7e1c893Smrg save->fp2_2_gen_cntl |= (RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN); 957b7e1c893Smrg save->fp2_2_gen_cntl &= ~RS400_FP2_2_BLANK_EN; 958b7e1c893Smrg } 959b7e1c893Smrg break; 960b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 961b7e1c893Smrg ErrorF("enable primary dac\n"); 962b7e1c893Smrg tmp = INREG(RADEON_CRTC_EXT_CNTL); 963b7e1c893Smrg tmp |= RADEON_CRTC_CRT_ON; 964b7e1c893Smrg OUTREG(RADEON_CRTC_EXT_CNTL, tmp); 965b7e1c893Smrg save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; 966b7e1c893Smrg RADEONDacPowerSet(pScrn, TRUE, TRUE); 967b7e1c893Smrg break; 968b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 969b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 970b7e1c893Smrg ErrorF("enable TV\n"); 971b7e1c893Smrg tmp = INREG(RADEON_TV_MASTER_CNTL); 972b7e1c893Smrg tmp |= RADEON_TV_ON; 973b7e1c893Smrg OUTREG(RADEON_TV_MASTER_CNTL, tmp); 974b7e1c893Smrg radeon_output->tvout.tv_on = TRUE; 975b7e1c893Smrg } else { 976b7e1c893Smrg ErrorF("enable TVDAC\n"); 977209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_R200) { 978209ff23fSmrg tmp = INREG(RADEON_FP2_GEN_CNTL); 979209ff23fSmrg tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); 980209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, tmp); 981209ff23fSmrg save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); 982209ff23fSmrg } else { 983209ff23fSmrg tmp = INREG(RADEON_CRTC2_GEN_CNTL); 984209ff23fSmrg tmp |= RADEON_CRTC2_CRT2_ON; 985209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); 986209ff23fSmrg save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; 987209ff23fSmrg } 988209ff23fSmrg } 989b7e1c893Smrg RADEONDacPowerSet(pScrn, TRUE, FALSE); 990b7e1c893Smrg break; 991b7e1c893Smrg } 992b7e1c893Smrg break; 993b7e1c893Smrg case DPMSModeOff: 994b7e1c893Smrg case DPMSModeSuspend: 995b7e1c893Smrg case DPMSModeStandby: 996b7e1c893Smrg radeon_encoder->devices &= ~(radeon_output->active_device); 997b7e1c893Smrg if (!radeon_encoder->devices) { 998b7e1c893Smrg switch (radeon_encoder->encoder_id) { 999b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1000b7e1c893Smrg { 1001b7e1c893Smrg unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); 10020974d292Smrg radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv; 10030974d292Smrg if (lvds == NULL) 10040974d292Smrg return; 1005b7e1c893Smrg if (info->IsMobility || info->IsIGP) { 1006b7e1c893Smrg /* Asic bug, when turning off LVDS_ON, we have to make sure 1007b7e1c893Smrg RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off 1008b7e1c893Smrg */ 1009b7e1c893Smrg OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); 1010b7e1c893Smrg } 1011ad43ddacSmrg#if defined(__powerpc__) 1012ad43ddacSmrg /* not sure if this is needed on non-Macs */ 1013ad43ddacSmrg if (info->MacModel) { 1014ad43ddacSmrg tmp = INREG(RADEON_LVDS_GEN_CNTL); 1015ad43ddacSmrg tmp |= RADEON_LVDS_DISPLAY_DIS; 1016ad43ddacSmrg tmp &= ~RADEON_LVDS_BL_MOD_EN; 1017ad43ddacSmrg OUTREG(RADEON_LVDS_GEN_CNTL, tmp); 1018ad43ddacSmrg usleep(100); 1019ad43ddacSmrg tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN); 1020ad43ddacSmrg OUTREG(RADEON_LVDS_GEN_CNTL, tmp); 1021ad43ddacSmrg } else 1022ad43ddacSmrg#endif 1023ad43ddacSmrg { 1024ad43ddacSmrg tmp = INREG(RADEON_LVDS_GEN_CNTL); 1025ad43ddacSmrg tmp |= RADEON_LVDS_DISPLAY_DIS; 1026ad43ddacSmrg tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); 1027ad43ddacSmrg OUTREG(RADEON_LVDS_GEN_CNTL, tmp); 1028ad43ddacSmrg } 1029b7e1c893Smrg save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; 1030b7e1c893Smrg save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); 1031b7e1c893Smrg if (info->IsMobility || info->IsIGP) { 1032b7e1c893Smrg OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); 1033b7e1c893Smrg } 10340974d292Smrg usleep (lvds->PanelPwrDly * 1000); 1035b7e1c893Smrg } 1036b7e1c893Smrg break; 1037b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1038b7e1c893Smrg ErrorF("disable FP1\n"); 1039209ff23fSmrg tmp = INREG(RADEON_FP_GEN_CNTL); 1040b7e1c893Smrg tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); 1041209ff23fSmrg OUTREG(RADEON_FP_GEN_CNTL, tmp); 1042b7e1c893Smrg save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); 1043209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 1044209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 1045209ff23fSmrg tmp = INREG(RS400_FP_2ND_GEN_CNTL); 1046b7e1c893Smrg tmp &= ~(RS400_FP_2ND_ON | RS400_TMDS_2ND_EN); 1047209ff23fSmrg OUTREG(RS400_FP_2ND_GEN_CNTL, tmp); 1048b7e1c893Smrg save->fp_2nd_gen_cntl &= ~(RS400_FP_2ND_ON | 1049b7e1c893Smrg RS400_TMDS_2ND_EN); 1050209ff23fSmrg } 1051b7e1c893Smrg break; 1052b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1053b7e1c893Smrg ErrorF("disable FP2\n"); 1054209ff23fSmrg tmp = INREG(RADEON_FP2_GEN_CNTL); 1055b7e1c893Smrg tmp |= RADEON_FP2_BLANK_EN; 1056b7e1c893Smrg tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); 1057209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, tmp); 1058b7e1c893Smrg save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); 1059b7e1c893Smrg save->fp2_gen_cntl |= RADEON_FP2_BLANK_EN; 1060209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 1061209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 1062209ff23fSmrg tmp = INREG(RS400_FP2_2_GEN_CNTL); 1063b7e1c893Smrg tmp |= RS400_FP2_2_BLANK_EN; 1064b7e1c893Smrg tmp &= ~(RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN); 1065209ff23fSmrg OUTREG(RS400_FP2_2_GEN_CNTL, tmp); 1066b7e1c893Smrg save->fp2_2_gen_cntl &= ~(RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN); 1067b7e1c893Smrg save->fp2_2_gen_cntl |= RS400_FP2_2_BLANK_EN; 1068209ff23fSmrg } 1069b7e1c893Smrg break; 1070b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1071b7e1c893Smrg ErrorF("disable primary dac\n"); 1072b7e1c893Smrg tmp = INREG(RADEON_CRTC_EXT_CNTL); 1073b7e1c893Smrg tmp &= ~RADEON_CRTC_CRT_ON; 1074b7e1c893Smrg OUTREG(RADEON_CRTC_EXT_CNTL, tmp); 1075b7e1c893Smrg save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; 1076b7e1c893Smrg RADEONDacPowerSet(pScrn, FALSE, TRUE); 1077b7e1c893Smrg break; 1078b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1079b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 1080b7e1c893Smrg ErrorF("disable TV\n"); 1081b7e1c893Smrg tmp = INREG(RADEON_TV_MASTER_CNTL); 1082b7e1c893Smrg tmp &= ~RADEON_TV_ON; 1083b7e1c893Smrg OUTREG(RADEON_TV_MASTER_CNTL, tmp); 1084b7e1c893Smrg radeon_output->tvout.tv_on = FALSE; 1085b7e1c893Smrg } else { 1086b7e1c893Smrg ErrorF("disable TVDAC\n"); 1087209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_R200) { 1088209ff23fSmrg tmp = INREG(RADEON_FP2_GEN_CNTL); 1089209ff23fSmrg tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); 1090209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, tmp); 1091209ff23fSmrg save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); 1092209ff23fSmrg } else { 1093209ff23fSmrg tmp = INREG(RADEON_CRTC2_GEN_CNTL); 1094209ff23fSmrg tmp &= ~RADEON_CRTC2_CRT2_ON; 1095209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); 1096209ff23fSmrg save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; 1097209ff23fSmrg } 1098209ff23fSmrg } 1099b7e1c893Smrg RADEONDacPowerSet(pScrn, FALSE, FALSE); 1100b7e1c893Smrg break; 1101209ff23fSmrg } 1102209ff23fSmrg } 1103209ff23fSmrg break; 1104209ff23fSmrg } 1105209ff23fSmrg} 1106209ff23fSmrg 1107209ff23fSmrgstatic void 1108209ff23fSmrgRADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save, 1109209ff23fSmrg DisplayModePtr mode, BOOL IsPrimary) 1110209ff23fSmrg{ 1111209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1112209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1113209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1114209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1115b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1116b7e1c893Smrg radeon_tmds_ptr tmds = NULL; 1117209ff23fSmrg int i; 1118209ff23fSmrg uint32_t tmp = info->SavedReg->tmds_pll_cntl & 0xfffff; 1119209ff23fSmrg 1120b7e1c893Smrg if (radeon_encoder == NULL) 1121b7e1c893Smrg return; 1122b7e1c893Smrg 1123b7e1c893Smrg tmds = (radeon_tmds_ptr)radeon_encoder->dev_priv; 1124b7e1c893Smrg 1125b7e1c893Smrg if (tmds == NULL) 1126b7e1c893Smrg return; 1127b7e1c893Smrg 1128b7e1c893Smrg for (i = 0; i < 4; i++) { 1129b7e1c893Smrg if (tmds->tmds_pll[i].freq == 0) 1130b7e1c893Smrg break; 1131b7e1c893Smrg if ((uint32_t)(mode->Clock / 10) < tmds->tmds_pll[i].freq) { 1132b7e1c893Smrg tmp = tmds->tmds_pll[i].value ; 1133209ff23fSmrg break; 1134209ff23fSmrg } 1135209ff23fSmrg } 1136209ff23fSmrg 1137209ff23fSmrg if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { 1138209ff23fSmrg if (tmp & 0xfff00000) 1139209ff23fSmrg save->tmds_pll_cntl = tmp; 1140209ff23fSmrg else { 1141209ff23fSmrg save->tmds_pll_cntl = info->SavedReg->tmds_pll_cntl & 0xfff00000; 1142209ff23fSmrg save->tmds_pll_cntl |= tmp; 1143209ff23fSmrg } 1144209ff23fSmrg } else save->tmds_pll_cntl = tmp; 1145209ff23fSmrg 1146209ff23fSmrg save->tmds_transmitter_cntl = info->SavedReg->tmds_transmitter_cntl & 1147209ff23fSmrg ~(RADEON_TMDS_TRANSMITTER_PLLRST); 1148209ff23fSmrg 1149209ff23fSmrg if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2) 1150209ff23fSmrg save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); 1151209ff23fSmrg else /* weird, RV chips got this bit reversed? */ 1152209ff23fSmrg save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); 1153209ff23fSmrg 1154209ff23fSmrg save->fp_gen_cntl = info->SavedReg->fp_gen_cntl | 1155209ff23fSmrg (RADEON_FP_CRTC_DONT_SHADOW_VPAR | 1156209ff23fSmrg RADEON_FP_CRTC_DONT_SHADOW_HEND ); 1157209ff23fSmrg 1158209ff23fSmrg save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); 1159209ff23fSmrg 1160b7e1c893Smrg save->fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN | 1161b7e1c893Smrg RADEON_FP_DFP_SYNC_SEL | 1162b7e1c893Smrg RADEON_FP_CRT_SYNC_SEL | 1163b7e1c893Smrg RADEON_FP_CRTC_LOCK_8DOT | 1164b7e1c893Smrg RADEON_FP_USE_SHADOW_EN | 1165b7e1c893Smrg RADEON_FP_CRTC_USE_SHADOW_VEND | 1166b7e1c893Smrg RADEON_FP_CRT_SYNC_ALT); 1167b7e1c893Smrg 1168209ff23fSmrg if (pScrn->rgbBits == 8) 1169209ff23fSmrg save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ 1170209ff23fSmrg else 1171209ff23fSmrg save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ 1172209ff23fSmrg 1173209ff23fSmrg if (IsPrimary) { 1174209ff23fSmrg if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { 1175209ff23fSmrg save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; 1176209ff23fSmrg if (radeon_output->Flags & RADEON_USE_RMX) 1177209ff23fSmrg save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; 1178209ff23fSmrg else 1179209ff23fSmrg save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; 1180209ff23fSmrg } else 1181b7e1c893Smrg save->fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2; 1182209ff23fSmrg } else { 1183209ff23fSmrg if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { 1184209ff23fSmrg save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; 1185209ff23fSmrg save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; 1186209ff23fSmrg } else 1187209ff23fSmrg save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; 1188209ff23fSmrg } 1189209ff23fSmrg 1190209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 1191209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 1192209ff23fSmrg save->tmds2_transmitter_cntl = info->SavedReg->tmds2_transmitter_cntl & 1193209ff23fSmrg ~(RS400_TMDS2_PLLRST); 1194209ff23fSmrg save->tmds2_transmitter_cntl &= ~(RS400_TMDS2_PLLEN); 1195209ff23fSmrg 1196209ff23fSmrg save->fp_2nd_gen_cntl = info->SavedReg->fp_2nd_gen_cntl; 1197209ff23fSmrg 1198209ff23fSmrg if (pScrn->rgbBits == 8) 1199209ff23fSmrg save->fp_2nd_gen_cntl |= RS400_PANEL_FORMAT_2ND; /* 24 bit format */ 1200209ff23fSmrg else 1201209ff23fSmrg save->fp_2nd_gen_cntl &= ~RS400_PANEL_FORMAT_2ND;/* 18 bit format */ 1202209ff23fSmrg 1203209ff23fSmrg save->fp_2nd_gen_cntl &= ~RS400_FP_2ND_SOURCE_SEL_MASK; 1204209ff23fSmrg 1205209ff23fSmrg if (IsPrimary) { 1206209ff23fSmrg if (radeon_output->Flags & RADEON_USE_RMX) 1207209ff23fSmrg save->fp_2nd_gen_cntl |= RS400_FP_2ND_SOURCE_SEL_RMX; 1208209ff23fSmrg else 1209209ff23fSmrg save->fp_2nd_gen_cntl |= RS400_FP_2ND_SOURCE_SEL_CRTC1; 1210209ff23fSmrg } else 1211209ff23fSmrg save->fp_2nd_gen_cntl |= RS400_FP_2ND_SOURCE_SEL_CRTC2; 1212209ff23fSmrg } 1213209ff23fSmrg 1214209ff23fSmrg} 1215209ff23fSmrg 1216209ff23fSmrgstatic void 1217209ff23fSmrgRADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save, 1218209ff23fSmrg DisplayModePtr mode, BOOL IsPrimary) 1219209ff23fSmrg{ 1220209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1221209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1222209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1223209ff23fSmrg 1224209ff23fSmrg if (pScrn->rgbBits == 8) 1225209ff23fSmrg save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl | 1226209ff23fSmrg RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ 1227209ff23fSmrg else 1228209ff23fSmrg save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & 1229209ff23fSmrg ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ 1230209ff23fSmrg 1231209ff23fSmrg save->fp2_gen_cntl &= ~(RADEON_FP2_ON | 1232209ff23fSmrg RADEON_FP2_DVO_EN | 1233209ff23fSmrg RADEON_FP2_DVO_RATE_SEL_SDR); 1234209ff23fSmrg 1235209ff23fSmrg 1236b7e1c893Smrg /* XXX: these are oem specific */ 1237209ff23fSmrg if (IS_R300_VARIANT) { 1238b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV350_NP) && 1239b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1028) && 1240b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x2001)) 1241ad43ddacSmrg save->fp2_gen_cntl |= R200_FP2_DVO_CLOCK_MODE_SINGLE; /* Dell Inspiron 8600 */ 1242b7e1c893Smrg else 1243ad43ddacSmrg save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R200_FP2_DVO_CLOCK_MODE_SINGLE; 1244ad43ddacSmrg } 1245ad43ddacSmrg 1246209ff23fSmrg#if 0 1247ad43ddacSmrg /* DVO configurations: 1248ad43ddacSmrg * SDR single channel (data rate 165 Mhz, port width 12 bits) 1249ad43ddacSmrg * DDR single channel (data rate 330 Mhz, port width 12 bits) 1250ad43ddacSmrg * SDR dual channel (data rate 330 Mhz, port width 24 bits) 1251ad43ddacSmrg * - dual channel is only available on r3xx+ 1252ad43ddacSmrg */ 1253ad43ddacSmrg if (info->ChipFamily >= CHIP_FAMILY_R200) { 1254ad43ddacSmrg if (sdr) 1255ad43ddacSmrg save->fp2_gen_cntl |= R200_FP2_DVO_RATE_SEL_SDR; 1256ad43ddacSmrg if (IS_R300_VARIANT && dual channel) 1257209ff23fSmrg save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN; 1258209ff23fSmrg } 1259ad43ddacSmrg#endif 1260209ff23fSmrg 1261209ff23fSmrg if (IsPrimary) { 1262209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { 1263209ff23fSmrg save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; 1264209ff23fSmrg if (radeon_output->Flags & RADEON_USE_RMX) 1265209ff23fSmrg save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; 1266209ff23fSmrg else 1267209ff23fSmrg save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; 1268b7e1c893Smrg } else 1269209ff23fSmrg save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; 1270209ff23fSmrg } else { 1271209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { 1272209ff23fSmrg save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; 1273209ff23fSmrg save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; 1274b7e1c893Smrg } else 1275209ff23fSmrg save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; 1276209ff23fSmrg } 1277209ff23fSmrg 1278209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400) || 1279209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS480)) { 1280209ff23fSmrg if (pScrn->rgbBits == 8) 1281209ff23fSmrg save->fp2_2_gen_cntl = info->SavedReg->fp2_2_gen_cntl | 1282209ff23fSmrg RS400_FP2_2_PANEL_FORMAT; /* 24 bit format, */ 1283209ff23fSmrg else 1284209ff23fSmrg save->fp2_2_gen_cntl = info->SavedReg->fp2_2_gen_cntl & 1285209ff23fSmrg ~RS400_FP2_2_PANEL_FORMAT;/* 18 bit format, */ 1286209ff23fSmrg 1287209ff23fSmrg save->fp2_2_gen_cntl &= ~(RS400_FP2_2_ON | 1288209ff23fSmrg RS400_FP2_2_DVO2_EN | 1289209ff23fSmrg RS400_FP2_2_SOURCE_SEL_MASK); 1290209ff23fSmrg 1291209ff23fSmrg if (IsPrimary) { 1292209ff23fSmrg if (radeon_output->Flags & RADEON_USE_RMX) 1293209ff23fSmrg save->fp2_2_gen_cntl |= RS400_FP2_2_SOURCE_SEL_RMX; 1294209ff23fSmrg else 1295209ff23fSmrg save->fp2_2_gen_cntl |= RS400_FP2_2_SOURCE_SEL_CRTC1; 1296209ff23fSmrg } else 1297209ff23fSmrg save->fp2_2_gen_cntl |= RS400_FP2_2_SOURCE_SEL_CRTC2; 1298209ff23fSmrg } 1299209ff23fSmrg 1300209ff23fSmrg} 1301209ff23fSmrg 1302209ff23fSmrgstatic void 1303209ff23fSmrgRADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save, 1304209ff23fSmrg DisplayModePtr mode, BOOL IsPrimary) 1305209ff23fSmrg{ 1306209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1307209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1308209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1309209ff23fSmrg 1310209ff23fSmrg save->lvds_pll_cntl = (info->SavedReg->lvds_pll_cntl | 1311209ff23fSmrg RADEON_LVDS_PLL_EN); 1312209ff23fSmrg 1313209ff23fSmrg save->lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; 1314209ff23fSmrg 1315209ff23fSmrg save->lvds_gen_cntl = info->SavedReg->lvds_gen_cntl; 1316209ff23fSmrg save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; 1317209ff23fSmrg save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | 1318209ff23fSmrg RADEON_LVDS_BLON | 1319209ff23fSmrg RADEON_LVDS_EN | 1320209ff23fSmrg RADEON_LVDS_RST_FM); 1321209ff23fSmrg 1322209ff23fSmrg if (IS_R300_VARIANT) 1323209ff23fSmrg save->lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK); 1324209ff23fSmrg 1325209ff23fSmrg if (IsPrimary) { 1326209ff23fSmrg if (IS_R300_VARIANT) { 1327209ff23fSmrg if (radeon_output->Flags & RADEON_USE_RMX) 1328209ff23fSmrg save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; 1329209ff23fSmrg } else 1330209ff23fSmrg save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; 1331209ff23fSmrg } else { 1332209ff23fSmrg if (IS_R300_VARIANT) { 1333209ff23fSmrg save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2; 1334209ff23fSmrg } else 1335209ff23fSmrg save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; 1336209ff23fSmrg } 1337209ff23fSmrg 1338209ff23fSmrg} 1339209ff23fSmrg 1340209ff23fSmrgstatic void 1341209ff23fSmrgRADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save, 1342209ff23fSmrg DisplayModePtr mode) 1343209ff23fSmrg{ 1344209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1345209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1346209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1347b7e1c893Smrg radeon_native_mode_ptr native_mode = &radeon_output->native_mode; 1348209ff23fSmrg int xres = mode->HDisplay; 1349209ff23fSmrg int yres = mode->VDisplay; 1350209ff23fSmrg Bool Hscale = TRUE, Vscale = TRUE; 1351209ff23fSmrg int hsync_wid; 1352209ff23fSmrg int vsync_wid; 1353209ff23fSmrg int hsync_start; 1354209ff23fSmrg 1355209ff23fSmrg 1356209ff23fSmrg save->fp_vert_stretch = info->SavedReg->fp_vert_stretch & 1357209ff23fSmrg (RADEON_VERT_STRETCH_RESERVED | 1358209ff23fSmrg RADEON_VERT_AUTO_RATIO_INC); 1359209ff23fSmrg save->fp_horz_stretch = info->SavedReg->fp_horz_stretch & 1360209ff23fSmrg (RADEON_HORZ_FP_LOOP_STRETCH | 1361209ff23fSmrg RADEON_HORZ_AUTO_RATIO_INC); 1362209ff23fSmrg 1363209ff23fSmrg save->crtc_more_cntl = 0; 1364209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS100) || 1365209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS200)) { 1366209ff23fSmrg /* This is to workaround the asic bug for RMX, some versions 1367209ff23fSmrg of BIOS dosen't have this register initialized correctly. 1368209ff23fSmrg */ 1369209ff23fSmrg save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; 1370209ff23fSmrg } 1371209ff23fSmrg 1372209ff23fSmrg 1373209ff23fSmrg save->fp_crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) 1374209ff23fSmrg | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) 1375209ff23fSmrg << 16)); 1376209ff23fSmrg 1377209ff23fSmrg hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 1378209ff23fSmrg if (!hsync_wid) hsync_wid = 1; 1379209ff23fSmrg hsync_start = mode->CrtcHSyncStart - 8; 1380209ff23fSmrg 1381209ff23fSmrg save->fp_h_sync_strt_wid = ((hsync_start & 0x1fff) 1382209ff23fSmrg | ((hsync_wid & 0x3f) << 16) 1383209ff23fSmrg | ((mode->Flags & V_NHSYNC) 1384209ff23fSmrg ? RADEON_CRTC_H_SYNC_POL 1385209ff23fSmrg : 0)); 1386209ff23fSmrg 1387209ff23fSmrg save->fp_crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 1388209ff23fSmrg | ((mode->CrtcVDisplay - 1) << 16)); 1389209ff23fSmrg 1390209ff23fSmrg vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 1391209ff23fSmrg if (!vsync_wid) vsync_wid = 1; 1392209ff23fSmrg 1393209ff23fSmrg save->fp_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 1394209ff23fSmrg | ((vsync_wid & 0x1f) << 16) 1395209ff23fSmrg | ((mode->Flags & V_NVSYNC) 1396209ff23fSmrg ? RADEON_CRTC_V_SYNC_POL 1397209ff23fSmrg : 0)); 1398209ff23fSmrg 1399209ff23fSmrg save->fp_horz_vert_active = 0; 1400209ff23fSmrg 1401b7e1c893Smrg if ((radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) || 1402b7e1c893Smrg (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT))) { 1403209ff23fSmrg 1404b7e1c893Smrg if (native_mode->PanelXRes == 0 || native_mode->PanelYRes == 0) { 1405209ff23fSmrg Hscale = FALSE; 1406209ff23fSmrg Vscale = FALSE; 1407b7e1c893Smrg } else { 1408b7e1c893Smrg if (xres > native_mode->PanelXRes) 1409b7e1c893Smrg xres = native_mode->PanelXRes; 1410b7e1c893Smrg if (yres > native_mode->PanelYRes) 1411b7e1c893Smrg yres = native_mode->PanelYRes; 1412b7e1c893Smrg 1413b7e1c893Smrg if (xres == native_mode->PanelXRes) 1414b7e1c893Smrg Hscale = FALSE; 1415b7e1c893Smrg if (yres == native_mode->PanelYRes) 1416b7e1c893Smrg Vscale = FALSE; 1417b7e1c893Smrg } 1418209ff23fSmrg 1419b7e1c893Smrg if ((!Hscale) || (!(radeon_output->Flags & RADEON_USE_RMX)) || 1420b7e1c893Smrg (radeon_output->rmx_type == RMX_CENTER)) { 1421b7e1c893Smrg save->fp_horz_stretch |= ((xres/8-1)<<16); 1422b7e1c893Smrg } else { 1423b7e1c893Smrg uint32_t scale, inc; 1424b7e1c893Smrg inc = (save->fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; 1425b7e1c893Smrg scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) 1426b7e1c893Smrg / native_mode->PanelXRes + 1; 1427b7e1c893Smrg save->fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | 1428b7e1c893Smrg RADEON_HORZ_STRETCH_BLEND | 1429b7e1c893Smrg RADEON_HORZ_STRETCH_ENABLE | 1430b7e1c893Smrg ((native_mode->PanelXRes/8-1)<<16)); 1431b7e1c893Smrg } 1432209ff23fSmrg 1433b7e1c893Smrg if ((!Vscale) || (!(radeon_output->Flags & RADEON_USE_RMX)) || 1434b7e1c893Smrg (radeon_output->rmx_type == RMX_CENTER)) { 1435b7e1c893Smrg save->fp_vert_stretch |= ((yres-1)<<12); 1436b7e1c893Smrg } else { 1437b7e1c893Smrg uint32_t scale, inc; 1438b7e1c893Smrg inc = (save->fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; 1439b7e1c893Smrg scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) 1440b7e1c893Smrg / native_mode->PanelYRes + 1; 1441b7e1c893Smrg save->fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | 1442b7e1c893Smrg RADEON_VERT_STRETCH_ENABLE | 1443b7e1c893Smrg RADEON_VERT_STRETCH_BLEND | 1444b7e1c893Smrg ((native_mode->PanelYRes-1)<<12)); 1445b7e1c893Smrg } 1446209ff23fSmrg 1447b7e1c893Smrg if ((radeon_output->rmx_type == RMX_CENTER) && 1448b7e1c893Smrg (radeon_output->Flags & RADEON_USE_RMX)) { 1449b7e1c893Smrg int blank_width; 1450209ff23fSmrg 1451b7e1c893Smrg save->crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | 1452b7e1c893Smrg RADEON_CRTC_AUTO_VERT_CENTER_EN); 1453209ff23fSmrg 1454b7e1c893Smrg blank_width = (mode->CrtcHBlankEnd - mode->CrtcHBlankStart) / 8; 1455b7e1c893Smrg if (blank_width > 110) 1456b7e1c893Smrg blank_width = 110; 1457209ff23fSmrg 1458b7e1c893Smrg save->fp_crtc_h_total_disp = (((blank_width) & 0x3ff) 1459b7e1c893Smrg | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) 1460b7e1c893Smrg << 16)); 1461209ff23fSmrg 1462b7e1c893Smrg hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 1463b7e1c893Smrg if (!hsync_wid) 1464b7e1c893Smrg hsync_wid = 1; 1465209ff23fSmrg 1466b7e1c893Smrg save->fp_h_sync_strt_wid = ((((mode->CrtcHSyncStart - mode->CrtcHBlankStart) / 8) & 0x1fff) 1467b7e1c893Smrg | ((hsync_wid & 0x3f) << 16) 1468b7e1c893Smrg | ((mode->Flags & V_NHSYNC) 1469b7e1c893Smrg ? RADEON_CRTC_H_SYNC_POL 1470b7e1c893Smrg : 0)); 1471209ff23fSmrg 1472b7e1c893Smrg save->fp_crtc_v_total_disp = (((mode->CrtcVBlankEnd - mode->CrtcVBlankStart) & 0xffff) 1473b7e1c893Smrg | ((mode->CrtcVDisplay - 1) << 16)); 1474209ff23fSmrg 1475b7e1c893Smrg vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 1476b7e1c893Smrg if (!vsync_wid) 1477b7e1c893Smrg vsync_wid = 1; 1478209ff23fSmrg 1479b7e1c893Smrg save->fp_v_sync_strt_wid = ((((mode->CrtcVSyncStart - mode->CrtcVBlankStart) & 0xfff) 1480b7e1c893Smrg | ((vsync_wid & 0x1f) << 16) 1481b7e1c893Smrg | ((mode->Flags & V_NVSYNC) 1482b7e1c893Smrg ? RADEON_CRTC_V_SYNC_POL 1483b7e1c893Smrg : 0))); 1484209ff23fSmrg 1485b7e1c893Smrg save->fp_horz_vert_active = (((native_mode->PanelYRes) & 0xfff) | 1486b7e1c893Smrg (((native_mode->PanelXRes / 8) & 0x1ff) << 16)); 1487209ff23fSmrg 1488b7e1c893Smrg } 1489209ff23fSmrg } 1490209ff23fSmrg} 1491209ff23fSmrg 1492209ff23fSmrgstatic void 1493209ff23fSmrgRADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save, 1494209ff23fSmrg DisplayModePtr mode, BOOL IsPrimary) 1495209ff23fSmrg{ 1496209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1497209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1498209ff23fSmrg 1499209ff23fSmrg if (IsPrimary) { 1500209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { 1501209ff23fSmrg save->disp_output_cntl = info->SavedReg->disp_output_cntl & 1502209ff23fSmrg ~RADEON_DISP_DAC_SOURCE_MASK; 1503209ff23fSmrg } else { 1504209ff23fSmrg save->dac2_cntl = info->SavedReg->dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL); 1505209ff23fSmrg } 1506209ff23fSmrg } else { 1507209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { 1508209ff23fSmrg save->disp_output_cntl = info->SavedReg->disp_output_cntl & 1509209ff23fSmrg ~RADEON_DISP_DAC_SOURCE_MASK; 1510209ff23fSmrg save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; 1511209ff23fSmrg } else { 1512209ff23fSmrg save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC_CLK_SEL; 1513209ff23fSmrg } 1514209ff23fSmrg } 1515209ff23fSmrg save->dac_cntl = (RADEON_DAC_MASK_ALL 1516209ff23fSmrg | RADEON_DAC_VGA_ADR_EN 1517209ff23fSmrg | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); 1518209ff23fSmrg 1519209ff23fSmrg save->dac_macro_cntl = info->SavedReg->dac_macro_cntl; 1520209ff23fSmrg} 1521209ff23fSmrg 1522209ff23fSmrgstatic void 1523209ff23fSmrgRADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save) 1524209ff23fSmrg{ 1525209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1526209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1527b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1528b7e1c893Smrg radeon_tvdac_ptr tvdac = NULL; 1529b7e1c893Smrg 1530b7e1c893Smrg if (radeon_encoder == NULL) 1531b7e1c893Smrg return; 1532b7e1c893Smrg 1533b7e1c893Smrg tvdac = (radeon_tvdac_ptr)radeon_encoder->dev_priv; 1534b7e1c893Smrg 1535b7e1c893Smrg if (tvdac == NULL) 1536b7e1c893Smrg return; 1537209ff23fSmrg 1538209ff23fSmrg if (info->ChipFamily == CHIP_FAMILY_R420 || 1539209ff23fSmrg info->ChipFamily == CHIP_FAMILY_RV410) { 1540209ff23fSmrg save->tv_dac_cntl = info->SavedReg->tv_dac_cntl & 1541209ff23fSmrg ~(RADEON_TV_DAC_STD_MASK | 1542209ff23fSmrg RADEON_TV_DAC_BGADJ_MASK | 1543209ff23fSmrg R420_TV_DAC_DACADJ_MASK | 1544209ff23fSmrg R420_TV_DAC_RDACPD | 1545209ff23fSmrg R420_TV_DAC_GDACPD | 1546ad43ddacSmrg R420_TV_DAC_BDACPD | 1547209ff23fSmrg R420_TV_DAC_TVENABLE); 1548209ff23fSmrg } else { 1549209ff23fSmrg save->tv_dac_cntl = info->SavedReg->tv_dac_cntl & 1550209ff23fSmrg ~(RADEON_TV_DAC_STD_MASK | 1551209ff23fSmrg RADEON_TV_DAC_BGADJ_MASK | 1552209ff23fSmrg RADEON_TV_DAC_DACADJ_MASK | 1553209ff23fSmrg RADEON_TV_DAC_RDACPD | 1554209ff23fSmrg RADEON_TV_DAC_GDACPD | 1555ad43ddacSmrg RADEON_TV_DAC_BDACPD); 1556209ff23fSmrg } 1557209ff23fSmrg 1558209ff23fSmrg save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | 1559209ff23fSmrg RADEON_TV_DAC_NHOLD | 1560209ff23fSmrg RADEON_TV_DAC_STD_PS2 | 1561b7e1c893Smrg tvdac->ps2_tvdac_adj); 1562209ff23fSmrg 1563209ff23fSmrg} 1564209ff23fSmrg 1565209ff23fSmrgstatic void 1566209ff23fSmrgRADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save, 1567209ff23fSmrg DisplayModePtr mode, BOOL IsPrimary) 1568209ff23fSmrg{ 1569209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1570209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1571209ff23fSmrg 1572209ff23fSmrg /*0x0028023;*/ 1573209ff23fSmrg RADEONInitTvDacCntl(output, save); 1574209ff23fSmrg 1575209ff23fSmrg if (IS_R300_VARIANT) 1576209ff23fSmrg save->gpiopad_a = info->SavedReg->gpiopad_a | 1; 1577209ff23fSmrg 1578209ff23fSmrg save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; 1579209ff23fSmrg 1580209ff23fSmrg if (IsPrimary) { 1581209ff23fSmrg if (IS_R300_VARIANT) { 1582209ff23fSmrg save->disp_output_cntl = info->SavedReg->disp_output_cntl & 1583209ff23fSmrg ~RADEON_DISP_TVDAC_SOURCE_MASK; 1584209ff23fSmrg save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; 1585209ff23fSmrg } else if (info->ChipFamily == CHIP_FAMILY_R200) { 1586209ff23fSmrg save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & 1587209ff23fSmrg ~(R200_FP2_SOURCE_SEL_MASK | 1588209ff23fSmrg RADEON_FP2_DVO_RATE_SEL_SDR); 1589209ff23fSmrg } else { 1590209ff23fSmrg save->disp_hw_debug = info->SavedReg->disp_hw_debug | RADEON_CRT2_DISP1_SEL; 1591209ff23fSmrg } 1592209ff23fSmrg } else { 1593209ff23fSmrg if (IS_R300_VARIANT) { 1594209ff23fSmrg save->disp_output_cntl = info->SavedReg->disp_output_cntl & 1595209ff23fSmrg ~RADEON_DISP_TVDAC_SOURCE_MASK; 1596209ff23fSmrg save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; 1597209ff23fSmrg } else if (info->ChipFamily == CHIP_FAMILY_R200) { 1598209ff23fSmrg save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & 1599209ff23fSmrg ~(R200_FP2_SOURCE_SEL_MASK | 1600209ff23fSmrg RADEON_FP2_DVO_RATE_SEL_SDR); 1601209ff23fSmrg save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; 1602209ff23fSmrg } else { 1603209ff23fSmrg save->disp_hw_debug = info->SavedReg->disp_hw_debug & 1604209ff23fSmrg ~RADEON_CRT2_DISP1_SEL; 1605209ff23fSmrg } 1606209ff23fSmrg } 1607209ff23fSmrg} 1608209ff23fSmrg 1609209ff23fSmrgvoid 1610209ff23fSmrglegacy_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, 1611b7e1c893Smrg DisplayModePtr adjusted_mode) 1612209ff23fSmrg{ 1613209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1614209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1615209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1616209ff23fSmrg xf86CrtcPtr crtc = output->crtc; 1617209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 1618b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1619b7e1c893Smrg Bool is_primary = FALSE; 1620209ff23fSmrg 1621b7e1c893Smrg if (radeon_encoder == NULL) 1622b7e1c893Smrg return; 1623209ff23fSmrg 1624b7e1c893Smrg radeon_output->pixel_clock = adjusted_mode->Clock; 1625b7e1c893Smrg if (radeon_crtc->crtc_id == 0) { 1626b7e1c893Smrg ErrorF("set RMX\n"); 1627b7e1c893Smrg is_primary = TRUE; 1628b7e1c893Smrg RADEONInitRMXRegisters(output, info->ModeReg, adjusted_mode); 1629209ff23fSmrg RADEONRestoreRMXRegisters(pScrn, info->ModeReg); 1630b7e1c893Smrg } 1631209ff23fSmrg 1632b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1633b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1634b7e1c893Smrg ErrorF("set LVDS\n"); 1635b7e1c893Smrg RADEONInitLVDSRegisters(output, info->ModeReg, adjusted_mode, is_primary); 1636209ff23fSmrg RADEONRestoreLVDSRegisters(pScrn, info->ModeReg); 1637209ff23fSmrg break; 1638b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1639b7e1c893Smrg ErrorF("set FP1\n"); 1640b7e1c893Smrg RADEONInitFPRegisters(output, info->ModeReg, adjusted_mode, is_primary); 1641b7e1c893Smrg RADEONRestoreFPRegisters(pScrn, info->ModeReg); 1642b7e1c893Smrg break; 1643b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1644b7e1c893Smrg ErrorF("set FP2\n"); 1645b7e1c893Smrg RADEONInitFP2Registers(output, info->ModeReg, adjusted_mode, is_primary); 1646b7e1c893Smrg if (info->IsAtomBios) { 1647b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 1648b7e1c893Smrg uint32_t fp2_gen_cntl; 1649b7e1c893Smrg 1650b7e1c893Smrg atombios_external_tmds_setup(output, ATOM_ENABLE); 1651b7e1c893Smrg fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL) & ~R200_FP2_SOURCE_SEL_MASK; 1652b7e1c893Smrg if (radeon_crtc->crtc_id == 1) 1653b7e1c893Smrg fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; 1654b7e1c893Smrg else { 1655b7e1c893Smrg if (radeon_output->Flags & RADEON_USE_RMX) 1656b7e1c893Smrg fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; 1657b7e1c893Smrg else 1658b7e1c893Smrg fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; 1659209ff23fSmrg } 1660b7e1c893Smrg OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 1661b7e1c893Smrg } else { 1662b7e1c893Smrg RADEONRestoreFP2Registers(pScrn, info->ModeReg); 1663b7e1c893Smrg RADEONRestoreDVOChip(pScrn, output); 1664209ff23fSmrg } 1665209ff23fSmrg break; 1666b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1667b7e1c893Smrg ErrorF("set primary dac\n"); 1668b7e1c893Smrg RADEONInitDACRegisters(output, info->ModeReg, adjusted_mode, is_primary); 1669209ff23fSmrg RADEONRestoreDACRegisters(pScrn, info->ModeReg); 1670209ff23fSmrg break; 1671b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1672b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 1673b7e1c893Smrg ErrorF("set TV\n"); 1674b7e1c893Smrg RADEONInitTVRegisters(output, info->ModeReg, adjusted_mode, is_primary); 1675b7e1c893Smrg RADEONRestoreDACRegisters(pScrn, info->ModeReg); 1676b7e1c893Smrg RADEONRestoreTVRegisters(pScrn, info->ModeReg); 1677b7e1c893Smrg } else { 1678b7e1c893Smrg ErrorF("set TVDAC\n"); 1679b7e1c893Smrg RADEONInitDAC2Registers(output, info->ModeReg, adjusted_mode, is_primary); 1680b7e1c893Smrg RADEONRestoreDACRegisters(pScrn, info->ModeReg); 1681b7e1c893Smrg } 1682b7e1c893Smrg break; 1683209ff23fSmrg } 1684209ff23fSmrg 1685209ff23fSmrg} 1686209ff23fSmrg 1687209ff23fSmrg/* the following functions are based on the load detection code 1688209ff23fSmrg * in the beos radeon driver by Thomas Kurschel and the existing 1689209ff23fSmrg * load detection code in this driver. 1690209ff23fSmrg */ 1691209ff23fSmrgstatic RADEONMonitorType 1692209ff23fSmrgradeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color) 1693209ff23fSmrg{ 1694209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1695209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1696209ff23fSmrg uint32_t vclk_ecp_cntl, crtc_ext_cntl; 1697209ff23fSmrg uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; 1698209ff23fSmrg RADEONMonitorType found = MT_NONE; 1699209ff23fSmrg 1700209ff23fSmrg /* save the regs we need */ 1701209ff23fSmrg vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); 1702209ff23fSmrg crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); 1703209ff23fSmrg dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); 1704209ff23fSmrg dac_cntl = INREG(RADEON_DAC_CNTL); 1705209ff23fSmrg dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); 1706209ff23fSmrg 1707209ff23fSmrg tmp = vclk_ecp_cntl & 1708209ff23fSmrg ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); 1709209ff23fSmrg OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); 1710209ff23fSmrg 1711209ff23fSmrg tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; 1712209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, tmp); 1713209ff23fSmrg 1714209ff23fSmrg tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | 1715209ff23fSmrg RADEON_DAC_FORCE_DATA_EN; 1716209ff23fSmrg 1717209ff23fSmrg if (color) 1718209ff23fSmrg tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; 1719209ff23fSmrg else 1720209ff23fSmrg tmp |= RADEON_DAC_FORCE_DATA_SEL_G; 1721209ff23fSmrg 1722209ff23fSmrg if (IS_R300_VARIANT) 1723209ff23fSmrg tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); 1724209ff23fSmrg else 1725209ff23fSmrg tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); 1726209ff23fSmrg 1727209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, tmp); 1728209ff23fSmrg 1729209ff23fSmrg tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); 1730209ff23fSmrg tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; 1731209ff23fSmrg OUTREG(RADEON_DAC_CNTL, tmp); 1732209ff23fSmrg 1733209ff23fSmrg tmp &= ~(RADEON_DAC_PDWN_R | 1734209ff23fSmrg RADEON_DAC_PDWN_G | 1735209ff23fSmrg RADEON_DAC_PDWN_B); 1736209ff23fSmrg 1737209ff23fSmrg OUTREG(RADEON_DAC_MACRO_CNTL, tmp); 1738209ff23fSmrg 1739209ff23fSmrg usleep(2000); 1740209ff23fSmrg 1741209ff23fSmrg if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) { 1742209ff23fSmrg found = MT_CRT; 1743209ff23fSmrg xf86DrvMsg (pScrn->scrnIndex, X_INFO, 1744209ff23fSmrg "Found %s CRT connected to primary DAC\n", 1745209ff23fSmrg color ? "color" : "bw"); 1746209ff23fSmrg } 1747209ff23fSmrg 1748209ff23fSmrg /* restore the regs we used */ 1749209ff23fSmrg OUTREG(RADEON_DAC_CNTL, dac_cntl); 1750209ff23fSmrg OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); 1751209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); 1752209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 1753209ff23fSmrg OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); 1754209ff23fSmrg 1755209ff23fSmrg return found; 1756209ff23fSmrg} 1757209ff23fSmrg 1758209ff23fSmrgstatic RADEONMonitorType 1759209ff23fSmrgradeon_detect_ext_dac(ScrnInfoPtr pScrn) 1760209ff23fSmrg{ 1761209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1762209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1763209ff23fSmrg uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; 1764209ff23fSmrg uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; 1765209ff23fSmrg uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; 1766209ff23fSmrg uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; 1767209ff23fSmrg uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; 1768209ff23fSmrg RADEONMonitorType found = MT_NONE; 1769209ff23fSmrg int connected = 0; 1770209ff23fSmrg int i = 0; 1771209ff23fSmrg 1772209ff23fSmrg /* save the regs we need */ 1773209ff23fSmrg gpio_monid = INREG(RADEON_GPIO_MONID); 1774209ff23fSmrg fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); 1775209ff23fSmrg disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); 1776209ff23fSmrg crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); 1777209ff23fSmrg disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); 1778209ff23fSmrg disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); 1779209ff23fSmrg disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); 1780209ff23fSmrg disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); 1781209ff23fSmrg disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); 1782209ff23fSmrg disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); 1783209ff23fSmrg crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); 1784209ff23fSmrg crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); 1785209ff23fSmrg crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); 1786209ff23fSmrg crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); 1787209ff23fSmrg 1788209ff23fSmrg tmp = INREG(RADEON_GPIO_MONID); 1789209ff23fSmrg tmp &= ~RADEON_GPIO_A_0; 1790209ff23fSmrg OUTREG(RADEON_GPIO_MONID, tmp); 1791209ff23fSmrg 1792209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, 1793209ff23fSmrg RADEON_FP2_ON | 1794209ff23fSmrg RADEON_FP2_PANEL_FORMAT | 1795209ff23fSmrg R200_FP2_SOURCE_SEL_TRANS_UNIT | 1796209ff23fSmrg RADEON_FP2_DVO_EN | 1797209ff23fSmrg R200_FP2_DVO_RATE_SEL_SDR); 1798209ff23fSmrg 1799209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, 1800209ff23fSmrg RADEON_DISP_DAC_SOURCE_RMX | 1801209ff23fSmrg RADEON_DISP_TRANS_MATRIX_GRAPHICS); 1802209ff23fSmrg 1803209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, 1804209ff23fSmrg RADEON_CRTC2_EN | 1805209ff23fSmrg RADEON_CRTC2_DISP_REQ_EN_B); 1806209ff23fSmrg 1807209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); 1808209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); 1809209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); 1810209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); 1811209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); 1812209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); 1813209ff23fSmrg 1814209ff23fSmrg OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); 1815209ff23fSmrg OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); 1816209ff23fSmrg OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); 1817209ff23fSmrg OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); 1818209ff23fSmrg 1819209ff23fSmrg for (i = 0; i < 200; i++) { 1820209ff23fSmrg tmp = INREG(RADEON_GPIO_MONID); 1821209ff23fSmrg if (tmp & RADEON_GPIO_Y_0) 1822209ff23fSmrg connected = 1; 1823209ff23fSmrg else 1824209ff23fSmrg connected = 0; 1825209ff23fSmrg 1826209ff23fSmrg if (!connected) 1827209ff23fSmrg break; 1828209ff23fSmrg 1829209ff23fSmrg usleep(1000); 1830209ff23fSmrg } 1831209ff23fSmrg 1832209ff23fSmrg if (connected) 1833209ff23fSmrg found = MT_CRT; 1834209ff23fSmrg 1835209ff23fSmrg /* restore the regs we used */ 1836209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); 1837209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); 1838209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); 1839209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); 1840209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); 1841209ff23fSmrg OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); 1842209ff23fSmrg OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); 1843209ff23fSmrg OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); 1844209ff23fSmrg OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); 1845209ff23fSmrg OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); 1846209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 1847209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 1848209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 1849209ff23fSmrg OUTREG(RADEON_GPIO_MONID, gpio_monid); 1850209ff23fSmrg 1851209ff23fSmrg return found; 1852209ff23fSmrg} 1853209ff23fSmrg 1854209ff23fSmrgstatic RADEONMonitorType 1855209ff23fSmrgradeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color) 1856209ff23fSmrg{ 1857209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1858209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1859209ff23fSmrg uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; 1860209ff23fSmrg uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; 1861209ff23fSmrg RADEONMonitorType found = MT_NONE; 1862209ff23fSmrg 1863209ff23fSmrg /* save the regs we need */ 1864209ff23fSmrg pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); 1865209ff23fSmrg gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0; 1866209ff23fSmrg disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0; 1867209ff23fSmrg disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0; 1868209ff23fSmrg crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); 1869209ff23fSmrg tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 1870209ff23fSmrg dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); 1871209ff23fSmrg dac_cntl2 = INREG(RADEON_DAC_CNTL2); 1872209ff23fSmrg 1873209ff23fSmrg tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb 1874209ff23fSmrg | RADEON_PIX2CLK_DAC_ALWAYS_ONb); 1875209ff23fSmrg OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); 1876209ff23fSmrg 1877209ff23fSmrg if (IS_R300_VARIANT) { 1878209ff23fSmrg OUTREGP(RADEON_GPIOPAD_A, 1, ~1 ); 1879209ff23fSmrg } 1880209ff23fSmrg 1881209ff23fSmrg tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; 1882209ff23fSmrg tmp |= RADEON_CRTC2_CRT2_ON | 1883209ff23fSmrg (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); 1884209ff23fSmrg 1885209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); 1886209ff23fSmrg 1887209ff23fSmrg if (IS_R300_VARIANT) { 1888209ff23fSmrg tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; 1889209ff23fSmrg tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; 1890209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); 1891209ff23fSmrg } else { 1892209ff23fSmrg tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; 1893209ff23fSmrg OUTREG(RADEON_DISP_HW_DEBUG, tmp); 1894209ff23fSmrg } 1895209ff23fSmrg 1896209ff23fSmrg tmp = RADEON_TV_DAC_NBLANK | 1897209ff23fSmrg RADEON_TV_DAC_NHOLD | 1898209ff23fSmrg RADEON_TV_MONITOR_DETECT_EN | 1899209ff23fSmrg RADEON_TV_DAC_STD_PS2; 1900209ff23fSmrg 1901209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, tmp); 1902209ff23fSmrg 1903209ff23fSmrg tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | 1904209ff23fSmrg RADEON_DAC2_FORCE_DATA_EN; 1905209ff23fSmrg 1906209ff23fSmrg if (color) 1907209ff23fSmrg tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; 1908209ff23fSmrg else 1909209ff23fSmrg tmp |= RADEON_DAC_FORCE_DATA_SEL_G; 1910209ff23fSmrg 1911209ff23fSmrg if (IS_R300_VARIANT) 1912209ff23fSmrg tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); 1913209ff23fSmrg else 1914209ff23fSmrg tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); 1915209ff23fSmrg 1916209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, tmp); 1917209ff23fSmrg 1918209ff23fSmrg tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; 1919209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, tmp); 1920209ff23fSmrg 1921209ff23fSmrg usleep(10000); 1922209ff23fSmrg 1923209ff23fSmrg if (IS_R300_VARIANT) { 1924209ff23fSmrg if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) { 1925209ff23fSmrg found = MT_CRT; 1926209ff23fSmrg xf86DrvMsg (pScrn->scrnIndex, X_INFO, 1927209ff23fSmrg "Found %s CRT connected to TV DAC\n", 1928209ff23fSmrg color ? "color" : "bw"); 1929209ff23fSmrg } 1930209ff23fSmrg } else { 1931209ff23fSmrg if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) { 1932209ff23fSmrg found = MT_CRT; 1933209ff23fSmrg xf86DrvMsg (pScrn->scrnIndex, X_INFO, 1934209ff23fSmrg "Found %s CRT connected to TV DAC\n", 1935209ff23fSmrg color ? "color" : "bw"); 1936209ff23fSmrg } 1937209ff23fSmrg } 1938209ff23fSmrg 1939209ff23fSmrg /* restore regs we used */ 1940209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, dac_cntl2); 1941209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); 1942209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); 1943209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 1944209ff23fSmrg 1945209ff23fSmrg if (IS_R300_VARIANT) { 1946209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 1947209ff23fSmrg OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 ); 1948209ff23fSmrg } else { 1949209ff23fSmrg OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug); 1950209ff23fSmrg } 1951209ff23fSmrg OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl); 1952209ff23fSmrg 1953209ff23fSmrg return found; 1954209ff23fSmrg} 1955209ff23fSmrg 1956209ff23fSmrgstatic RADEONMonitorType 1957209ff23fSmrgr300_detect_tv(ScrnInfoPtr pScrn) 1958209ff23fSmrg{ 1959209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1960209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1961209ff23fSmrg uint32_t tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl; 1962209ff23fSmrg uint32_t gpiopad_a, disp_output_cntl; 1963209ff23fSmrg RADEONMonitorType found = MT_NONE; 1964209ff23fSmrg 1965209ff23fSmrg /* save the regs we need */ 1966209ff23fSmrg gpiopad_a = INREG(RADEON_GPIOPAD_A); 1967209ff23fSmrg dac_cntl2 = INREG(RADEON_DAC_CNTL2); 1968209ff23fSmrg crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); 1969209ff23fSmrg dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); 1970209ff23fSmrg tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 1971209ff23fSmrg disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); 1972209ff23fSmrg 1973209ff23fSmrg OUTREGP(RADEON_GPIOPAD_A, 0, ~1 ); 1974209ff23fSmrg 1975209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL ); 1976209ff23fSmrg 1977209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, 1978209ff23fSmrg RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT ); 1979209ff23fSmrg 1980209ff23fSmrg tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; 1981209ff23fSmrg tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; 1982209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); 1983209ff23fSmrg 1984209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, 1985209ff23fSmrg RADEON_DAC2_FORCE_BLANK_OFF_EN | 1986209ff23fSmrg RADEON_DAC2_FORCE_DATA_EN | 1987209ff23fSmrg RADEON_DAC_FORCE_DATA_SEL_RGB | 1988209ff23fSmrg (0xec << RADEON_DAC_FORCE_DATA_SHIFT )); 1989209ff23fSmrg 1990209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, 1991209ff23fSmrg RADEON_TV_DAC_STD_NTSC | 1992209ff23fSmrg (8 << RADEON_TV_DAC_BGADJ_SHIFT) | 1993209ff23fSmrg (6 << RADEON_TV_DAC_DACADJ_SHIFT )); 1994209ff23fSmrg 1995209ff23fSmrg INREG(RADEON_TV_DAC_CNTL); 1996209ff23fSmrg 1997209ff23fSmrg usleep(4000); 1998209ff23fSmrg 1999209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, 2000209ff23fSmrg RADEON_TV_DAC_NBLANK | 2001209ff23fSmrg RADEON_TV_DAC_NHOLD | 2002209ff23fSmrg RADEON_TV_MONITOR_DETECT_EN | 2003209ff23fSmrg RADEON_TV_DAC_STD_NTSC | 2004209ff23fSmrg (8 << RADEON_TV_DAC_BGADJ_SHIFT) | 2005209ff23fSmrg (6 << RADEON_TV_DAC_DACADJ_SHIFT )); 2006209ff23fSmrg 2007209ff23fSmrg INREG(RADEON_TV_DAC_CNTL); 2008209ff23fSmrg 2009209ff23fSmrg usleep(6000); 2010209ff23fSmrg 2011209ff23fSmrg tmp = INREG(RADEON_TV_DAC_CNTL); 2012209ff23fSmrg if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) { 2013209ff23fSmrg found = MT_STV; 2014209ff23fSmrg xf86DrvMsg (pScrn->scrnIndex, X_INFO, 2015209ff23fSmrg "S-Video TV connection detected\n"); 2016209ff23fSmrg } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) { 2017209ff23fSmrg found = MT_CTV; 2018209ff23fSmrg xf86DrvMsg (pScrn->scrnIndex, X_INFO, 2019209ff23fSmrg "Composite TV connection detected\n" ); 2020209ff23fSmrg } 2021209ff23fSmrg 2022209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl ); 2023209ff23fSmrg OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); 2024209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 2025209ff23fSmrg OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 2026209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, dac_cntl2); 2027209ff23fSmrg OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1); 2028209ff23fSmrg 2029209ff23fSmrg return found; 2030209ff23fSmrg} 2031209ff23fSmrg 2032209ff23fSmrgstatic RADEONMonitorType 2033209ff23fSmrgradeon_detect_tv(ScrnInfoPtr pScrn) 2034209ff23fSmrg{ 2035209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2036209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 2037209ff23fSmrg uint32_t tmp, dac_cntl2, tv_master_cntl; 2038209ff23fSmrg uint32_t tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl; 2039209ff23fSmrg RADEONMonitorType found = MT_NONE; 2040209ff23fSmrg 2041209ff23fSmrg if (IS_R300_VARIANT) 2042209ff23fSmrg return r300_detect_tv(pScrn); 2043209ff23fSmrg 2044209ff23fSmrg /* save the regs we need */ 2045209ff23fSmrg dac_cntl2 = INREG(RADEON_DAC_CNTL2); 2046209ff23fSmrg tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); 2047209ff23fSmrg tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 2048209ff23fSmrg config_cntl = INREG(RADEON_CONFIG_CNTL); 2049209ff23fSmrg tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); 2050209ff23fSmrg 2051209ff23fSmrg tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; 2052209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, tmp); 2053209ff23fSmrg 2054209ff23fSmrg tmp = tv_master_cntl | RADEON_TV_ON; 2055209ff23fSmrg tmp &= ~(RADEON_TV_ASYNC_RST | 2056209ff23fSmrg RADEON_RESTART_PHASE_FIX | 2057209ff23fSmrg RADEON_CRT_FIFO_CE_EN | 2058209ff23fSmrg RADEON_TV_FIFO_CE_EN | 2059209ff23fSmrg RADEON_RE_SYNC_NOW_SEL_MASK); 2060209ff23fSmrg tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; 2061209ff23fSmrg 2062209ff23fSmrg OUTREG(RADEON_TV_MASTER_CNTL, tmp); 2063209ff23fSmrg 2064209ff23fSmrg tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | 2065209ff23fSmrg RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | 2066209ff23fSmrg (8 << RADEON_TV_DAC_BGADJ_SHIFT); 2067209ff23fSmrg 2068209ff23fSmrg if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) 2069209ff23fSmrg tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); 2070209ff23fSmrg else 2071209ff23fSmrg tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); 2072209ff23fSmrg 2073209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, tmp); 2074209ff23fSmrg 2075209ff23fSmrg tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | 2076209ff23fSmrg RADEON_RED_MX_FORCE_DAC_DATA | 2077209ff23fSmrg RADEON_GRN_MX_FORCE_DAC_DATA | 2078209ff23fSmrg RADEON_BLU_MX_FORCE_DAC_DATA | 2079209ff23fSmrg (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); 2080209ff23fSmrg 2081209ff23fSmrg OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); 2082209ff23fSmrg 2083209ff23fSmrg usleep(3000); 2084209ff23fSmrg 2085209ff23fSmrg tmp = INREG(RADEON_TV_DAC_CNTL); 2086209ff23fSmrg if (tmp & RADEON_TV_DAC_GDACDET) { 2087209ff23fSmrg found = MT_STV; 2088209ff23fSmrg xf86DrvMsg (pScrn->scrnIndex, X_INFO, 2089209ff23fSmrg "S-Video TV connection detected\n"); 2090209ff23fSmrg } else if (tmp & RADEON_TV_DAC_BDACDET) { 2091209ff23fSmrg found = MT_CTV; 2092209ff23fSmrg xf86DrvMsg (pScrn->scrnIndex, X_INFO, 2093209ff23fSmrg "Composite TV connection detected\n" ); 2094209ff23fSmrg } 2095209ff23fSmrg 2096209ff23fSmrg OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); 2097209ff23fSmrg OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); 2098209ff23fSmrg OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl); 2099209ff23fSmrg OUTREG(RADEON_DAC_CNTL2, dac_cntl2); 2100209ff23fSmrg 2101209ff23fSmrg return found; 2102209ff23fSmrg} 2103