diff -dNau8 old-src/radeon.h src/radeon.h --- old-src/radeon.h 2006-08-31 21:07:19.000000000 -0700 +++ src/radeon.h 2006-08-31 21:14:13.000000000 -0700 @@ -72,16 +72,23 @@ #include "GL/glxint.h" #endif /* Render support */ #ifdef RENDER #include "picturestr.h" #endif +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif +#ifndef MIN +#define MIN(a,b) ((a)>(b)?(b):(a)) +#endif + /* ------- mergedfb support ------------- */ /* Psuedo Xinerama support */ #define NEED_REPLIES /* ? */ #define EXTENSION_PROC_ARGS void * #include "extnsionst.h" /* required */ #include /* required */ #define RADEON_XINERAMA_MAJOR_VERSION 1 #define RADEON_XINERAMA_MINOR_VERSION 1 @@ -126,16 +133,80 @@ #endif /* Other macros */ #define RADEON_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) +typedef enum { + OPTION_NOACCEL, + OPTION_SW_CURSOR, + OPTION_DAC_6BIT, + OPTION_DAC_8BIT, +#ifdef XF86DRI + OPTION_BUS_TYPE, + OPTION_CP_PIO, + OPTION_USEC_TIMEOUT, + OPTION_AGP_MODE, + OPTION_AGP_FW, + OPTION_GART_SIZE, + OPTION_GART_SIZE_OLD, + OPTION_RING_SIZE, + OPTION_BUFFER_SIZE, + OPTION_DEPTH_MOVE, + OPTION_PAGE_FLIP, + OPTION_NO_BACKBUFFER, + OPTION_XV_DMA, + OPTION_FBTEX_PERCENT, +#endif + OPTION_PANEL_OFF, + OPTION_DDC_MODE, + OPTION_MONITOR_LAYOUT, + OPTION_IGNORE_EDID, + OPTION_FBDEV, + OPTION_MERGEDFB, + OPTION_CRT2HSYNC, + OPTION_CRT2VREFRESH, + OPTION_CRT2POS, + OPTION_METAMODES, + OPTION_MERGEDDPI, + OPTION_RADEONXINERAMA, + OPTION_CRT2ISSCRN0, + OPTION_MERGEDFBNONRECT, + OPTION_MERGEDFBMOUSER, + OPTION_DISP_PRIORITY, + OPTION_PANEL_SIZE, + OPTION_MIN_DOTCLOCK, + OPTION_COLOR_TILING, +#ifdef XvExtension + OPTION_VIDEO_KEY, + OPTION_RAGE_THEATRE_CRYSTAL, + OPTION_RAGE_THEATRE_TUNER_PORT, + OPTION_RAGE_THEATRE_COMPOSITE_PORT, + OPTION_RAGE_THEATRE_SVIDEO_PORT, + OPTION_TUNER_TYPE, + OPTION_RAGE_THEATRE_MICROC_PATH, + OPTION_RAGE_THEATRE_MICROC_TYPE, +#endif +#ifdef RENDER + OPTION_RENDER_ACCEL, + OPTION_SUBPIXEL_ORDER, +#endif + OPTION_SHOWCACHE, + OPTION_DYNAMIC_CLOCKS, + OPTION_BIOS_HOTKEYS, + OPTION_VGA_ACCESS, + OPTION_REVERSE_DDC, + OPTION_LVDS_PROBE_PLL, + OPTION_ACCELMETHOD, + OPTION_CONSTANTDPI, + OPTION_REVERSE_DISPLAY +} RADEONOpts; typedef struct { /* Common registers */ CARD32 ovr_clr; CARD32 ovr_wid_left_right; CARD32 ovr_wid_top_bottom; CARD32 ov0_scale_cntl; CARD32 mpp_tb_config; @@ -180,64 +251,69 @@ CARD32 grph_buffer_cntl; CARD32 crtc_more_cntl; /* CRTC2 registers */ CARD32 crtc2_gen_cntl; CARD32 dac2_cntl; CARD32 disp_output_cntl; + CARD32 disp_tv_out_cntl; CARD32 disp_hw_debug; CARD32 disp2_merge_cntl; CARD32 grph2_buffer_cntl; CARD32 crtc2_h_total_disp; CARD32 crtc2_h_sync_strt_wid; CARD32 crtc2_v_total_disp; CARD32 crtc2_v_sync_strt_wid; CARD32 crtc2_offset; CARD32 crtc2_offset_cntl; CARD32 crtc2_pitch; /* Flat panel registers */ CARD32 fp_crtc_h_total_disp; CARD32 fp_crtc_v_total_disp; + CARD32 fp_crtc2_h_total_disp; + CARD32 fp_crtc2_v_total_disp; CARD32 fp_gen_cntl; CARD32 fp2_gen_cntl; CARD32 fp_h_sync_strt_wid; - CARD32 fp2_h_sync_strt_wid; + CARD32 fp_h2_sync_strt_wid; CARD32 fp_horz_stretch; CARD32 fp_panel_cntl; CARD32 fp_v_sync_strt_wid; - CARD32 fp2_v_sync_strt_wid; + CARD32 fp_v2_sync_strt_wid; CARD32 fp_vert_stretch; CARD32 lvds_gen_cntl; CARD32 lvds_pll_cntl; CARD32 tmds_pll_cntl; CARD32 tmds_transmitter_cntl; /* Computed values for PLL */ CARD32 dot_clock_freq; CARD32 pll_output_freq; int feedback_div; int post_div; /* PLL registers */ unsigned ppll_ref_div; unsigned ppll_div_3; CARD32 htotal_cntl; + CARD32 vclk_cntl; /* Computed values for PLL2 */ CARD32 dot_clock_freq_2; CARD32 pll_output_freq_2; int feedback_div_2; int post_div_2; /* PLL2 registers */ CARD32 p2pll_ref_div; CARD32 p2pll_div_0; CARD32 htotal_cntl2; + CARD32 pixclks_cntl; /* Pallet */ Bool palette_valid; CARD32 palette[256]; CARD32 palette2[256]; CARD32 tv_dac_cntl; @@ -715,16 +791,18 @@ /* enable bios hotkey output switching */ Bool BiosHotkeys; Bool VGAAccess; int MaxSurfaceWidth; int MaxLines; + CARD32 tv_dac_adj; + } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ do { \ if (info->fifo_slots < entries) \ RADEONWaitForFifoFunction(pScrn, entries); \ info->fifo_slots -= entries; \ } while (0) @@ -772,16 +850,29 @@ extern void RADEONInitVideo(ScreenPtr pScreen); extern void RADEONResetVideo(ScrnInfoPtr pScrn); extern void R300CGWorkaround(ScrnInfoPtr pScrn); extern void RADEONPllErrataAfterIndex(RADEONInfoPtr info); extern void RADEONPllErrataAfterData(RADEONInfoPtr info); +extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); +extern Bool RADEONI2cInit(ScrnInfoPtr pScrn); +extern void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag); +extern Bool RADEONMapControllers(ScrnInfoPtr pScrn); +extern void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONController* pCRTC, BOOL bEnable); +extern void RADEONGetPanelInfo(ScrnInfoPtr pScrn); +extern void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn); +extern void RADEONUnblank(ScrnInfoPtr pScrn); +extern void RADEONBlank(ScrnInfoPtr pScrn); +extern void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, + int flags); + #ifdef XF86DRI #ifdef USE_XAA extern void RADEONAccelInitCP(ScreenPtr pScreen, XAAInfoRecPtr a); #endif extern Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn); extern Bool RADEONDRIScreenInit(ScreenPtr pScreen); extern void RADEONDRICloseScreen(ScreenPtr pScreen); extern void RADEONDRIResume(ScreenPtr pScreen); diff -dNau8 old-src/radeon_driver.c src/radeon_driver.c --- old-src/radeon_driver.c 2006-08-31 21:07:19.000000000 -0700 +++ src/radeon_driver.c 2006-08-31 21:51:09.000000000 -0700 @@ -1,10 +1,10 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.117 2004/02/19 22:38:12 tsi Exp $ */ -/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.92.2.17 2006-04-24 07:46:37 benh Exp $ */ +/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.88 2006-02-26 10:01:32 benh Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -86,125 +86,51 @@ /* colormap initialization */ #include "micmap.h" #include "dixstruct.h" /* X and server generic header files */ #include "xf86.h" #include "xf86_OSproc.h" +#include "xf86PciInfo.h" #include "xf86RAC.h" #include "xf86Resources.h" #include "xf86cmap.h" #include "vbe.h" /* fbdevhw * vgaHW definitions */ #ifdef WITH_VGAHW #include "vgaHW.h" #endif #include "fbdevhw.h" #define DPMS_SERVER #include -#include "atipciids.h" #include "radeon_chipset.h" -#ifndef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) -#endif -#ifndef MIN -#define MIN(a,b) ((a)>(b)?(b):(a)) -#endif /* Forward definitions for driver functions */ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode); static void RADEONSave(ScrnInfoPtr pScrn); static void RADEONRestore(ScrnInfoPtr pScrn); static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); -static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, - int flags); -static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn); static int RADEONValidateMergeModes(ScrnInfoPtr pScrn); static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode); -static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn); static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); /* psuedo xinerama support */ extern Bool RADEONnoPanoramiXExtension; -typedef enum { - OPTION_NOACCEL, - OPTION_SW_CURSOR, - OPTION_DAC_6BIT, - OPTION_DAC_8BIT, -#ifdef XF86DRI - OPTION_BUS_TYPE, - OPTION_CP_PIO, - OPTION_USEC_TIMEOUT, - OPTION_AGP_MODE, - OPTION_AGP_FW, - OPTION_GART_SIZE, - OPTION_GART_SIZE_OLD, - OPTION_RING_SIZE, - OPTION_BUFFER_SIZE, - OPTION_DEPTH_MOVE, - OPTION_PAGE_FLIP, - OPTION_NO_BACKBUFFER, - OPTION_XV_DMA, - OPTION_FBTEX_PERCENT, -#endif - OPTION_PANEL_OFF, - OPTION_DDC_MODE, - OPTION_MONITOR_LAYOUT, - OPTION_IGNORE_EDID, - OPTION_FBDEV, - OPTION_MERGEDFB, - OPTION_CRT2HSYNC, - OPTION_CRT2VREFRESH, - OPTION_CRT2POS, - OPTION_METAMODES, - OPTION_MERGEDDPI, - OPTION_RADEONXINERAMA, - OPTION_CRT2ISSCRN0, - OPTION_MERGEDFBNONRECT, - OPTION_MERGEDFBMOUSER, - OPTION_DISP_PRIORITY, - OPTION_PANEL_SIZE, - OPTION_MIN_DOTCLOCK, - OPTION_COLOR_TILING, -#ifdef XvExtension - OPTION_VIDEO_KEY, - OPTION_RAGE_THEATRE_CRYSTAL, - OPTION_RAGE_THEATRE_TUNER_PORT, - OPTION_RAGE_THEATRE_COMPOSITE_PORT, - OPTION_RAGE_THEATRE_SVIDEO_PORT, - OPTION_TUNER_TYPE, - OPTION_RAGE_THEATRE_MICROC_PATH, - OPTION_RAGE_THEATRE_MICROC_TYPE, -#endif -#ifdef RENDER - OPTION_RENDER_ACCEL, - OPTION_SUBPIXEL_ORDER, -#endif - OPTION_SHOWCACHE, - OPTION_DYNAMIC_CLOCKS, - OPTION_BIOS_HOTKEYS, - OPTION_VGA_ACCESS, - OPTION_REVERSE_DDC, - OPTION_LVDS_PROBE_PLL, - OPTION_ACCELMETHOD -} RADEONOpts; - static const OptionInfoRec RADEONOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, #ifdef XF86DRI { OPTION_BUS_TYPE, "BusType", OPTV_ANYSTR, {0}, FALSE }, { OPTION_CP_PIO, "CPPIOMode", OPTV_BOOLEAN, {0}, FALSE }, @@ -214,17 +140,16 @@ { OPTION_GART_SIZE_OLD, "AGPSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_GART_SIZE, "GARTSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_DEPTH_MOVE, "EnableDepthMoves", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NO_BACKBUFFER, "NoBackBuffer", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_XV_DMA, "DMAForXv", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_FBTEX_PERCENT, "FBTexPercent", OPTV_INTEGER, {0}, FALSE }, #endif { OPTION_PANEL_OFF, "PanelOff", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DDC_MODE, "DDCMode", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR, {0}, FALSE }, { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_MERGEDFB, "MergedFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CRT2HSYNC, "CRT2HSync", OPTV_ANYSTR, {0}, FALSE }, @@ -256,16 +181,17 @@ #endif { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DYNAMIC_CLOCKS, "DynamicClocks", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_BIOS_HOTKEYS, "BIOSHotkeys", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VGA_ACCESS, "VGAAccess", OPTV_BOOLEAN, {0}, TRUE }, { OPTION_REVERSE_DDC, "ReverseDDC", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, + { OPTION_REVERSE_DISPLAY,"ReverseDisplay", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; _X_EXPORT const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions; } #ifdef WITH_VGAHW static const char *vgahwSymbols[] = { "vgaHWFreeHWRec", @@ -501,38 +427,16 @@ {640, 480, 75}, {640, 480, 72}, {640, 480, 67}, {640, 480, 60}, {720, 400, 88}, {720, 400, 70}, }; -static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = -{ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ - {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ - {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x400f7/*0x40111*/}, {0, 0}}, /*CHIP_FAMILY_RV280*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ -}; - #ifdef XFree86LOADER static int getRADEONEntityIndex(void) { int *radeon_entity_index = LoaderSymbol("gRADEONEntityIndex"); if (!radeon_entity_index) return -1; else return *radeon_entity_index; @@ -865,483 +769,61 @@ } #endif /* Wait for vertical sync on primary CRTC */ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 crtc_gen_cntl; int i; - crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); - if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || - !(crtc_gen_cntl & RADEON_CRTC_EN)) - return; - /* Clear the CRTC_VBLANK_SAVE bit */ OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ for (i = 0; i < RADEON_TIMEOUT/1000; i++) { if (INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) break; usleep(1); } } /* Wait for vertical sync on secondary CRTC */ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 crtc2_gen_cntl; int i; - - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); - if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || - !(crtc2_gen_cntl & RADEON_CRTC2_EN)) - return; /* Clear the CRTC2_VBLANK_SAVE bit */ OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ for (i = 0; i < RADEON_TIMEOUT/1000; i++) { if (INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) break; usleep(1); } } -/* Blank screen */ -static void RADEONBlank(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (!info->IsSecondary) { - switch(info->DisplayType) { - case MT_LCD: - case MT_CRT: - case MT_DFP: - OUTREGP(RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_DISPLAY_DIS, - ~(RADEON_CRTC_DISPLAY_DIS)); - break; - - case MT_NONE: - default: - break; - } - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS, - ~(RADEON_CRTC2_DISP_DIS)); - } else { - OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS, - ~(RADEON_CRTC2_DISP_DIS)); - } -} - -/* Unblank screen */ -static void RADEONUnblank(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (!info->IsSecondary) { - switch (info->DisplayType) { - case MT_LCD: - case MT_CRT: - case MT_DFP: - OUTREGP(RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_CRT_ON, - ~(RADEON_CRTC_DISPLAY_DIS)); - break; - - case MT_NONE: - default: - break; - } - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - 0, - ~(RADEON_CRTC2_DISP_DIS)); - } else { - switch (info->DisplayType) { - case MT_LCD: - case MT_DFP: - case MT_CRT: - OUTREGP(RADEON_CRTC2_GEN_CNTL, - 0, - ~(RADEON_CRTC2_DISP_DIS)); - break; - - case MT_NONE: - default: - break; - } - } -} - /* Compute log base 2 of val */ int RADEONMinBits(int val) { int bits; if (!val) return 1; for (bits = 0; val; val >>= 1, ++bits); return bits; } /* Compute n/d with rounding */ static int RADEONDiv(int n, int d) { return (n + (d / 2)) / d; } -static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, RADEONConnector* port) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - unsigned long DDCReg; - RADEONMonitorType MonType = MT_NONE; - xf86MonPtr* MonInfo = &port->MonInfo; - int i, j; - - DDCReg = info->DDCReg; - switch(DDCType) - { - case DDC_MONID: - info->DDCReg = RADEON_GPIO_MONID; - break; - case DDC_DVI: - info->DDCReg = RADEON_GPIO_DVI_DDC; - break; - case DDC_VGA: - info->DDCReg = RADEON_GPIO_VGA_DDC; - break; - case DDC_CRT2: - info->DDCReg = RADEON_GPIO_CRT2_DDC; - break; - default: - info->DDCReg = DDCReg; - return MT_NONE; - } - - /* Read and output monitor info using DDC2 over I2C bus */ - if (info->pI2CBus && info->ddc2) { - OUTREG(info->DDCReg, INREG(info->DDCReg) & - (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); - - /* For some old monitors (like Compaq Presario FP500), we need - * following process to initialize/stop DDC - */ - OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (j = 0; j < 3; j++) { - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(13000); - - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 10; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - if (i == 10) continue; - - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 5; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - if(*MonInfo) break; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); - MonType = MT_NONE; - } - - OUTREG(info->DDCReg, INREG(info->DDCReg) & - ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); - - if (*MonInfo) { - if ((*MonInfo)->rawData[0x14] & 0x80) { - /* Note some laptops have a DVI output that uses internal TMDS, - * when its DVI is enabled by hotkey, LVDS panel is not used. - * In this case, the laptop is configured as DVI+VGA as a normal - * desktop card. - * Also for laptop, when X starts with lid closed (no DVI connection) - * both LDVS and TMDS are disable, we still need to treat it as a LVDS panel. - */ - if (port->TMDSType == TMDS_EXT) MonType = MT_DFP; - else { - if ((INREG(RADEON_FP_GEN_CNTL) & (1<<7)) || !info->IsMobility) - MonType = MT_DFP; - else - MonType = MT_LCD; - } - } else MonType = MT_CRT; - } else MonType = MT_NONE; - - info->DDCReg = DDCReg; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DDC Type: %d, Detected Type: %d\n", DDCType, MonType); - - return MonType; -} - -static RADEONMonitorType -RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int bConnected = 0; - - /* the monitor either wasn't connected or it is a non-DDC CRT. - * try to probe it - */ - if(IsCrtDac) { - unsigned long ulOrigVCLK_ECP_CNTL; - unsigned long ulOrigDAC_CNTL; - unsigned long ulOrigDAC_EXT_CNTL; - unsigned long ulOrigCRTC_EXT_CNTL; - unsigned long ulData; - unsigned long ulMask; - - ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - - ulData = ulOrigVCLK_ECP_CNTL; - ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb - | RADEON_PIXCLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb - |RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); - ulData = ulOrigCRTC_EXT_CNTL; - ulData |= RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, ulData); - - ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); - ulData = ulOrigDAC_EXT_CNTL; - ulData &= ~RADEON_DAC_FORCE_DATA_MASK; - ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN - |RADEON_DAC_FORCE_DATA_EN - |RADEON_DAC_FORCE_DATA_SEL_MASK); - if ((info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) - ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); - else - ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); - - OUTREG(RADEON_DAC_EXT_CNTL, ulData); - - ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); - ulData = ulOrigDAC_CNTL; - ulData |= RADEON_DAC_CMP_EN; - ulData &= ~(RADEON_DAC_RANGE_CNTL_MASK - | RADEON_DAC_PDWN); - ulData |= 0x2; - OUTREG(RADEON_DAC_CNTL, ulData); - - usleep(10000); - - ulData = INREG(RADEON_DAC_CNTL); - bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; - - ulData = ulOrigVCLK_ECP_CNTL; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); - OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); - OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); - } else { /* TV DAC */ - - /* This doesn't seem to work reliably (maybe worse on some OEM cards), - for now we always return false. If one wants to connected a - non-DDC monitor on the DVI port when CRT port is also connected, - he will need to explicitly tell the driver in the config file - with Option MonitorLayout. - */ - bConnected = FALSE; - -#if 0 - if (info->ChipFamily == CHIP_FAMILY_R200) { - unsigned long ulOrigGPIO_MONID; - unsigned long ulOrigFP2_GEN_CNTL; - unsigned long ulOrigDISP_OUTPUT_CNTL; - unsigned long ulOrigCRTC2_GEN_CNTL; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; - unsigned long ulOrigCRTC2_H_TOTAL_DISP; - unsigned long ulOrigCRTC2_V_TOTAL_DISP; - unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; - unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; - unsigned long ulData, i; - - ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); - ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); - ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); - ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); - ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); - ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); - ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); - ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); - ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); - ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); - - ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); - ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); - ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); - ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); - - ulData = INREG(RADEON_GPIO_MONID); - ulData &= ~RADEON_GPIO_A_0; - OUTREG(RADEON_GPIO_MONID, ulData); - - OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); - - OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); - - OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); - - for (i = 0; i < 200; i++) { - ulData = INREG(RADEON_GPIO_MONID); - bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; - if (!bConnected) break; - - usleep(1000); - } - - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); - OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); - OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); - OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); - } else { - unsigned long ulOrigPIXCLKSDATA; - unsigned long ulOrigTV_MASTER_CNTL; - unsigned long ulOrigTV_DAC_CNTL; - unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; - unsigned long ulOrigDAC_CNTL2; - unsigned long ulData; - unsigned long ulMask; - - ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - - ulData = ulOrigPIXCLKSDATA; - ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); - ulData = ulOrigTV_MASTER_CNTL; - ulData &= ~RADEON_TVCLK_ALWAYS_ONb; - OUTREG(RADEON_TV_MASTER_CNTL, ulData); - - ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); - ulData = ulOrigDAC_CNTL2; - ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; - OUTREG(RADEON_DAC_CNTL2, ulData); - - ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); - - ulData = 0x00880213; - OUTREG(RADEON_TV_DAC_CNTL, ulData); - - ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); - - ulData = (RADEON_Y_RED_EN - | RADEON_C_GRN_EN - | RADEON_CMP_BLU_EN - | RADEON_RED_MX_FORCE_DAC_DATA - | RADEON_GRN_MX_FORCE_DAC_DATA - | RADEON_BLU_MX_FORCE_DAC_DATA); - if (IS_R300_VARIANT) - ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - else - ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); - - usleep(10000); - - ulData = INREG(RADEON_TV_DAC_CNTL); - bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; - - ulData = ulOrigPIXCLKSDATA; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); - OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); - OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); - } -#endif - } - - return(bConnected ? MT_CRT : MT_NONE); -} - static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPLLPtr pll = &info->pll; unsigned char *RADEONMMIO = info->MMIO; unsigned char ppll_div_sel; unsigned mpll_fb_div, spll_fb_div, M; unsigned xclk, tmp, ref_div; @@ -1534,165 +1016,16 @@ pll->reference_freq = xtal; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probed PLL values: xtal: %f Mhz, " "sclk: %f Mhz, mclk: %f Mhz\n", xtal/100.0, info->sclk, info->mclk); return TRUE; } -static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); - CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); - - info->PanelPwrDly = 200; - if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { - info->PanelYRes = (fp_vert_stretch>>12) + 1; - } else { - info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; - } - if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { - info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; - } else { - info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; - } - - if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { - info->PanelXRes = 640; - info->PanelYRes = 480; - } - - if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { - CARD32 ppll_div_sel, ppll_val; - - ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; - RADEONPllErrataAfterIndex(info); - ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); - if ((ppll_val & 0x000707ff) == 0x1bb) - goto noprobe; - info->FeedbackDivider = ppll_val & 0x7ff; - info->PostDivider = (ppll_val >> 16) & 0x7; - info->RefDivider = info->pll.reference_div; - info->UseBiosDividers = TRUE; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Existing panel PLL dividers will be used.\n"); - } - noprobe: - - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Panel size %dx%d is derived, this may not be correct.\n" - "If not, use PanelSize option to overwrite this setting\n", - info->PanelXRes, info->PanelYRes); -} - -static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (!RADEONGetLVDSInfoFromBIOS(pScrn)) - RADEONGetPanelInfoFromReg(pScrn); - - /* The panel size we collected from BIOS may not be the - * maximum size supported by the panel. If not, we update - * it now. These will be used if no matching mode can be - * found from EDID data. - */ - RADEONUpdatePanelSize(pScrn); - - /* No timing information for the native mode, - * use whatever specified in the Modeline. - * If no Modeline specified, we'll just pick - * the VESA mode at 60Hz refresh rate which - * is likely to be the best for a flat panel. - */ - if (info->DotClock == 0) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - DisplayModePtr tmp_mode = NULL; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No valid timing info from BIOS.\n"); - tmp_mode = pScrn->monitor->Modes; - while(tmp_mode) { - if ((tmp_mode->HDisplay == info->PanelXRes) && - (tmp_mode->VDisplay == info->PanelYRes)) { - - float refresh = - (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; - if ((abs(60.0 - refresh) < 1.0) || - (tmp_mode->type == 0)) { - info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; - info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; - info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; - info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; - info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; - info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; - info->DotClock = tmp_mode->Clock; - info->Flags = 0; - break; - } - } - tmp_mode = tmp_mode->next; - } - if ((info->DotClock == 0) && !pRADEONEnt->PortInfo[0].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Panel size is not correctly detected.\n" - "Please try to use PanelSize option for correct settings.\n"); - return FALSE; - } - } - - return TRUE; -} - -static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - int i; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = 0; - info->tmds_pll[i].freq = 0; - } - - if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; - info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; - } -} - -static void RADEONGetPanelInfo (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - char* s; - - if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - info->PanelPwrDly = 200; - if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); - RADEONGetPanelInfoFromReg(pScrn); - } - } else { - - if(info->DisplayType == MT_LCD) { - RADEONGetLVDSInfo(pScrn); - } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { - RADEONGetTMDSInfo(pScrn); - if (!pScrn->monitor->DDC) - RADEONGetHardCodedEDIDFromBIOS(pScrn); - else if (!info->IsSecondary) - RADEONUpdatePanelSize(pScrn); - } - } -} - static void RADEONGetClockInfo(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR (pScrn); RADEONPLLPtr pll = &info->pll; double min_dotclock; if (RADEONGetClockInfoFromBIOS(pScrn)) { if (pll->reference_div < 2) { @@ -1735,25 +1068,16 @@ pll->reference_div = 12; pll->xclk = 10300; info->sclk = 200.00; info->mclk = 200.00; } - if (info->ChipFamily == CHIP_FAMILY_RV100 && !info->HasCRTC2) { - /* Avoid RN50 corruption due to memory bandwidth starvation. - * 18 is an empirical value based on the databook and Windows driver. - */ - pll->max_pll_freq = min(pll->max_pll_freq, - 18 * info->mclk * 100 / pScrn->bitsPerPixel * - info->RamWidth / 16); - } - xf86DrvMsg (pScrn->scrnIndex, X_INFO, "PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n", pll->reference_freq, pll->reference_div, pll->min_pll_freq, pll->max_pll_freq, pll->xclk); /* (Some?) Radeon BIOSes seem too lie about their minimum dot * clocks. Allow users to override the detected minimum dot clock @@ -1771,432 +1095,16 @@ "Forced minimum dotclock to %.2f MHz " "(instead of detected %.2f MHz)\n", min_dotclock, ((double)pll->min_pll_freq/1000)); pll->min_pll_freq = min_dotclock * 1000; } } } -static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - const char *s; - Bool ignore_edid = FALSE; - int i = 0, second = 0, max_mt; - - const char *MonTypeName[7] = - { - "AUTO", - "NONE", - "CRT", - "LVDS", - "TMDS", - "CTV", - "STV" - }; - - const RADEONMonitorType MonTypeID[7] = - { - MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ - MT_NONE, /* NONE -> NONE */ - MT_CRT, /* CRT -> CRT */ - MT_LCD, /* Laptop LCDs are driven via LVDS port */ - MT_DFP, /* DFPs are driven via TMDS */ - MT_CTV, /* CTV -> CTV */ - MT_STV, /* STV -> STV */ - }; - - const char *TMDSTypeName[3] = - { - "NONE", - "Internal", - "External" - }; - - const char *DDCTypeName[5] = - { - "NONE", - "MONID", - "DVI_DDC", - "VGA_DDC", - "CRT2_DDC" - }; - - const char *DACTypeName[3] = - { - "Unknown", - "Primary", - "TVDAC/ExtDAC", - }; - - const char *ConnectorTypeName[8] = - { - "None", - "Proprietary", - "VGA", - "DVI-I", - "DVI-D", - "CTV", - "STV", - "Unsupported" - }; - - const char *ConnectorTypeNameATOM[10] = - { - "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "STV", - "CTV", - "LVDS", - "Digital", - "Unsupported" - }; - - max_mt = 5; - - if(info->IsSecondary) { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; - if(info->DisplayType == MT_NONE) return FALSE; - return TRUE; - } - - - /* We first get the information about all connectors from BIOS. - * This is how the card is phyiscally wired up. - * The information should be correct even on a OEM card. - * If not, we may have problem -- need to use MonitorLayout option. - */ - for (i = 0; i < 2; i++) { - pRADEONEnt->PortInfo[i].MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[i].MonInfo = NULL; - pRADEONEnt->PortInfo[i].DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[i].DACType = DAC_UNKNOWN; - pRADEONEnt->PortInfo[i].TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[i].ConnectorType = CONNECTOR_NONE; - } - - if (!RADEONGetConnectorInfoFromBIOS(pScrn)) { - /* Below is the most common setting, but may not be true */ - pRADEONEnt->PortInfo[0].MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[0].MonInfo = NULL; - pRADEONEnt->PortInfo[0].DDCType = DDC_DVI; - pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; - pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_DVI_D; - - pRADEONEnt->PortInfo[1].MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[1].MonInfo = NULL; - pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; - pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT; - pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; - - /* Some cards have the DDC lines swapped and we have no way to - * detect it yet (Mac cards) - */ - if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { - pRADEONEnt->PortInfo[0].DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1].DDCType = DDC_DVI; - } - } - - /* always make TMDS_INT port first*/ - if (pRADEONEnt->PortInfo[1].TMDSType == TMDS_INT) { - RADEONConnector connector; - connector = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = connector; - } else if ((pRADEONEnt->PortInfo[0].TMDSType != TMDS_INT && - pRADEONEnt->PortInfo[1].TMDSType != TMDS_INT)) { - /* no TMDS_INT port, make primary DAC port first */ - /* On my Inspiron 8600 both internal and external ports are - marked DAC_PRIMARY in BIOS. So be extra careful - only - swap when the first port is not DAC_PRIMARY */ - if ( (pRADEONEnt->PortInfo[1].DACType == DAC_PRIMARY) && - (pRADEONEnt->PortInfo[0].DACType != DAC_PRIMARY)) { - RADEONConnector connector; - connector = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = connector; - } - } - - if (info->HasSingleDAC) { - /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ - if (pRADEONEnt->PortInfo[0].ConnectorType == CONNECTOR_CRT) { - pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; - } else { - pRADEONEnt->PortInfo[1].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; - } - } else if (!info->HasCRTC2) { - pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; - } - - /* IgnoreEDID option is different from the NoDDCxx options used by DDC module - * When IgnoreEDID is used, monitor detection will still use DDC - * detection, but all EDID data will not be used in mode validation. - * You can use this option when you have a DDC monitor but want specify your own - * monitor timing parameters by using HSync, VRefresh and Modeline, - */ - if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { - if (ignore_edid) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "IgnoreEDID is specified, EDID data will be ignored\n"); - } - - /* - * MonitorLayout option takes a string for two monitors connected in following format: - * Option "MonitorLayout" "primary-port-display, secondary-port-display" - * primary and secondary port displays can have one of following: - * NONE, CRT, LVDS, TMDS - * With this option, driver will bring up monitors as specified, - * not using auto-detection routines to probe monitors. - * - * This option can be used when the false monitor detection occurs. - * - * This option can also be used to disable one connected display. - * For example, if you have a laptop connected to an external CRT - * and you want to disable the internal LCD panel, you can specify - * Option "MonitorLayout" "NONE, CRT" - * - * This option can also used to disable Clone mode. One there is only - * one monitor is specified, clone mode will be turned off automatically - * even you have two monitors connected. - * - * Another usage of this option is you want to config the server - * to start up with a certain monitor arrangement even one monitor - * is not plugged in when server starts. - */ - if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { - char s1[5], s2[5]; - i = 0; - /* When using user specified monitor types, we will not do DDC detection - * - */ - do { - switch(*s) { - case ',': - s1[i] = '\0'; - i = 0; - second = 1; - break; - case ' ': - case '\t': - case '\n': - case '\r': - break; - default: - if (second) - s2[i] = *s; - else - s1[i] = *s; - i++; - break; - } - if (i > 4) i = 4; - } while(*s++); - s2[i] = '\0'; - - for (i = 0; i < max_mt; i++) { - if (strcmp(s1, MonTypeName[i]) == 0) { - pRADEONEnt->PortInfo[0].MonType = MonTypeID[i]; - break; - } - } - for (i = 0; i < max_mt; i++) { - if (strcmp(s2, MonTypeName[i]) == 0) { - pRADEONEnt->PortInfo[1].MonType = MonTypeID[i]; - break; - } - } - - if (i == max_mt) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 2nd port \n"); - - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2); - - if (pRADEONEnt->PortInfo[1].MonType == MT_CRT) { - pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; - pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; - pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[0].ConnectorType = pRADEONEnt->PortInfo[0].MonType+1; - pRADEONEnt->PortInfo[0].MonInfo = NULL; - } - - if (!ignore_edid) { - if ((pRADEONEnt->PortInfo[0].MonType > MT_NONE) && - (pRADEONEnt->PortInfo[0].MonType < MT_STV)) - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, - &pRADEONEnt->PortInfo[0]); - if ((pRADEONEnt->PortInfo[1].MonType > MT_NONE) && - (pRADEONEnt->PortInfo[1].MonType < MT_STV)) - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, - &pRADEONEnt->PortInfo[1]); - } - - } - - if(((!info->HasCRTC2) || info->IsDellServer)) { - if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { - if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0]))); - else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0]))); - else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0]))); - else - pRADEONEnt->PortInfo[0].MonType = MT_CRT; - } - - if (!ignore_edid) { - if (pRADEONEnt->PortInfo[0].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } - } - - pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; - pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - info->MergeType = MT_NONE; - info->DisplayType = pRADEONEnt->MonType1; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); - - return TRUE; - } - - if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { - - /* Primary Head (DVI or Laptop Int. panel)*/ - /* A ddc capable display connected on DVI port */ - if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { - if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, &pRADEONEnt->PortInfo[0]))); - else if (info->IsMobility && - (INREG(RADEON_BIOS_4_SCRATCH) & 4)) { - /* non-DDC laptop panel connected on primary */ - pRADEONEnt->PortInfo[0].MonType = MT_LCD; - } else { - /* CRT on DVI, TODO: not reliable, make it always return false for now*/ - pRADEONEnt->PortInfo[0].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[0].DACType)); - } - } - - /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ - if (pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { - if((pRADEONEnt->PortInfo[1].MonType = - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, &pRADEONEnt->PortInfo[1]))); - else if (info->IsMobility && - (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON)) { - /* non-DDC TMDS panel connected through DVO */ - pRADEONEnt->PortInfo[1].MonType = MT_DFP; - } else - pRADEONEnt->PortInfo[1].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[1].DACType)); - } - } - - if(ignore_edid) { - pRADEONEnt->PortInfo[0].MonInfo = NULL; - pRADEONEnt->PortInfo[1].MonInfo = NULL; - } else { - if (pRADEONEnt->PortInfo[0].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 1 ----------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); - } - - if (pRADEONEnt->PortInfo[1].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 2-----------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[1].MonInfo ); - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); - - pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; - pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; - pRADEONEnt->MonType2 = pRADEONEnt->PortInfo[1].MonType; - pRADEONEnt->MonInfo2 = pRADEONEnt->PortInfo[1].MonInfo; - if (pRADEONEnt->PortInfo[0].MonType == MT_NONE) { - if (pRADEONEnt->PortInfo[1].MonType == MT_NONE) { - pRADEONEnt->MonType1 = MT_CRT; - pRADEONEnt->MonInfo1 = NULL; - } else { - RADEONConnector tmp; - pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[1].MonType; - pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[1].MonInfo; - tmp = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = tmp; - } - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - } - - info->DisplayType = pRADEONEnt->MonType1; - pRADEONEnt->ReversedDAC = FALSE; - info->OverlayOnCRTC2 = FALSE; - info->MergeType = MT_NONE; - if (pRADEONEnt->MonType2 != MT_NONE) { - if(!pRADEONEnt->HasSecondary) { - info->MergeType = pRADEONEnt->MonType2; - } - - if (pRADEONEnt->PortInfo[1].DACType == DAC_TVDAC) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DAC decteced\n"); - pRADEONEnt->ReversedDAC = TRUE; - } - } else { - pRADEONEnt->HasSecondary = FALSE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Secondary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[1].MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[1].ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[1].ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[1].DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[1].TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[1].DDCType]); - - return TRUE; -} - - /* This is called by RADEONPreInit to set up the default visual */ static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) return FALSE; @@ -2303,55 +1211,31 @@ /* We shouldn't use info->videoRam here which might have been clipped * but the real video RAM instead */ mem_size = INREG(RADEON_CONFIG_MEMSIZE); if (mem_size == 0) mem_size = 0x800000; -#ifdef XF86DRI - /* Apply memory map limitation if using an old DRI */ - if (info->directRenderingEnabled && !info->newMemoryMap) { - CARD32 aper_size = INREG(RADEON_CONFIG_APER_SIZE); - if (aper_size < mem_size) - mem_size = aper_size; - } -#endif /* We won't try to change MC_FB_LOCATION when using fbdev */ if (!info->FBDev) { if (info->IsIGP) info->mc_fb_location = INREG(RADEON_NB_TOM); else #ifdef XF86DRI /* Old DRI has restrictions on the memory map */ - if ( info->directRenderingEnabled && - info->pKernelDRMVersion->version_minor < 10 ) + if ( info->directRenderingEnabled && 0 ) info->mc_fb_location = (mem_size - 1) & 0xffff0000U; else #endif { CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE); - /* Recent chips have an "issue" with the memory controller, the - * location must be aligned to the size. We just align it down, - * too bad if we walk over the top of system memory, we don't - * use DMA without a remapped anyway. - * Affected chips are rv280, all r3xx, and all r4xx, but not IGP - */ - if (info->ChipFamily == CHIP_FAMILY_RV280 || - info->ChipFamily == CHIP_FAMILY_R300 || - info->ChipFamily == CHIP_FAMILY_R350 || - info->ChipFamily == CHIP_FAMILY_RV350 || - info->ChipFamily == CHIP_FAMILY_RV380 || - info->ChipFamily == CHIP_FAMILY_R420 || - info->ChipFamily == CHIP_FAMILY_RV410) - aper0_base &= ~(mem_size - 1); - info->mc_fb_location = (aper0_base >> 16) | ((aper0_base + mem_size - 1) & 0xffff0000U); } } info->fbLocation = (info->mc_fb_location & 0xffff) << 16; /* Just disable the damn AGP apertures for now, it may be * re-enabled later by the DRM @@ -2387,20 +1271,16 @@ case 2: info->RamWidth = 256; break; default: info->RamWidth = 128; break; } } else if ((info->ChipFamily == CHIP_FAMILY_RV100) || (info->ChipFamily == CHIP_FAMILY_RS100) || (info->ChipFamily == CHIP_FAMILY_RS200)){ if (tmp & RV100_HALF_MODE) info->RamWidth = 32; else info->RamWidth = 64; - if (!info->HasCRTC2) { - info->RamWidth /= 4; - info->IsDDR = TRUE; - } } else { if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) info->RamWidth = 128; else info->RamWidth = 64; } /* This may not be correct, as some cards can have half of channel disabled * ToDo: identify these cases */ @@ -2415,44 +1295,23 @@ { RADEONInfoPtr info = RADEONPTR(pScrn); EntityInfoPtr pEnt = info->pEnt; GDevPtr dev = pEnt->device; MessageType from; unsigned char *RADEONMMIO = info->MMIO; CARD32 aper_size = INREG(RADEON_CONFIG_APER_SIZE) / 1024; -#ifdef XF86DRI - /* If we use the DRI, we need to check if it's a version that has the - * bug of always cropping MC_FB_LOCATION to one aperture, in which case - * we need to limit the amount of accessible video memory - */ - if (info->directRenderingEnabled && - info->pKernelDRMVersion->version_minor < 23) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[dri] limiting video memory to one aperture of %dK\n", - aper_size); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[dri] detected radeon kernel module version 1.%d but" - " 1.23 or newer is required for full memory mapping.\n", - info->pKernelDRMVersion->version_minor); - info->newMemoryMap = FALSE; - return aper_size; - } - info->newMemoryMap = TRUE; -#endif /* XF86DRI */ - /* Set HDP_APER_CNTL only on cards that are known not to be broken, * that is has the 2nd generation multifunction PCI interface */ if (info->ChipFamily == CHIP_FAMILY_RV280 || info->ChipFamily == CHIP_FAMILY_RV350 || info->ChipFamily == CHIP_FAMILY_RV380 || - info->ChipFamily == CHIP_FAMILY_R420 || - info->ChipFamily == CHIP_FAMILY_RV410) { + info->ChipFamily == CHIP_FAMILY_R420) { OUTREGP (RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, ~RADEON_HDP_APER_CNTL); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Generation 2 PCI interface, using max accessible memory\n"); return aper_size * 2; } /* Older cards have all sorts of funny issues to deal with. First @@ -2471,133 +1330,33 @@ * we expect the BIOS to have done the right thing (might be too optimistic...) */ if (INREG(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) return aper_size * 2; return aper_size; } -static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - EntityInfoPtr pEnt = info->pEnt; - GDevPtr dev = pEnt->device; - unsigned char *RADEONMMIO = info->MMIO; - MessageType from = X_PROBED; - - if (info->FBDev) - pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; - else if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { - CARD32 tom = INREG(RADEON_NB_TOM); - - pScrn->videoRam = (((tom >> 16) - - (tom & 0xffff) + 1) << 6); - - OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024); - } else { - CARD32 accessible; - CARD32 bar_size; - - /* Read VRAM size from card */ - pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; - - /* Some production boards of m6 will return 0 if it's 8 MB */ - if (pScrn->videoRam == 0) { - pScrn->videoRam = 8192; - OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000); - } - - /* Get accessible memory */ - accessible = RADEONGetAccessibleVRAM(pScrn); - - /* Crop it to the size of the PCI BAR */ - bar_size = (1ul << info->PciInfo->size[0]) / 1024; - if (bar_size == 0) - bar_size = 0x20000; - if (accessible > bar_size) - accessible = bar_size; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected total video RAM=%dK, accessible=%dK " - "(PCI BAR=%dK)\n", - pScrn->videoRam, accessible, bar_size); - if (pScrn->videoRam > accessible) - pScrn->videoRam = accessible; - } - - info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); - info->BusCntl = INREG(RADEON_BUS_CNTL); - - RADEONGetVRamType(pScrn); - - if (dev->videoRam) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Video RAM override, using %d kB instead of %d kB\n", - dev->videoRam, - pScrn->videoRam); - from = X_CONFIG; - pScrn->videoRam = dev->videoRam; - } - - xf86DrvMsg(pScrn->scrnIndex, from, - "Mapped VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); - - /* FIXME: For now, split FB into two equal sections. This should - * be able to be adjusted by user with a config option. */ - if (info->IsPrimary) { - pScrn->videoRam /= 2; - info->MergedFB = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %dk of videoram for primary head\n", - pScrn->videoRam); - } - - if (info->IsSecondary) { - pScrn->videoRam /= 2; - info->LinearAddr += pScrn->videoRam * 1024; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %dk of videoram for secondary head\n", - pScrn->videoRam); - } - - pScrn->videoRam &= ~1023; - info->FbMapSize = pScrn->videoRam * 1024; - - /* if the card is PCI Express reserve the last 32k for the gart table */ -#ifdef XF86DRI - if (info->cardType == CARD_PCIE && info->directRenderingEnabled) - info->FbSecureSize = RADEON_PCIGART_TABLE_SIZE; - else -#endif - info->FbSecureSize = 0; - - return TRUE; -} - - /* This is called by RADEONPreInit to handle config file overrides for * things like chipset and memory regions. Also determine memory size * and type. If memory type ever needs an override, put it in this * routine. */ -static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) +static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); EntityInfoPtr pEnt = info->pEnt; GDevPtr dev = pEnt->device; + MessageType from; unsigned char *RADEONMMIO = info->MMIO; - MessageType from = X_PROBED; #ifdef XF86DRI const char *s; #endif - /* Chipset */ + /* Chipset */ from = X_PROBED; if (dev->chipset && *dev->chipset) { info->Chipset = xf86StringToToken(RADEONChipsets, dev->chipset); from = X_CONFIG; } else if (dev->chipID >= 0) { info->Chipset = dev->chipID; from = X_CONFIG; } else { @@ -2627,21 +1386,20 @@ info->HasSingleDAC = FALSE; switch (info->Chipset) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ: info->IsMobility = TRUE; info->ChipFamily = CHIP_FAMILY_RV100; break; - case PCI_CHIP_RN50_515E: /* RN50 is based on the RV100 but 3D isn't guaranteed to work. YMMV. */ - case PCI_CHIP_RN50_5969: - info->HasCRTC2 = FALSE; case PCI_CHIP_RV100_QY: case PCI_CHIP_RV100_QZ: + case PCI_CHIP_RN50_515E: /* RN50 is based on the RV100 but 3D isn't guaranteed to work. YMMV. */ + case PCI_CHIP_RN50_5969: info->ChipFamily = CHIP_FAMILY_RV100; /* DELL triple-head configuration. */ if ((info->PciInfo->subsysVendor == PCI_VENDOR_DELL) && ((info->PciInfo->subsysCard == 0x016c) || (info->PciInfo->subsysCard == 0x016d) || (info->PciInfo->subsysCard == 0x016e) || (info->PciInfo->subsysCard == 0x016f) || @@ -2863,16 +1621,17 @@ break; default: /* Original Radeon/7200 */ info->ChipFamily = CHIP_FAMILY_RADEON; info->HasCRTC2 = FALSE; } + /* Framebuffer */ from = X_PROBED; info->LinearAddr = info->PciInfo->memBase[0] & 0xfe000000; pScrn->memPhysBase = info->LinearAddr; if (dev->MemBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Linear address override, using 0x%08lx instead of 0x%08lx\n", dev->MemBase, @@ -2899,16 +1658,49 @@ from = X_CONFIG; } if (info->BIOSAddr) { xf86DrvMsg(pScrn->scrnIndex, from, "BIOS at 0x%08lx\n", info->BIOSAddr); } /* Read registers used to determine options */ + from = X_PROBED; + if (info->FBDev) + pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; + else if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + CARD32 tom = INREG(RADEON_NB_TOM); + + pScrn->videoRam = (((tom >> 16) - + (tom & 0xffff) + 1) << 6); + + OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024); + } else { + CARD32 accessible; + + /* Read VRAM size from card */ + pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; + + /* Some production boards of m6 will return 0 if it's 8 MB */ + if (pScrn->videoRam == 0) { + pScrn->videoRam = 8192; + OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000); + } + + /* Get accessible memory */ + accessible = RADEONGetAccessibleVRAM(pScrn); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected total video RAM: %dl, max accessible: %dK\n", + pScrn->videoRam, accessible); + if (pScrn->videoRam > accessible) + pScrn->videoRam = accessible; + } + /* Check chip errata */ info->ChipErrata = 0; if (info->ChipFamily == CHIP_FAMILY_R300 && (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11) info->ChipErrata |= CHIP_ERRATA_R300_CG; @@ -2916,16 +1708,56 @@ info->ChipFamily == CHIP_FAMILY_RS200) info->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS; if (info->ChipFamily == CHIP_FAMILY_RV100 || info->ChipFamily == CHIP_FAMILY_RS100 || info->ChipFamily == CHIP_FAMILY_RS200) info->ChipErrata |= CHIP_ERRATA_PLL_DELAY; + info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); + info->BusCntl = INREG(RADEON_BUS_CNTL); + + RADEONGetVRamType(pScrn); + + if (dev->videoRam) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Video RAM override, using %d kB instead of %d kB\n", + dev->videoRam, + pScrn->videoRam); + from = X_CONFIG; + pScrn->videoRam = dev->videoRam; + } + + xf86DrvMsg(pScrn->scrnIndex, from, + "VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); + + /* FIXME: For now, split FB into two equal sections. This should + * be able to be adjusted by user with a config option. */ + if (info->IsPrimary) { + pScrn->videoRam /= 2; + info->MergedFB = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for primary head\n", + pScrn->videoRam); + } + + if (info->IsSecondary) { + pScrn->videoRam /= 2; + info->LinearAddr += pScrn->videoRam * 1024; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for secondary head\n", + pScrn->videoRam); + } + + pScrn->videoRam &= ~1023; + info->FbMapSize = pScrn->videoRam * 1024; + + info->FbSecureSize = 0; + #ifdef XF86DRI /* AGP/PCI */ /* Proper autodetection of an AGP capable device requires examining * PCI config registers to determine if the device implements extended * PCI capabilities, and then walking the capability list as indicated * in the PCI 2.2 and AGP 2.0 specifications, to determine if AGP * capability is present. The procedure is outlined as follows: * @@ -2999,200 +1831,34 @@ } else if (strcmp(s, "PCIE") == 0) { info->cardType = CARD_PCIE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI Express mode\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Invalid BusType option, using detected type\n"); } } + + /* if the card is PCI Express reserve the last 32k for the gart table */ + if (info->cardType == CARD_PCIE) + info->FbSecureSize = RADEON_PCIGART_TABLE_SIZE; #endif xf86GetOptValBool(info->Options, OPTION_SHOWCACHE, &info->showCache); if (info->showCache) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option ShowCache enabled\n"); #ifdef RENDER info->RenderAccel = xf86ReturnOptValBool (info->Options, OPTION_RENDER_ACCEL, TRUE); #endif return TRUE; } -static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - /* Get the result */ - val = INREG(info->DDCReg); - - *Clock = (val & RADEON_GPIO_Y_1) != 0; - *data = (val & RADEON_GPIO_Y_0) != 0; -} - -static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); - val |= (Clock ? 0:RADEON_GPIO_EN_1); - val |= (data ? 0:RADEON_GPIO_EN_0); - OUTREG(info->DDCReg, val); - - /* read back to improve reliability on some cards. */ - val = INREG(info->DDCReg); -} - -static Bool RADEONI2cInit(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - info->pI2CBus = xf86CreateI2CBusRec(); - if (!info->pI2CBus) return FALSE; - - info->pI2CBus->BusName = "DDC"; - info->pI2CBus->scrnIndex = pScrn->scrnIndex; - info->pI2CBus->I2CPutBits = RADEONI2CPutBits; - info->pI2CBus->I2CGetBits = RADEONI2CGetBits; - info->pI2CBus->AcknTimeout = 5; - - if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; - return TRUE; -} - -static void RADEONPreInitDDC(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - /* vbeInfoPtr pVbe; */ - - info->ddc1 = FALSE; - info->ddc_bios = FALSE; - if (!xf86LoadSubModule(pScrn, "ddc")) { - info->ddc2 = FALSE; - } else { - xf86LoaderReqSymLists(ddcSymbols, NULL); - info->ddc2 = TRUE; - } - - /* DDC can use I2C bus */ - /* Load I2C if we have the code to use it */ - if (info->ddc2) { - if (xf86LoadSubModule(pScrn, "i2c")) { - xf86LoaderReqSymLists(i2cSymbols,NULL); - info->ddc2 = RADEONI2cInit(pScrn); - } - else info->ddc2 = FALSE; - } -} - - -/* BIOS may not have right panel size, we search through all supported - * DDC modes looking for the maximum panel size. - */ -static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) -{ - int j; - RADEONInfoPtr info = RADEONPTR (pScrn); - xf86MonPtr ddc = pScrn->monitor->DDC; - DisplayModePtr p; - - if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) - return; - - /* Go thru detailed timing table first */ - for (j = 0; j < 4; j++) { - if (ddc->det_mon[j].type == 0) { - struct detailed_timings *d_timings = - &ddc->det_mon[j].section.d_timings; - int match = 0; - - /* If we didn't get a panel clock or guessed one, try to match the - * mode with the panel size. We do that because we _need_ a panel - * clock, or ValidateFPModes will fail, even when UseBiosDividers - * is set. - */ - if (info->DotClock == 0 && - info->PanelXRes == d_timings->h_active && - info->PanelYRes == d_timings->v_active) - match = 1; - - /* If we don't have a BIOS provided panel data with fixed dividers, - * check for a larger panel size - */ - if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active && - !info->UseBiosDividers) - match = 1; - - if (match) { - info->PanelXRes = d_timings->h_active; - info->PanelYRes = d_timings->v_active; - info->DotClock = d_timings->clock / 1000; - info->HOverPlus = d_timings->h_sync_off; - info->HSyncWidth = d_timings->h_sync_width; - info->HBlank = d_timings->h_blanking; - info->VOverPlus = d_timings->v_sync_off; - info->VSyncWidth = d_timings->v_sync_width; - info->VBlank = d_timings->v_blanking; - info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); - if (d_timings->sync == 3) { - switch (d_timings->misc) { - case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; - } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - - if (info->UseBiosDividers && info->DotClock != 0) - return; - - /* Search thru standard VESA modes from EDID */ - for (j = 0; j < 8; j++) { - if ((info->PanelXRes < ddc->timings2[j].hsize) && - (info->PanelYRes < ddc->timings2[j].vsize)) { - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((ddc->timings2[j].hsize == p->HDisplay) && - (ddc->timings2[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - info->PanelXRes = ddc->timings2[j].hsize; - info->PanelYRes = ddc->timings2[j].vsize; - info->HBlank = p->HTotal - p->HDisplay; - info->HOverPlus = p->HSyncStart - p->HDisplay; - info->HSyncWidth = p->HSyncEnd - p->HSyncStart; - info->VBlank = p->VTotal - p->VDisplay; - info->VOverPlus = p->VSyncStart - p->VDisplay; - info->VSyncWidth = p->VSyncEnd - p->VSyncStart; - info->DotClock = p->Clock; - info->Flags = p->Flags; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - } - } -} - /* This function will sort all modes according to their resolution. * Highest resolution first. */ static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first, DisplayModePtr *last) { DisplayModePtr p; @@ -3719,113 +2385,50 @@ } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Total number of valid FP mode(s) found: %d\n", count); return count; } +static void RADEONPreInitDDC(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + /* vbeInfoPtr pVbe; */ + + info->ddc1 = FALSE; + info->ddc_bios = FALSE; + if (!xf86LoadSubModule(pScrn, "ddc")) { + info->ddc2 = FALSE; + } else { + xf86LoaderReqSymLists(ddcSymbols, NULL); + info->ddc2 = TRUE; + } + + /* DDC can use I2C bus */ + /* Load I2C if we have the code to use it */ + if (info->ddc2) { + if (xf86LoadSubModule(pScrn, "i2c")) { + xf86LoaderReqSymLists(i2cSymbols,NULL); + info->ddc2 = RADEONI2cInit(pScrn); + } + else info->ddc2 = FALSE; + } +} + /* This is called by RADEONPreInit to initialize gamma correction */ static Bool RADEONPreInitGamma(ScrnInfoPtr pScrn) { Gamma zeros = { 0.0, 0.0, 0.0 }; if (!xf86SetGamma(pScrn, zeros)) return FALSE; return TRUE; } -static void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) -{ - MonPtr mon = pScrn->monitor; - xf86MonPtr ddc = mon->DDC; - int i; - - if (flag) { /* HSync */ - for (i = 0; i < 4; i++) { - if (ddc->det_mon[i].type == DS_RANGES) { - mon->nHsync = 1; - mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; - mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; - return; - } - } - /* If no sync ranges detected in detailed timing table, let's - * try to derive them from supported VESA modes. Are we doing - * too much here!!!? */ - i = 0; - if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ - mon->hsync[i].lo = mon->hsync[i].hi = 35.2; - i++; - } - if (ddc->timings1.t1 & 0x04) { /* 640x480@75 */ - mon->hsync[i].lo = mon->hsync[i].hi = 37.5; - i++; - } - if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) { - mon->hsync[i].lo = mon->hsync[i].hi = 37.9; - i++; - } - if (ddc->timings1.t2 & 0x40) { - mon->hsync[i].lo = mon->hsync[i].hi = 46.9; - i++; - } - if ((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) { - mon->hsync[i].lo = mon->hsync[i].hi = 48.1; - i++; - } - if (ddc->timings1.t2 & 0x04) { - mon->hsync[i].lo = mon->hsync[i].hi = 56.5; - i++; - } - if (ddc->timings1.t2 & 0x02) { - mon->hsync[i].lo = mon->hsync[i].hi = 60.0; - i++; - } - if (ddc->timings1.t2 & 0x01) { - mon->hsync[i].lo = mon->hsync[i].hi = 64.0; - i++; - } - mon->nHsync = i; - } else { /* Vrefresh */ - for (i = 0; i < 4; i++) { - if (ddc->det_mon[i].type == DS_RANGES) { - mon->nVrefresh = 1; - mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; - mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; - return; - } - } - - i = 0; - if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 56; - i++; - } - if ((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 60; - i++; - } - if (ddc->timings1.t2 & 0x04) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 70; - i++; - } - if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 72; - i++; - } - if ((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) || - (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 75; - i++; - } - mon->nVrefresh = i; - } -} - static int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) { RADEONInfoPtr info = RADEONPTR(pScrn1); ClockRangePtr clockRanges; int modesFound; ScrnInfoPtr pScrn = info->CRT2pScrn; /* fill in pScrn2 */ @@ -4028,32 +2631,27 @@ else info->NoVirtual = FALSE; } info->ddc_mode = xf86ReturnOptValBool(info->Options, OPTION_DDC_MODE, FALSE); /* don't use RMX if we have a dual-tmds panels */ - if (pRADEONEnt->MonType2 == MT_DFP) + if (pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) info->ddc_mode = TRUE; /* don't use RMX if we are Dell Server */ if (info->IsDellServer) { info->ddc_mode = TRUE; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Validating modes on %s head ---------\n", info->IsSecondary ? "Secondary" : "Primary"); - if (info->IsSecondary) - pScrn->monitor->DDC = pRADEONEnt->MonInfo2; - else - pScrn->monitor->DDC = pRADEONEnt->MonInfo1; - if (!pScrn->monitor->DDC && info->ddc_mode) { info->ddc_mode = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DDC data available, DDCMode option is dismissed\n"); } if ((info->DisplayType == MT_DFP) || (info->DisplayType == MT_LCD)) { @@ -4473,54 +3071,16 @@ } #ifdef XF86DRI static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); MessageType from; - info->directRenderingEnabled = FALSE; - info->directRenderingInited = FALSE; - info->CPInUse = FALSE; - info->CPStarted = FALSE; - info->pLibDRMVersion = NULL; - info->pKernelDRMVersion = NULL; - - if (xf86IsEntityShared(info->pEnt->index)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Direct Rendering Disabled -- " - "Dual-head configuration is not working with " - "DRI at present.\n" - "Please use the radeon MergedFB option if you " - "want Dual-head with DRI.\n"); - return FALSE; - } - if (info->IsSecondary) - return FALSE; - - if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[dri] Acceleration disabled, not initializing the DRI\n"); - return FALSE; - } - - if (!RADEONDRIGetVersion(pScrn)) - return FALSE; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[dri] Found DRI library version %d.%d.%d and kernel" - " module version %d.%d.%d\n", - info->pLibDRMVersion->version_major, - info->pLibDRMVersion->version_minor, - info->pLibDRMVersion->version_patchlevel, - info->pKernelDRMVersion->version_major, - info->pKernelDRMVersion->version_minor, - info->pKernelDRMVersion->version_patchlevel); - if (xf86ReturnOptValBool(info->Options, OPTION_CP_PIO, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CP into PIO mode\n"); info->CPMode = RADEON_DEFAULT_CP_PIO_MODE; } else { info->CPMode = RADEON_DEFAULT_CP_BM_MODE; } info->agpMode = RADEON_DEFAULT_AGP_MODE; @@ -4627,17 +3187,16 @@ /* Two options to try and squeeze as much texture memory as possible * for dedicated 3d rendering boxes */ info->noBackBuffer = xf86ReturnOptValBool(info->Options, OPTION_NO_BACKBUFFER, FALSE); -#ifdef XF86DRI if (info->noBackBuffer) { info->allowPageFlip = 0; } else if (!xf86LoadSubModule(pScrn, "shadowfb")) { info->allowPageFlip = 0; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't load shadowfb module:\n"); } else { xf86LoaderReqSymLists(driShadowFBSymbols, NULL); @@ -4649,84 +3208,27 @@ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping not allowed with EXA, disabling.\n"); info->allowPageFlip = FALSE; } } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", info->allowPageFlip ? "en" : "dis"); -#endif info->DMAForXv = TRUE; from = xf86GetOptValBool(info->Options, OPTION_XV_DMA, &info->DMAForXv) ? X_CONFIG : X_INFO; xf86DrvMsg(pScrn->scrnIndex, from, "Will %stry to use DMA for Xv image transfers\n", info->DMAForXv ? "" : "not "); return TRUE; } -#endif /* XF86DRI */ - -static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (IS_R300_VARIANT) { - /* false by default on R3/4xx */ - info->allowColorTiling = xf86ReturnOptValBool(info->Options, - OPTION_COLOR_TILING, FALSE); - info->MaxSurfaceWidth = 3968; /* one would have thought 4096...*/ - info->MaxLines = 4096; - } else { - info->allowColorTiling = xf86ReturnOptValBool(info->Options, - OPTION_COLOR_TILING, TRUE); - info->MaxSurfaceWidth = 2048; - info->MaxLines = 2048; - } - - if (!info->allowColorTiling) - return; - -#ifdef XF86DRI - if (info->directRenderingEnabled && - info->pKernelDRMVersion->version_minor < 14) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[dri] color tiling disabled because of version " - "mismatch.\n" - "[dri] radeon.o kernel module version is %d.%d.%d but " - "1.14.0 or later is required for color tiling.\n", - info->pKernelDRMVersion->version_major, - info->pKernelDRMVersion->version_minor, - info->pKernelDRMVersion->version_patchlevel); - info->allowColorTiling = FALSE; - return; - } -#endif /* XF86DRI */ - - if ((info->allowColorTiling) && (info->IsSecondary)) { - /* can't have tiling on the 2nd head (as long as it can't use drm). - * We'd never get the surface save/restore (vt switching) right... - */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled for 2nd head\n"); - info->allowColorTiling = FALSE; - } - else if ((info->allowColorTiling) && (info->FBDev)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Color tiling not supported with UseFBDev option\n"); - info->allowColorTiling = FALSE; - } - else if (info->allowColorTiling) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling enabled by default\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled\n"); - } -} - +#endif static Bool RADEONPreInitXv(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); CARD16 mm_table; CARD16 bios_header; CARD16 pll_info_block; @@ -4792,16 +3294,29 @@ pll_info_block+=(((int)info->VBIOS[bios_header+0x31]+0)<<8); info->video_decoder_type=info->VBIOS[pll_info_block+0x08]; info->video_decoder_type+=(((int)info->VBIOS[pll_info_block+0x09]+0)<<8); return TRUE; } +static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +{ + RADEONGetBIOSInfo(pScrn, pInt10); + + RADEONMapControllers(pScrn); + + RADEONGetClockInfo(pScrn); + RADEONGetPanelInfo(pScrn); + RADEONGetTVDacAdjInfo(pScrn); + + return TRUE; +} + static void RADEONProbeDDC(ScrnInfoPtr pScrn, int indx) { vbeInfoPtr pVbe; if (xf86LoadSubModule(pScrn, "vbe")) { pVbe = VBEInit(NULL,indx); ConfiguredMonitor = vbeDoEDID(pVbe, NULL); @@ -4886,18 +3401,16 @@ } else { RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); info->IsPrimary = TRUE; xf86SetPrimInitDone(info->pEnt->index); pRADEONEnt->pPrimaryScrn = pScrn; - pRADEONEnt->RestorePrimary = FALSE; - pRADEONEnt->IsSecondaryRestored = FALSE; } } if (flags & PROBE_DETECT) { RADEONProbeDDC(pScrn, info->pEnt->index); RADEONPostInt10Check(pScrn, int10_save); if(info->MMIO) RADEONUnmapMMIO(pScrn); return TRUE; @@ -5078,55 +3591,75 @@ } if (!info->FBDev) if (!RADEONPreInitInt10(pScrn, &pInt10)) goto fail; RADEONPostInt10Check(pScrn, int10_save); - if (!RADEONPreInitChipType(pScrn)) + if (!RADEONPreInitConfig(pScrn)) goto fail; -#ifdef XF86DRI - /* PreInit DRI first of all since we need that for getting a proper - * memory map - */ - info->directRenderingEnabled = RADEONPreInitDRI(pScrn); -#endif - - if (!RADEONPreInitVRAM(pScrn)) - goto fail; + if (IS_R300_VARIANT) { + /* false by default on R3/4xx */ + info->allowColorTiling = xf86ReturnOptValBool(info->Options, + OPTION_COLOR_TILING, FALSE); + info->MaxSurfaceWidth = 3968; /* one would have thought 4096...*/ + info->MaxLines = 4096; + } else { + info->allowColorTiling = xf86ReturnOptValBool(info->Options, + OPTION_COLOR_TILING, TRUE); + info->MaxSurfaceWidth = 2048; + info->MaxLines = 2048; + } - RADEONPreInitColorTiling(pScrn); + if ((info->allowColorTiling) && (info->IsSecondary)) { + /* can't have tiling on the 2nd head (as long as it can't use drm). We'd never + get the surface save/restore (vt switching) right... */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled for 2nd head\n"); + info->allowColorTiling = FALSE; + } + else if ((info->allowColorTiling) && (info->FBDev)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Color tiling not supported with UseFBDev option\n"); + info->allowColorTiling = FALSE; + } + else if (info->allowColorTiling) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling enabled by default\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled\n"); + } RADEONPreInitDDC(pScrn); - RADEONGetBIOSInfo(pScrn, pInt10); - if (!RADEONQueryConnectedMonitors(pScrn)) goto fail; - RADEONGetClockInfo(pScrn); + if (!RADEONPreInitControllers (pScrn, pInt10)) goto fail; /* collect MergedFB options */ /* only parse mergedfb options on the primary head. Mergedfb is already disabled in xinerama/screen based multihead */ if (!info->IsSecondary) RADEONGetMergedFBOptions(pScrn); if (!RADEONPreInitGamma(pScrn)) goto fail; if (!RADEONPreInitModes(pScrn, pInt10)) goto fail; if (!RADEONPreInitCursor(pScrn)) goto fail; if (!RADEONPreInitAccel(pScrn)) goto fail; +#ifdef XF86DRI + if (!RADEONPreInitDRI(pScrn)) goto fail; +#endif + if (!RADEONPreInitXv(pScrn)) goto fail; - /* Free the video bios (if applicable) */ + /* Free the video bios (if applicable) */ if (info->VBIOS) { xfree(info->VBIOS); info->VBIOS = NULL; } /* Free int10 info */ if (pInt10) xf86FreeInt10(pInt10); @@ -5175,24 +3708,34 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; int i; int idx, j; unsigned char r, g, b; + CARD32 tmp = 0; + + RADEONTRACE(("RADEONLoadPalette !\n")); #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); #endif if (info->accelOn && pScrn->pScreen) RADEON_SYNC(info, pScrn); + if (info->HasCRTC2) { + tmp = INPLL (pScrn, RADEON_PIXCLKS_CNTL); + OUTPLLP (pScrn, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + } + if (info->FBDev) { fbdevHWLoadPalette(pScrn, numColors, indices, colors, pVisual); } else { /* If the second monitor is connected, we also need to deal with * the secondary palette */ if (info->IsSecondary) j = 1; else j = 0; @@ -5291,19 +3834,24 @@ b = colors[idx].blue; g = colors[idx].green; OUTPAL(idx, r, g, b); } } } } + if (info->HasCRTC2) + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); #endif + + RADEONTRACE(("LoadPalette() end\n")); } static void RADEONBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) { ScreenPtr pScreen = screenInfo.screens[i]; ScrnInfoPtr pScrn = xf86Screens[i]; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -5337,17 +3885,16 @@ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); int cpp = info->CurrentLayout.pixel_bytes; int width_bytes = pScrn->displayWidth * cpp; int bufferSize; int depthSize; int l; int scanlines; - int texsizerequest; BoxRec MemBox; FBAreaPtr fbarea; info->frontOffset = 0; info->frontPitch = pScrn->displayWidth; info->backPitch = pScrn->displayWidth; /* make sure we use 16 line alignment for tiling (8 might be enough). @@ -5388,51 +3935,38 @@ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d MB for vertex/indirect buffers\n", info->bufSize); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d MB for GART textures\n", info->gartTexSize); /* Try for front, back, depth, and three framebuffers worth of * pixmap cache. Should be enough for a fullscreen background * image plus some leftovers. - * If the FBTexPercent option was used, try to achieve that percentage instead, - * but still have at least one pixmap buffer (get problems with xvideo/render - * otherwise probably), and never reserve more than 3 offscreen buffers as it's - * probably useless for XAA. */ - if (info->textureSize >= 0) { - texsizerequest = ((int)info->FbMapSize - 2 * bufferSize - depthSize - - 2 * width_bytes - 16384 - info->FbSecureSize) - /* first divide, then multiply or we'll get an overflow (been there...) */ - / 100 * info->textureSize; - } - else { - texsizerequest = (int)info->FbMapSize / 2; - } info->textureSize = info->FbMapSize - info->FbSecureSize - 5 * bufferSize - depthSize; - /* If that gives us less than the requested memory, let's + /* If that gives us less than half the available memory, let's * be greedy and grab some more. Sorry, I care more about 3D * performance than playing nicely, and you'll get around a full * framebuffer's worth of pixmap cache anyway. */ - if (info->textureSize < texsizerequest) { + if (info->textureSize < (int)info->FbMapSize / 2) { info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize; } - if (info->textureSize < texsizerequest) { + if (info->textureSize < (int)info->FbMapSize / 2) { info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; } /* If there's still no space for textures, try without pixmap cache, but * never use the reserved space, the space hw cursor and PCIGART table might * use. */ if (info->textureSize < 0) { info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize - - 2 * width_bytes - 16384 - info->FbSecureSize; + - 2 * width_bytes - 16384 - info->FbSecureSize; } /* Check to see if there is more room available after the 8192nd * scanline for textures */ /* FIXME: what's this good for? condition is pretty much impossible to meet */ if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize > info->textureSize) { @@ -5671,39 +4205,51 @@ #ifdef RENDER int subPixelOrder = SubPixelUnknown; char* s; #endif RADEONTRACE(("RADEONScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset)); +#ifdef XF86DRI + /* Turn off the CP for now. */ + info->CPInUse = FALSE; + info->CPStarted = FALSE; + info->directRenderingEnabled = FALSE; + info->directRenderingInited = FALSE; +#endif info->accelOn = FALSE; info->accel = NULL; pScrn->fbOffset = 0; if (info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; if (!RADEONMapMem(pScrn)) return FALSE; #ifdef XF86DRI info->fbX = 0; info->fbY = 0; #endif - info->PaletteSavedOnVT = FALSE; - RADEONSave(pScrn); if ((!info->IsSecondary) && info->IsMobility) { if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { RADEONSetDynamicClock(pScrn, 1); } else { RADEONSetDynamicClock(pScrn, 0); } } +#if 0 + if (info->allowColorTiling && info->useEXA) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Color tiling not supported yet with EXA, disabling\n"); + info->allowColorTiling = FALSE; + } +#endif if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling not supported with virtual x resolutions larger than %d, disabling\n", info->MaxSurfaceWidth); info->allowColorTiling = FALSE; } if (info->allowColorTiling) { if (info->MergedFB) { @@ -5713,39 +4259,44 @@ (V_DBLSCAN | V_INTERLACE))) info->tilingEnabled = FALSE; else info->tilingEnabled = TRUE; } else { info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; } } - - /* Visual setup */ + /* Visual setup */ miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits, pScrn->defaultVisual)) return FALSE; miSetPixmapDepths (); #ifdef XF86DRI - /* Setup DRI after visuals have been established, but before fbScreenInit is - * called. fbScreenInit will eventually call the driver's InitGLXVisuals - * call back. */ - if (info->directRenderingEnabled) { + /* Setup DRI after visuals have been + established, but before fbScreenInit is + called. fbScreenInit will eventually + call the driver's InitGLXVisuals call + back. */ + { /* FIXME: When we move to dynamic allocation of back and depth * buffers, we will want to revisit the following check for 3 * times the virtual size of the screen below. */ int width_bytes = (pScrn->displayWidth * info->CurrentLayout.pixel_bytes); int maxy = info->FbMapSize / width_bytes; - if (maxy <= pScrn->virtualY * 3) { + if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Acceleration disabled, not initializing the DRI\n"); + info->directRenderingEnabled = FALSE; + } else if (maxy <= pScrn->virtualY * 3) { xf86DrvMsg(scrnIndex, X_ERROR, "Static buffer allocation failed. Disabling DRI.\n"); xf86DrvMsg(scrnIndex, X_ERROR, "At least %d kB of video memory needed at this " "resolution and depth.\n", (pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024); info->directRenderingEnabled = FALSE; @@ -5753,39 +4304,34 @@ xf86DrvMsg(scrnIndex, X_WARNING, "Enabling DRM support\n\n" "\t*** Direct rendering support is highly experimental for Radeon 9500\n" "\t*** and newer cards. The 3d mesa driver is not provided in this tree.\n" "\t*** A very experimental (and incomplete) version is available from Mesa CVS.\n" "\t*** Additional information can be found on http://r300.sourceforge.net\n" "\t*** This message has been last modified on 2005-08-07.\n\n" ); info->directRenderingEnabled = RADEONDRIScreenInit(pScreen); + } else if (info->IsSecondary) { + info->directRenderingEnabled = FALSE; + } else if (xf86IsEntityShared(info->pEnt->index)) { + /* Xinerama has sync problem with DRI, disable it for now */ + info->directRenderingEnabled = FALSE; + xf86DrvMsg(scrnIndex, X_WARNING, + "Direct Rendering Disabled -- " + "Dual-head configuration is not working with " + "DRI at present.\n" + "Please use the radeon MergedFB option if you " + "want Dual-head with DRI.\n"); } else { info->directRenderingEnabled = RADEONDRIScreenInit(pScreen); } } - /* Tell DRI about new memory map */ - if (info->directRenderingEnabled && info->newMemoryMap) { - drmRadeonSetParam radeonsetparam; - RADEONTRACE(("DRI New memory map param\n")); - memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); - radeonsetparam.param = RADEON_SETPARAM_NEW_MEMMAP; - radeonsetparam.value = 1; - if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, - &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[drm] failed to enable new memory map\n"); - RADEONDRICloseScreen(pScreen); - info->directRenderingEnabled = FALSE; - } - } - hasDRI = info->directRenderingEnabled; -#endif /* XF86DRI */ +#endif /* Initialize the memory map, this basically calculates the values * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION */ RADEONInitMemoryMap(pScrn); if (!info->IsSecondary) { /* empty the surfaces */ @@ -5809,31 +4355,29 @@ } else { if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; } RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); -#ifdef XF86DRI /* Depth moves are disabled by default since they are extremely slow */ info->depthMoves = xf86ReturnOptValBool(info->Options, OPTION_DEPTH_MOVE, FALSE); if (info->depthMoves && info->allowColorTiling) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling depth moves\n"); } else if (info->depthMoves) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Depth moves don't work without color tiling, disabled\n"); info->depthMoves = FALSE; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Depth moves disabled by default\n"); } -#endif /* Initial setup of surfaces */ if (!info->IsSecondary) { RADEONTRACE(("Setting up initial surfaces\n")); RADEONChangeSurfaces(pScrn); } RADEONTRACE(("Initializing fb layer\n")); @@ -5884,55 +4428,23 @@ PictureSetSubpixelOrder (pScreen, subPixelOrder); } #endif /* Memory manager setup */ RADEONTRACE(("Setting up accel memmap\n")); #ifdef USE_EXA - if (info->useEXA) { -#ifdef XF86DRI - /* Reserve approx. half of offscreen memory for local textures by - * default, can be overridden with Option "FBTexPercent". - * Round down to a whole number of texture regions. - */ - info->textureSize = 50; - - if (xf86GetOptValInteger(info->Options, OPTION_FBTEX_PERCENT, - &(info->textureSize))) { - if (info->textureSize < 0 || info->textureSize > 100) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Illegal texture memory percentage: %dx, setting to default 50%\n", - info->textureSize); - info->textureSize = 50; - } - } -#endif /* XF86DRI */ - - if (!RADEONSetupMemEXA(pScreen)) - return FALSE; - } + if (info->useEXA && !RADEONSetupMemEXA(pScreen)) + return FALSE; #endif #if defined(XF86DRI) && defined(USE_XAA) - if (!info->useEXA && hasDRI) { - info->textureSize = -1; - if (xf86GetOptValInteger(info->Options, OPTION_FBTEX_PERCENT, - &(info->textureSize))) { - if (info->textureSize < 0 || info->textureSize > 100) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Illegal texture memory percentage: %dx, using default behaviour\n", - info->textureSize); - info->textureSize = -1; - } - } - if (!RADEONSetupMemXAA_DRI(scrnIndex, pScreen)) - return FALSE; - } + if (!info->useEXA && hasDRI && !RADEONSetupMemXAA_DRI(scrnIndex, pScreen)) + return FALSE; #endif #ifdef USE_XAA if (!info->useEXA && !hasDRI && !RADEONSetupMemXAA(scrnIndex, pScreen)) return FALSE; #endif info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) @@ -5940,18 +4452,30 @@ /* Backing store setup */ RADEONTRACE(("Initializing backing store\n")); miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); /* DRI finalisation */ #ifdef XF86DRI - if (info->directRenderingEnabled && info->cardType==CARD_PCIE && - info->pciGartOffset && info->pKernelDRMVersion->version_minor >= 19) + /* Tell DRI about new memory map */ + if (info->directRenderingEnabled) { + drmRadeonSetParam radeonsetparam; + RADEONTRACE(("DRI New memory map param\n")); + memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); + radeonsetparam.param = RADEON_SETPARAM_NEW_MEMMAP; + radeonsetparam.value = 1; + if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, + &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[drm] failed to enable new memory map\n"); + } + + if (info->cardType==CARD_PCIE && info->pciGartOffset && 1) { drmRadeonSetParam radeonsetparam; RADEONTRACE(("DRI PCIGART param\n")); memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); radeonsetparam.param = RADEON_SETPARAM_PCIGART_LOCATION; radeonsetparam.value = info->pciGartOffset; if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) @@ -6014,23 +4538,22 @@ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); info->accelOn = FALSE; } } else { xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); info->accelOn = FALSE; } -#ifdef XF86DRI + /* Init page flipping if enabled now */ if (info->allowPageFlip) { RADEONTRACE(("Initializing Page Flipping\n")); RADEONDRIInitPageFlip(pScreen); } -#endif /* Init DPMS */ RADEONTRACE(("Initializing DPMS\n")); xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0); RADEONTRACE(("Initializing Cursor\n")); /* Set Silken Mouse */ @@ -6095,20 +4618,16 @@ info->MouseRestrictions = FALSE; } } /* Init Xv */ RADEONTRACE(("Initializing Xv\n")); RADEONInitVideo(pScreen); - if(info->MergedFB) - /* need this here to fix up sarea values */ - RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ /* Wrap CloseScreen */ info->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = RADEONCloseScreen; pScreen->SaveScreen = RADEONSaveScreen; info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; @@ -6116,160 +4635,109 @@ if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); RADEONTRACE(("RADEONScreenInit finished\n")); return TRUE; } +#if 1 +/* Write palette data */ +static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i; + CARD32 tmp = 0; + + if (info->HasCRTC2) { + tmp = INPLL (pScrn, RADEON_PIXCLKS_CNTL); + OUTPLLP (pScrn, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + PAL_SELECT(1); + OUTPAL_START(0); + for (i = 0; i < 256; i++) { + OUTPAL_NEXT_CARD32(restore->palette2[i]); + } + } + + PAL_SELECT(0); + OUTPAL_START(0); + for (i = 0; i < 256; i++) { + OUTPAL_NEXT_CARD32(restore->palette[i]); + } + + if (info->HasCRTC2) + OUTREG(RADEON_PIXCLKS_CNTL, tmp); +} +#endif + /* Write memory mapping registers */ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int i, timeout; + int i; RADEONTRACE(("RADEONRestoreMemMapRegisters() : \n")); RADEONTRACE((" MC_FB_LOCATION : 0x%08lx\n", restore->mc_fb_location)); RADEONTRACE((" MC_AGP_LOCATION : 0x%08lx\n", restore->mc_agp_location)); /* Write memory mapping registers only if their value change * since we must ensure no access is done while they are * reprogrammed */ if (INREG(RADEON_MC_FB_LOCATION) != restore->mc_fb_location || INREG(RADEON_MC_AGP_LOCATION) != restore->mc_agp_location) { - CARD32 crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl=0, ov0_scale_cntl; - CARD32 old_mc_status, status_idle; + CARD32 tmp; RADEONTRACE((" Map Changed ! Applying ...\n")); /* Make sure engine is idle. We assume the CCE is stopped * at this point */ RADEONWaitForIdleMMIO(pScrn); - if (info->IsIGP) - goto igp_no_mcfb; - - /* Capture MC_STATUS in case things go wrong ... */ - old_mc_status = INREG(RADEON_MC_STATUS); - /* Stop display & memory access */ - ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL); - OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); - crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); - OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); - crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); - RADEONWaitForVerticalSync(pScrn); - OUTREG(RADEON_CRTC_GEN_CNTL, - (crtc_gen_cntl - & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) - | RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); - - if (info->HasCRTC2) { - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); - RADEONWaitForVerticalSync2(pScrn); - OUTREG(RADEON_CRTC2_GEN_CNTL, - (crtc2_gen_cntl - & ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) - | RADEON_CRTC2_DISP_REQ_EN_B); - } - - /* Make sure the chip settles down (paranoid !) */ - usleep(100000); - - /* Wait for MC idle */ - if (IS_R300_VARIANT) - status_idle = R300_MC_IDLE; - else - status_idle = RADEON_MC_IDLE; - - timeout = 0; - while (!(INREG(RADEON_MC_STATUS) & status_idle)) { - if (++timeout > 1000000) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Timeout trying to update memory controller settings !\n"); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "MC_STATUS = 0x%08x (on entry = 0x%08x)\n", - INREG(RADEON_MC_STATUS), old_mc_status); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "You will probably crash now ... \n"); - /* Nothing we can do except maybe try to kill the server, - * let's wait 2 seconds to leave the above message a chance - * to maybe hit the disk and continue trying to setup despite - * the MC being non-idle - */ - usleep(2000000); - } - usleep(10); + tmp = INREG(RADEON_CRTC_EXT_CNTL); + OUTREG(RADEON_CRTC_EXT_CNTL, tmp | RADEON_CRTC_DISPLAY_DIS); + tmp = INREG(RADEON_CRTC_GEN_CNTL); + tmp &= ~RADEON_CRTC_CUR_EN; + tmp |= RADEON_CRTC_DISP_REQ_EN_B; + OUTREG(RADEON_CRTC_GEN_CNTL, tmp); + if (info->HasCRTC2) { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp &= ~RADEON_CRTC2_CUR_EN; + tmp |= RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); } + tmp = INREG(RADEON_OV0_SCALE_CNTL); + tmp &= ~RADEON_SCALER_ENABLE; + OUTREG(RADEON_OV0_SCALE_CNTL, tmp); - /* Update maps, first clearing out AGP to make sure we don't get - * a temporary overlap - */ - OUTREG(RADEON_MC_AGP_LOCATION, 0xfffffffc); + /* Make sure the chip settles down and set new map*/ + usleep(100000); OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location); - igp_no_mcfb: OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location); /* Make sure map fully reached the chip */ (void)INREG(RADEON_MC_FB_LOCATION); - RADEONTRACE((" Map applied, resetting engine ...\n")); - /* Reset the engine and HDP */ RADEONEngineReset(pScrn); - - /* Make sure we have sane offsets before re-enabling the CRTCs, disable - * stereo, clear offsets, and wait for offsets to catch up with hw - */ - - OUTREG(RADEON_CRTC_OFFSET_CNTL, RADEON_CRTC_OFFSET_FLIP_CNTL); - OUTREG(RADEON_CRTC_OFFSET, 0); - OUTREG(RADEON_CUR_OFFSET, 0); - timeout = 0; - while(INREG(RADEON_CRTC_OFFSET) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) { - if (timeout++ > 1000000) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Timeout waiting for CRTC offset to update !\n"); - break; - } - usleep(1000); - } - if (info->HasCRTC2) { - OUTREG(RADEON_CRTC2_OFFSET_CNTL, RADEON_CRTC2_OFFSET_FLIP_CNTL); - OUTREG(RADEON_CRTC2_OFFSET, 0); - OUTREG(RADEON_CUR2_OFFSET, 0); - timeout = 0; - while(INREG(RADEON_CRTC2_OFFSET) & RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET) { - if (timeout++ > 1000000) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Timeout waiting for CRTC2 offset to update !\n"); - break; - } - usleep(1000); - } - } } - - RADEONTRACE(("Updating display base addresses...\n")); - + + /* Restore base addresses */ OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); - if (info->HasCRTC2) - OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr); + OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr); OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr); - (void)INREG(RADEON_OV0_BASE_ADDR); - - /* More paranoia delays, wait 100ms */ - usleep(100000); - - RADEONTRACE(("Memory map updated.\n")); - } +} static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 fb, agp; int fb_loc_changed; @@ -6367,137 +4835,123 @@ } /* Write CRTC registers */ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONTRACE(("Programming CRTC1, offset: 0x%08x\n", - restore->crtc_offset)); - - /* We prevent the CRTC from hitting the memory controller until - * fully programmed - */ - OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl | - RADEON_CRTC_DISP_REQ_EN_B); + OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); + OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); + OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); + OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); + OUTREG(RADEON_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); + OUTREG(RADEON_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); + OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); + if (info->IsSwitching) return; - OUTREGP(RADEON_CRTC_EXT_CNTL, - restore->crtc_ext_cntl, - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_DISPLAY_DIS); + OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl); + OUTREG(RADEON_CRTC_EXT_CNTL, restore->crtc_ext_cntl); OUTREGP(RADEON_DAC_CNTL, restore->dac_cntl, RADEON_DAC_RANGE_CNTL | RADEON_DAC_BLANKING); - OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); - OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); - OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); - OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); - OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); OUTREG(RADEON_DISP_MERGE_CNTL, restore->disp_merge_cntl); OUTREG(RADEON_CRTC_MORE_CNTL, restore->crtc_more_cntl); + /* when there is only single head, we need to make sure + * it's using first CRTC, no matter what type of display + */ + if (!pRADEONEnt->Controller[1].IsUsed && info->HasCRTC2) { + + if ((info->ChipFamily != CHIP_FAMILY_RADEON) && + (info->ChipFamily != CHIP_FAMILY_R200)) + OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + + if(IS_RV100_VARIANT) { + OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); + } + OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); + } + if (info->IsDellServer) { OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); } - OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl); } /* Write CRTC2 registers */ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 crtc2_gen_cntl; - - RADEONTRACE(("Programming CRTC2, offset: 0x%08x\n", - restore->crtc2_offset)); - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) & - (RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS | - RADEON_CRTC2_DISP_DIS); - crtc2_gen_cntl |= restore->crtc2_gen_cntl; - - /* We prevent the CRTC from hitting the memory controller until - * fully programmed - */ - OUTREG(RADEON_CRTC2_GEN_CNTL, - crtc2_gen_cntl | RADEON_CRTC2_DISP_REQ_EN_B); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); + OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); + OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid); + OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid); + if (info->IsSwitching) return; + OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); - OUTREG(RADEON_TV_DAC_CNTL, 0x00280203); - if ((info->ChipFamily == CHIP_FAMILY_R200) || - IS_R300_VARIANT) { + if ((info->ChipFamily != CHIP_FAMILY_RADEON) && + (info->ChipFamily != CHIP_FAMILY_R200)) + OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + if (IS_R300_VARIANT) { + OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl); + } else if (info->ChipFamily == CHIP_FAMILY_R200) { OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl); + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); } else { OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); } - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); - OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); - - if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->MergeType == MT_DFP) { - OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp2_h_sync_strt_wid); - OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid); - OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); - } - - OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); - -#if 0 - /* Hack for restoring text mode -- fixed elsewhere */ - usleep(100000); -#endif } /* Write flat panel registers */ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; unsigned long tmp; - OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); - OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); - OUTREG(RADEON_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); - OUTREG(RADEON_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); OUTREG(RADEON_TMDS_PLL_CNTL, restore->tmds_pll_cntl); OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl); OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch); OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch); + + if (info->IsSwitching) return; OUTREG(RADEON_FP_GEN_CNTL, restore->fp_gen_cntl); - /* old AIW Radeon has some BIOS initialization problem - * with display buffer underflow, only occurs to DFP - */ - if (!info->HasCRTC2) - OUTREG(RADEON_GRPH_BUFFER_CNTL, - INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); + if (!info->HasCRTC2) return; + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); if (info->IsMobility) { OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch); OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch); OUTREG(RADEON_BIOS_6_SCRATCH, restore->bios_6_scratch); } if (info->DisplayType != MT_DFP) { @@ -6531,16 +4985,17 @@ if (info->IsMobility || info->IsIGP) { if (!(restore->lvds_gen_cntl & RADEON_LVDS_ON)) { OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); } } } } + static void RADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) { int i = 0; /* FIXME: Certain revisions of R300 can't recover here. Not sure of the cause yet, but this workaround will mask the problem for now. Other chips usually will pass at the very first test, so the workaround shouldn't have any effect on them. */ @@ -6673,19 +5128,17 @@ INPLL(pScrn, RADEON_PPLL_CNTL))); RADEONTRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16)); usleep(50000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, - RADEON_VCLK_SRC_SEL_PPLLCLK, - ~(RADEON_VCLK_SRC_SEL_MASK)); + OUTPLLP (pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_cntl, 0); } /* Write PLL2 registers */ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) { OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, @@ -6732,19 +5185,17 @@ INPLL(pScrn, RADEON_P2PLL_CNTL))); RADEONTRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, (restore->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >>16)); usleep(5000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, - RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, - ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + OUTPLLP (pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl, 0); } /* restore original surface info (for fb console). */ static void RADEONRestoreSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -6911,118 +5362,76 @@ surf_info, 0, bufferSize - 1024);*/ } } /* Update surface images */ RADEONSaveSurfaces(pScrn, &info->ModeReg); } -#if 0 -/* Write palette data */ -static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int i; - - if (!restore->palette_valid) return; - - PAL_SELECT(1); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette2[i]); - } - - PAL_SELECT(0); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette[i]); - } -} -#endif - /* Write out state to define a new video mode */ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - static RADEONSaveRec restore0; - - RADEONTRACE(("RADEONRestoreMode()\n")); - - /* For Non-dual head card, we don't have private field in the Entity */ - if (!info->HasCRTC2) { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - return; - } - - RADEONTRACE(("RADEONRestoreMode(%p)\n", restore)); + RADEONController* pCRTC1 = &pRADEONEnt->Controller[0]; + RADEONController* pCRTC2 = &pRADEONEnt->Controller[1]; /* When changing mode with Dual-head card, care must be taken for * the special order in setting registers. CRTC2 has to be set * before changing CRTC_EXT register. In the dual-head setup, X * server calls this routine twice with primary and secondary pScrn * pointers respectively. The calls can come with different * order. Regardless the order of X server issuing the calls, we * have to ensure we set registers in the right order!!! Otherwise * we may get a blank screen. * * We always restore MemMap first, the saverec should be up to date * in all cases */ - if (info->IsSecondary) { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - - if (info->IsSwitching) - return; - - pRADEONEnt->IsSecondaryRestored = TRUE; - if (pRADEONEnt->RestorePrimary) { - pRADEONEnt->RestorePrimary = FALSE; + if (info->IsSwitching) { + if (info->IsSecondary) { + RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + RADEONEnableDisplay(pScrn, pCRTC2, TRUE); + } else { + RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); + if (info->MergedFB) { + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + } - RADEONRestoreCrtcRegisters(pScrn, &restore0); - RADEONRestoreFPRegisters(pScrn, &restore0); - RADEONRestorePLLRegisters(pScrn, &restore0); - pRADEONEnt->IsSecondaryRestored = FALSE; + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + RADEONEnableDisplay(pScrn, pCRTC1, TRUE); + if (info->MergedFB) { + RADEONEnableDisplay(pScrn, pCRTC2, TRUE); + } } } else { RADEONRestoreMemMapRegisters(pScrn, restore); RADEONRestoreCommonRegisters(pScrn, restore); - if (info->MergedFB) { + if ((info->MergedFB) || pRADEONEnt->HasSecondary) { RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); } - if (!pRADEONEnt->HasSecondary || pRADEONEnt->IsSecondaryRestored || - info->IsSwitching) { - pRADEONEnt->IsSecondaryRestored = FALSE; - - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - } else { - memcpy(&restore0, restore, sizeof(restore0)); - pRADEONEnt->RestorePrimary = TRUE; + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + RADEONEnableDisplay(pScrn, pCRTC1, TRUE); + if ((info->MergedFB) || pRADEONEnt->HasSecondary) { + RADEONEnableDisplay(pScrn, pCRTC2, TRUE); } } - -#if 0 - RADEONRestorePalette(pScrn, &info->SavedReg); -#endif } /* Read memory map */ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -7081,25 +5490,28 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; save->crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); save->crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); save->dac_cntl = INREG(RADEON_DAC_CNTL); + save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); save->crtc_h_total_disp = INREG(RADEON_CRTC_H_TOTAL_DISP); save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID); save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP); save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID); save->crtc_offset = INREG(RADEON_CRTC_OFFSET); save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); save->crtc_pitch = INREG(RADEON_CRTC_PITCH); save->disp_merge_cntl = INREG(RADEON_DISP_MERGE_CNTL); save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); + save->fp_h_sync_strt_wid = INREG(RADEON_FP_H_SYNC_STRT_WID); + save->fp_v_sync_strt_wid = INREG(RADEON_FP_V_SYNC_STRT_WID); if (info->IsDellServer) { save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); save->dac2_cntl = INREG(RADEON_DAC_CNTL2); save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); } } @@ -7108,19 +5520,19 @@ static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; save->fp_crtc_h_total_disp = INREG(RADEON_FP_CRTC_H_TOTAL_DISP); save->fp_crtc_v_total_disp = INREG(RADEON_FP_CRTC_V_TOTAL_DISP); save->fp_gen_cntl = INREG(RADEON_FP_GEN_CNTL); - save->fp_h_sync_strt_wid = INREG(RADEON_FP_H_SYNC_STRT_WID); + /*save->fp_h_sync_strt_wid = INREG(RADEON_FP_H_SYNC_STRT_WID);*/ save->fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); - save->fp_v_sync_strt_wid = INREG(RADEON_FP_V_SYNC_STRT_WID); + /*save->fp_v_sync_strt_wid = INREG(RADEON_FP_V_SYNC_STRT_WID);*/ save->fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); save->lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL); save->lvds_pll_cntl = INREG(RADEON_LVDS_PLL_CNTL); save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL); save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL); save->bios_4_scratch = INREG(RADEON_BIOS_4_SCRATCH); save->bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH); save->bios_6_scratch = INREG(RADEON_BIOS_6_SCRATCH); @@ -7133,40 +5545,45 @@ /* Read CRTC2 registers */ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; save->dac2_cntl = INREG(RADEON_DAC_CNTL2); - save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); - save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); + if (IS_RV100_VARIANT) { + save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); + } else { + save->disp_output_cntl = INREG (RADEON_DISP_OUTPUT_CNTL); + } + save->disp_tv_out_cntl = INREG(RADEON_DISP_TV_OUT_CNTL); save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); save->crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); save->crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); save->crtc2_offset = INREG(RADEON_CRTC2_OFFSET); save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH); - save->fp2_h_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); - save->fp2_v_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); + save->fp_h2_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); + save->fp_v2_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); save->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL); save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL); } /* Read PLL registers */ static void RADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV); save->ppll_div_3 = INPLL(pScrn, RADEON_PPLL_DIV_3); save->htotal_cntl = INPLL(pScrn, RADEON_HTOTAL_CNTL); + save->vclk_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n", save->ppll_ref_div, save->ppll_div_3, save->htotal_cntl)); RADEONTRACE(("Read: rd=%d, fd=%d, pd=%d\n", save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, @@ -7174,16 +5591,17 @@ } /* Read PLL registers */ static void RADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) { save->p2pll_ref_div = INPLL(pScrn, RADEON_P2PLL_REF_DIV); save->p2pll_div_0 = INPLL(pScrn, RADEON_P2PLL_DIV_0); save->htotal_cntl2 = INPLL(pScrn, RADEON_HTOTAL2_CNTL); + save->pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n", save->p2pll_ref_div, save->p2pll_div_0, save->htotal_cntl2)); RADEONTRACE(("Read: rd=%d, fd=%d, pd=%d\n", save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, @@ -7191,51 +5609,59 @@ } /* Read palette data */ static void RADEONSavePalette(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; int i; + CARD32 tmp = 0; + + if (info->HasCRTC2) { + tmp = INPLL (pScrn, RADEON_PIXCLKS_CNTL); + OUTPLLP (pScrn, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + PAL_SELECT(1); + INPAL_START(0); + for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); + } -#ifdef ENABLE_FLAT_PANEL - /* Select palette 0 (main CRTC) if using FP-enabled chip */ - /* if (info->Port1 == MT_DFP) PAL_SELECT(1); */ -#endif - PAL_SELECT(1); - INPAL_START(0); - for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); PAL_SELECT(0); INPAL_START(0); for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT(); - save->palette_valid = TRUE; + + if (info->HasCRTC2) + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + } /* Save state that defines current video mode */ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONTRACE(("RADEONSaveMode(%p)\n", save)); - RADEONSaveMemMapRegisters(pScrn, save); - RADEONSaveCommonRegisters(pScrn, save); + if (info->IsSecondary) { - RADEONSaveCrtc2Registers(pScrn, save); - RADEONSavePLL2Registers(pScrn, save); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); + memcpy(&info->SavedReg, &info0->SavedReg, sizeof(RADEONSaveRec)); } else { - RADEONSavePLLRegisters(pScrn, save); - RADEONSaveCrtcRegisters(pScrn, save); - RADEONSaveFPRegisters(pScrn, save); - - if (info->MergedFB) { - RADEONSaveCrtc2Registers(pScrn, save); - RADEONSavePLL2Registers(pScrn, save); - } - /* RADEONSavePalette(pScrn, save); */ + RADEONSaveMemMapRegisters(pScrn, save); + RADEONSaveCommonRegisters(pScrn, save); + RADEONSavePLLRegisters (pScrn, save); + RADEONSaveCrtcRegisters (pScrn, save); + RADEONSaveFPRegisters (pScrn, save); + RADEONSaveCrtc2Registers (pScrn, save); + RADEONSavePLL2Registers (pScrn, save); + RADEONSavePalette(pScrn, save); + memcpy(&info->ModeReg, &info->SavedReg, sizeof(RADEONSaveRec)); } RADEONTRACE(("RADEONSaveMode returns %p\n", save)); } /* Save everything needed to restore the original VC state */ static void RADEONSave(ScrnInfoPtr pScrn) { @@ -7282,58 +5708,41 @@ } /* Restore the original (text) mode */ static void RADEONRestore(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr restore = &info->SavedReg; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONTRACE(("RADEONRestore\n")); #if X_BYTE_ORDER == X_BIG_ENDIAN RADEONWaitForFifo(pScrn, 1); OUTREG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); #endif if (info->FBDev) { + RADEONRestorePalette(pScrn, restore); fbdevHWRestore(pScrn); return; } RADEONBlank(pScrn); OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); RADEONPllErrataAfterIndex(info); OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); OUTREG(RADEON_GRPH2_BUFFER_CNTL, restore->grph2_buffer_cntl); - -#if 0 - /* M6 card has trouble restoring text mode for its CRT. - * This is fixed elsewhere and will be removed in the future. - */ - if ((xf86IsEntityShared(info->pEnt->index) || info->MergedFB) - && info->IsM6) - OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); -#endif - + RADEONRestoreMode(pScrn, restore); - if (!info->IsSecondary) - RADEONRestoreSurfaces(pScrn, restore); - -#if 0 - /* Temp fix to "solve" VT switch problems. When switching VTs on - * some systems, the console can either hang or the fonts can be - * corrupted. This hack solves the problem 99% of the time. A - * correct fix is being worked on. - */ - usleep(100000); -#endif + RADEONRestorePalette(pScrn, restore); #ifdef WITH_VGAHW if (info->VGAAccess) { vgaHWPtr hwp = VGAHWPTR(pScrn); if (!info->IsSecondary) { vgaHWUnlock(hwp); # if defined(__powerpc__) /* Temporary hack to prevent crashing on PowerMacs when trying to @@ -7387,463 +5796,322 @@ /* * If bursts are enabled, turn on discards * Radeon doesn't have write bursts */ if (save->bus_cntl & (RADEON_BUS_READ_BURST)) save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; } - -/* Calculate display buffer watermark to prevent buffer underflow */ -static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) +static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) { - RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONInfoPtr info2 = NULL; - - DisplayModePtr mode1, mode2; - - CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; - float mem_tcas; - int k1, c; - CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; - CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; - CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + RADEONInfoPtr info = RADEONPTR(pScrn); + int xres = mode->HDisplay; + int yres = mode->VDisplay; + float Hratio, Vratio; + RADEONMonitorType MonType; + RADEONTmdsType TmdsType; + + if (IsPrimary) { + MonType = pRADEONEnt->Controller[0].pPort->MonType; + TmdsType = pRADEONEnt->Controller[0].pPort->TMDSType; + } else { + MonType = pRADEONEnt->Controller[1].pPort->MonType; + TmdsType = pRADEONEnt->Controller[1].pPort->TMDSType; + } - CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + if (IsPrimary) { + if (info->PanelXRes == 0 || info->PanelYRes == 0) { + Hratio = 1.0; + Vratio = 1.0; + } else { + if (xres > info->PanelXRes) xres = info->PanelXRes; + if (yres > info->PanelYRes) yres = info->PanelYRes; - float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; - float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; - float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; + Hratio = (float)xres/(float)info->PanelXRes; + Vratio = (float)yres/(float)info->PanelYRes; + } - float mem_bw, peak_disp_bw; - float min_mem_eff = 0.8; - float sclk_eff, sclk_delay; - float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; - float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; - float pix_clk, pix_clk2; /* in MHz */ - int cur_size = 16; /* in octawords */ - int critical_point, critical_point2; - int stop_req, max_stop_req; - float read_return_rate, time_disp1_drop_priority; + save->fp_vert_stretch &= RADEON_VERT_STRETCH_RESERVED; + save->fp_horz_stretch &= (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); - /* - * Set display0/1 priority up on r3/4xx in the memory controller for - * high res modes if the user specifies HIGH for displaypriority - * option. - */ - if ((info->DispPriority == 2) && IS_R300_VARIANT) { - CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); - if (info->MergedFB || pRADEONEnt->HasSecondary) { - mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ + if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_horz_stretch |= ((xres/8-1)<<16); } else { - mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ + save->fp_horz_stretch |= ((((unsigned long)(Hratio * RADEON_HORZ_STRETCH_RATIO_MAX + + 0.5)) & RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((info->PanelXRes/8-1)<<16)); } - OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); - } - - /* R420 and RV410 family not supported yet */ - if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; - - if (pRADEONEnt->pSecondaryScrn) { - if (info->IsSecondary) return; - info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (info->MergedFB) info2 = info; - - /* - * Determine if there is enough bandwidth for current display mode - */ - mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); + if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_vert_stretch |= ((yres-1)<<12); + } else { + save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX + + 0.5)) & RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((info->PanelYRes-1)<<12)); + } + } - mode1 = info->CurrentLayout.mode; - if (info->MergedFB) { - mode1 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; - mode2 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; - } else if ((pRADEONEnt->HasSecondary) && info2) { - mode2 = info2->CurrentLayout.mode; - } else { - mode2 = NULL; - } + save->fp_gen_cntl |= (RADEON_FP_CRTC_DONT_SHADOW_VPAR | + RADEON_FP_CRTC_DONT_SHADOW_HEND ); - pix_clk = mode1->Clock/1000.0; - if (mode2) - pix_clk2 = mode2->Clock/1000.0; + if (pScrn->rgbBits == 8) + save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format, */ else - pix_clk2 = 0; - - peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); - if (info2) - peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); + save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT; /* 18 bit format, */ - if (peak_disp_bw >= mem_bw * min_mem_eff) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "You may not have enough display bandwidth for current mode\n" - "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); - } + info->PanelOff = FALSE; + /*This option is used to force the ONLY DEVICE in XFConfig to + use CRT port, instead of default DVI port */ + if (xf86ReturnOptValBool (info->Options, OPTION_PANEL_OFF, FALSE)) { + info->PanelOff = TRUE; + } - /* CRTC1 - Set GRPH_BUFFER_CNTL register using h/w defined optimal values. - GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] - */ - stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; + if (info->PanelOff && info->MergedFB) { + info->OverlayOnCRTC2 = TRUE; + if (MonType == MT_LCD) { + /* Turning off LVDS_ON seems to make panel white blooming. + * For now we just turn off display data ??? + */ + save->lvds_gen_cntl |= (RADEON_LVDS_DISPLAY_DIS); + save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); - /* setup Max GRPH_STOP_REQ default value */ - if (IS_RV100_VARIANT) - max_stop_req = 0x5c; - else - max_stop_req = 0x7c; - if (stop_req > max_stop_req) - stop_req = max_stop_req; - - /* Get values from the EXT_MEM_CNTL register...converting its contents. */ - temp = INREG(RADEON_MEM_TIMING_CNTL); - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; - mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; - mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; - } else { /* RV200 and later */ - mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; - mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; - mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; - } - - /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ - temp = INREG(RADEON_MEM_SDRAM_MODE_REG); - data = (temp & (7<<20)) >> 20; - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - mem_tcas = MemTcas [data]; + } else if (MonType == MT_DFP) + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); } else { - mem_tcas = MemTcas2 [data]; - } + if (MonType == MT_LCD) { - if (IS_R300_VARIANT) { + save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - /* on the R300, Tcas is included in Trbs. - */ - temp = INREG(RADEON_MEM_CNTL); - data = (R300_MEM_NUM_CHANNELS_MASK & temp); - if (data == 1) { - if (R300_MEM_USE_CD_CH_ONLY & temp) { - temp = INREG(R300_MC_IND_INDEX); - temp &= ~R300_MC_IND_ADDR_MASK; - temp |= R300_MC_READ_CNTL_CD_mcind; - OUTREG(R300_MC_IND_INDEX, temp); - temp = INREG(R300_MC_IND_DATA); - data = (R300_MEM_RBS_POSITION_C_MASK & temp); - } else { - temp = INREG(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } else if ((MonType == MT_DFP) && (TmdsType == TMDS_INT)) { + int i; + CARD32 tmp = save->tmds_pll_cntl & 0xfffff; + for (i=0; i<4; i++) { + if (info->tmds_pll[i].freq == 0) break; + if ((CARD32)(mode->Clock/10) < info->tmds_pll[i].freq) { + tmp = info->tmds_pll[i].value ; + break; + } } - } else { - temp = INREG(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); - } + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (tmp & 0xfff00000) + save->tmds_pll_cntl = tmp; + else { + save->tmds_pll_cntl &= 0xfff00000; + save->tmds_pll_cntl |= tmp; + } + } else save->tmds_pll_cntl = tmp; - mem_trbs = MemTrbs[data]; - mem_tcas += mem_trbs; - } + save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_R200) || !info->HasCRTC2) + save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); + else /* weird, RV chips got this bit reversed? */ + save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - /* DDR64 SCLK_EFF = SCLK for analysis */ - sclk_eff = info->sclk; - } else { -#ifdef XF86DRI - if (info->directRenderingEnabled) - sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); - else -#endif - sclk_eff = info->sclk; + save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } } - /* Find the memory controller latency for the display client. - */ - if (IS_R300_VARIANT) { - /*not enough for R350 ???*/ - /* - if (!mode2) sclk_delay = 150; - else { - if (info->RamWidth == 256) sclk_delay = 87; - else sclk_delay = 97; - } - */ - sclk_delay = 250; - } else { - if ((info->ChipFamily == CHIP_FAMILY_RV100) || - info->IsIGP) { - if (info->IsDDR) sclk_delay = 41; - else sclk_delay = 33; - } else { - if (info->RamWidth == 128) sclk_delay = 57; - else sclk_delay = 41; - } + info->BiosHotkeys = FALSE; + /* + * Allow the bios to toggle outputs. see below for more. + */ + if (info->IsMobility) { + if (xf86ReturnOptValBool(info->Options, OPTION_BIOS_HOTKEYS, FALSE)) { + info->BiosHotkeys = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Enabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Disabled\n"); + } } - mc_latency_sclk = sclk_delay / sclk_eff; - - if (info->IsDDR) { - if (info->RamWidth == 32) { - k1 = 40; - c = 3; + if (info->IsMobility && (!info->BiosHotkeys)) { + + /* To work correctly with laptop hotkeys. + * Since there is no machnism for accessing ACPI evnets + * and the driver currently doesn't know how to validate + * a mode dynamically, we have to tell BIOS don't do + * display switching after X has started. + * If LCD is on, lid close/open should still work + * with below settings + */ + if (info->DisplayType == MT_LCD) { + if (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT) + save->bios_5_scratch = 0x0201; + else if (pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) + save->bios_5_scratch = 0x0801; } else { - k1 = 20; - c = 1; + if (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT) + save->bios_5_scratch = 0x0200; + else if (pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) + save->bios_5_scratch = 0x0800; + else + save->bios_5_scratch = 0x0; } - } else { - k1 = 40; - c = 3; - } - mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / - info->mclk) + (4.0 / sclk_eff); - - /* - HW cursor time assuming worst case of full size colour cursor. - */ - cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; - cur_latency_sclk = cur_size / sclk_eff; - - /* - Find the total latency for the display data. - */ - disp_latency_overhead = 8.0 / info->sclk; - mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; - mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; - disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); + save->bios_4_scratch = 0x4; + save->bios_6_scratch |= 0x40000000; - /* - Find the drain rate of the display buffer. - */ - disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); - if (info2) - disp_drain_rate2 = pix_clk2 / (16.0/info2->CurrentLayout.pixel_bytes); - else - disp_drain_rate2 = 0; + } else if (info->IsMobility && (info->DisplayType == MT_LCD)) { - /* - Find the critical point of the display buffer. - */ - critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); + /* BIOS will use this setting to reset displays upon lid close/open. + * Here we let BIOS controls LCD, but the driver will control the external CRT. + */ + if (info->MergedFB || pRADEONEnt->HasSecondary) + save->bios_5_scratch = 0x01020201; - /* ???? */ - /* - temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; - if (critical_point < temp) critical_point = temp; - */ - if (info->DispPriority == 2) { - if (mode2) { - /*??some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ - if (info->ChipFamily == CHIP_FAMILY_R300) - critical_point += 0x10; - else - critical_point = 0; - } - else - critical_point = 0; } +} - /* - The critical point should never be above max_stop_req-4. Setting - GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. - */ - if (max_stop_req - critical_point < 4) critical_point = 0; - - temp = info->SavedReg.grph_buffer_cntl; - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((info->ChipFamily == CHIP_FAMILY_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; +static void RADEONInitTvDacCntl(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + if (info->ChipFamily == CHIP_FAMILY_R420) { + save->tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + R420_TV_DAC_DACADJ_MASK | + R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_TVENABLE); + } else { + save->tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_GDACPD); } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - /* - Write the result into the register. - */ - OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - - RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", - info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); - - if (mode2) { - stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; - - if (stop_req > max_stop_req) stop_req = max_stop_req; - - temp = info->SavedReg.grph2_buffer_cntl; - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((info->ChipFamily == CHIP_FAMILY_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; - } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) - critical_point2 = 0; - else { - read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); - time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); + save->tv_dac_cntl = (RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_DAC_STD_PS2 | + info->tv_dac_adj); +} - critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + - disp_latency) * disp_drain_rate2 + 0.5); +/* Define CRTC registers for requested video mode. */ +Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, RADEONInfoPtr info) +{ + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; - if (info->DispPriority == 2) { - if (info->ChipFamily == CHIP_FAMILY_R300) - critical_point2 += 0x10; - else - critical_point2 = 0; - } + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - if (max_stop_req - critical_point2 < 4) critical_point2 = 0; + pRADEONEnt->Controller[0].IsUsed = TRUE; + pRADEONEnt->Controller[0].IsActive = TRUE; + pRADEONEnt->Controller[0].pCurMode = mode; - } + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); + return FALSE; + } - OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + | RADEON_CRTC_EN + | (format << 8) + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); - RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", - info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); - } -} + save->crtc_ext_cntl |= (RADEON_CRTC_CRT_ON | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); -/* Define CRTC registers for requested video mode */ -static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, RADEONInfoPtr info) -{ - unsigned char *RADEONMMIO = info->MMIO; + save->surface_cntl = 0; + save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; + save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* Alhought we current onlu use aperture 0, also setting aperture 1 should not harm -ReneR */ + switch (pScrn->bitsPerPixel) { + case 16: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; + break; - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; + case 32: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; + break; } - - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - if (mode->Flags & RADEON_USE_RMX) { -#if 0 - mode->CrtcHDisplay = info->PanelXRes; - mode->CrtcVDisplay = info->PanelYRes; #endif - mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; - mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; - mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; - mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; - mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; - mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; - mode->Clock = info->DotClock; - mode->Flags = info->Flags | RADEON_USE_RMX; - } - } - - save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN - | RADEON_CRTC_EN - | (format << 8) - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC_INTERLACE_EN - : 0)); - /* Don't try to be smart and unconditionally enable the analog output - * for now as the dodgy code to handle it for the second head doesn't - * work. This will be correctly fixed when Alex' megapatch gets in that - * reworks the whole output mapping - */ -#if 0 - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - save->crtc_ext_cntl = RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN; - save->crtc_gen_cntl &= ~(RADEON_CRTC_DBL_SCAN_EN | - RADEON_CRTC_CSYNC_EN | - RADEON_CRTC_INTERLACE_EN); - } else -#endif - { - save->crtc_ext_cntl = (RADEON_VGA_ATI_LINEAR | - RADEON_XCRT_CNT_EN | - RADEON_CRTC_CRT_ON); + save->crtc_more_cntl = 0; + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. + */ + save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; } - save->dac_cntl = (RADEON_DAC_MASK_ALL - | RADEON_DAC_VGA_ADR_EN - | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); + if (mode->Flags & RADEON_USE_RMX) { + mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; + mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; + mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; + mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; + mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; + mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; + mode->Clock = info->DotClock; + mode->Flags = info->Flags | RADEON_USE_RMX; + } save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) - << 16)); + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; hsync_start = mode->CrtcHSyncStart - 8; save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : RADEON_CRTC_H_SYNC_POL)); -#if 1 - /* This works for double scan mode. */ - save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); -#else - /* This is what cce/nbmode.c example code - * does -- is this correct? - */ + /* This works for double scan mode. */ save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) - << 16)); -#endif + | ((mode->CrtcVDisplay - 1) << 16)); vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0)); + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : RADEON_CRTC_V_SYNC_POL)); - save->crtc_offset = pScrn->fbOffset; - save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); + save->crtc_offset = 0; + /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL);*/ if (info->tilingEnabled) { if (IS_R300_VARIANT) save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | R300_CRTC_MICRO_TILE_BUFFER_DIS | R300_CRTC_MACRO_TILE_EN); else save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; } @@ -7851,50 +6119,109 @@ if (IS_R300_VARIANT) save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | R300_CRTC_MICRO_TILE_BUFFER_DIS | R300_CRTC_MACRO_TILE_EN); else save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; } - save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); + save->crtc_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); save->crtc_pitch |= save->crtc_pitch << 16; - save->crtc_more_cntl = 0; - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) { - /* This is to workaround the asic bug for RMX, some versions - of BIOS dosen't have this register initialized correctly. - */ - save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + save->vclk_cntl = (info->SavedReg.vclk_cntl & + ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; + + + /* Set following registers for all cases first, if a DFP/LCD is connected on + internal TMDS/LVDS port, they will be set by RADEONInitFPRegister + */ + if (!info->IsSwitching) { + save->fp_gen_cntl = 0; + save->fp_vert_stretch &= RADEON_VERT_STRETCH_RESERVED; + save->fp_horz_stretch &= (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); } - save->surface_cntl = 0; - save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; - save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + if (pRADEONEnt->Controller[0].pPort->MonType == MT_CRT) { + if (pRADEONEnt->Controller[0].pPort->DACType == DAC_PRIMARY) { + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; + } else { + save->dac2_cntl &= ~(RADEON_DAC2_DAC_CLK_SEL); + } + save->dac_cntl = (RADEON_DAC_MASK_ALL + | RADEON_DAC_VGA_ADR_EN + | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); + } else { + /*0x0028023;*/ + RADEONInitTvDacCntl(pScrn, save); + save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + if(IS_R300_VARIANT) { + save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (RADEON_FP2_ON | + RADEON_FP2_BLANK_EN | + RADEON_FP2_DVO_EN); + } else { + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + } + } + } else if ((pRADEONEnt->Controller[0].pPort->MonType == MT_DFP) || + (pRADEONEnt->Controller[0].pPort->MonType == MT_LCD)) { -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* We must set both apertures as they can be both used to map the entire - * video memory. -BenH. - */ - switch (pScrn->bitsPerPixel) { - case 16: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; - break; + save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; + save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; - case 32: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; - break; - } -#endif + RADEONInitFPRegisters(pScrn, save, mode, TRUE); + + if ((pRADEONEnt->Controller[0].pPort->TMDSType == TMDS_INT) || + (pRADEONEnt->Controller[0].pPort->MonType == MT_LCD)) { + + if (pRADEONEnt->Controller[0].pPort->MonType == MT_LCD) { + save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; + } else { + if ((IS_R300_VARIANT) || + (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + if (mode->Flags & RADEON_USE_RMX) + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; + else + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; + } + } else { + + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_EN | + RADEON_FP2_DVO_RATE_SEL_SDR); + if (mode->Flags & RADEON_USE_RMX) + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_SRC_SEL_CRTC2 | + RADEON_FP2_DVO_RATE_SEL_SDR); + } + save->fp2_gen_cntl |= ( RADEON_FP2_ON | + RADEON_FP2_BLANK_EN | + RADEON_FP2_DVO_EN); + if (pScrn->rgbBits == 8) + save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + } + } if (info->IsDellServer) { save->dac2_cntl = info->SavedReg.dac2_cntl; save->tv_dac_cntl = info->SavedReg.tv_dac_cntl; save->crtc2_gen_cntl = info->SavedReg.crtc2_gen_cntl; save->disp_hw_debug = info->SavedReg.disp_hw_debug; save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; @@ -7903,143 +6230,89 @@ /* For CRT on DAC2, don't turn it on if BIOS didn't enable it, even it's detected. */ save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); } - RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", - save->crtc_pitch, pScrn->virtualX, - info->CurrentLayout.displayWidth)); return TRUE; -} +} -/* Define CRTC2 registers for requested video mode */ -static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, RADEONInfoPtr info) +/* Define CRTC2 registers for requested video mode. */ +Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, RADEONInfoPtr info) { - unsigned char *RADEONMMIO = info->MMIO; + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = NULL; + if (info->IsSecondary) + info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; + pRADEONEnt->Controller[1].IsUsed = TRUE; + pRADEONEnt->Controller[1].IsActive = TRUE; + pRADEONEnt->Controller[1].pCurMode = mode; switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - save->crtc2_gen_cntl = (RADEON_CRTC2_EN - | RADEON_CRTC2_CRT2_ON - | (format << 8) - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC2_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC2_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC2_INTERLACE_EN - : 0)); - - /* Turn CRT on in case the first head is a DFP */ - save->dac2_cntl = info->SavedReg.dac2_cntl; - /* always let TVDAC drive CRT2, we don't support tvout yet */ - save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; - save->disp_output_cntl = info->SavedReg.disp_output_cntl; - if (info->ChipFamily == CHIP_FAMILY_R200 || - IS_R300_VARIANT) { - save->disp_output_cntl &= ~(RADEON_DISP_DAC_SOURCE_MASK | - RADEON_DISP_DAC2_SOURCE_MASK); - if (pRADEONEnt->MonType1 != MT_CRT) { - save->disp_output_cntl |= (RADEON_DISP_DAC_SOURCE_CRTC2 | - RADEON_DISP_DAC2_SOURCE_CRTC2); - } else { - if (pRADEONEnt->ReversedDAC) { - save->disp_output_cntl |= RADEON_DISP_DAC2_SOURCE_CRTC2; - } else { - save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; - } - } - } else { - save->disp_hw_debug = info->SavedReg.disp_hw_debug; - /* Turn on 2nd CRT */ - if (pRADEONEnt->MonType1 != MT_CRT) { - /* This is for some sample boards with the VGA port - connected to the TVDAC, but BIOS doesn't reflect this. - Here we configure both DACs to use CRTC2. - Not sure if this happens in any retail board. - */ - save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; - save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; - } else { - if (pRADEONEnt->ReversedDAC) { - save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; - save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; - } else { - save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; - save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; - } - } + case 4: format = 1; + break; + case 8: format = 2; + break; + case 15: format = 3; + break; /* 555 */ + case 16: format = 4; + break; /* 565 */ + case 24: format = 5; + break; /* RGB */ + case 32: format = 6; + break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); + return FALSE; } - save->crtc2_h_total_disp = - ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; hsync_start = mode->CrtcHSyncStart - 8; save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : RADEON_CRTC_H_SYNC_POL)); -#if 1 - /* This works for double scan mode. */ - save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); -#else - /* This is what cce/nbmode.c example code - * does -- is this correct? - */ + /* This works for double scan mode. */ save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) - << 16)); -#endif + | ((mode->CrtcVDisplay - 1) << 16)); vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC2_V_SYNC_POL - : 0)); + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC2_V_SYNC_POL + : RADEON_CRTC2_V_SYNC_POL)); /* It seems all fancy options apart from pflip can be safely disabled */ - save->crtc2_offset = pScrn->fbOffset; - save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & RADEON_CRTC_OFFSET_FLIP_CNTL; + save->crtc2_offset = 0; + /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & RADEON_CRTC_OFFSET_FLIP_CNTL;*/ + save->crtc2_offset_cntl &= RADEON_CRTC_OFFSET_FLIP_CNTL; if (info->tilingEnabled) { if (IS_R300_VARIANT) save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | R300_CRTC_MICRO_TILE_BUFFER_DIS | R300_CRTC_MACRO_TILE_EN); else save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; } @@ -8047,332 +6320,143 @@ if (IS_R300_VARIANT) save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | R300_CRTC_MICRO_TILE_BUFFER_DIS | R300_CRTC_MACRO_TILE_EN); else save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; } - /* this should be right */ - if (info->MergedFB) { - save->crtc2_pitch = (((info->CRT2pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); - save->crtc2_pitch |= save->crtc2_pitch << 16; - } else { - save->crtc2_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); + save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); save->crtc2_pitch |= save->crtc2_pitch << 16; - } + + save->crtc2_gen_cntl = (RADEON_CRTC2_EN + | RADEON_CRTC2_CRT2_ON + | (format << 8) + | RADEON_CRTC2_VSYNC_DIS + | RADEON_CRTC2_HSYNC_DIS + | RADEON_CRTC2_DISP_DIS + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC2_INTERLACE_EN + : 0)); + save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); + + if (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT) { + if (pRADEONEnt->Controller[1].pPort->DACType == DAC_PRIMARY) { + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + } else { + save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; + } + } else { + /*save->tv_dac_cntl = 0x0028023;*/ + RADEONInitTvDacCntl(pScrn, save); + if(IS_R300_VARIANT) { + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 | + RADEON_FP2_BLANK_EN | + RADEON_FP2_ON | + RADEON_FP2_DVO_EN); + save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; + save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; + } else { + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + } + } + } else if ((pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) || + (pRADEONEnt->Controller[1].pPort->MonType == MT_LCD)) { - if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->MergeType == MT_DFP) { - save->crtc2_gen_cntl = (RADEON_CRTC2_EN | (format << 8)); - save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid; - save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid; - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | RADEON_FP2_ON; - save->fp2_gen_cntl &= ~(RADEON_FP2_BLANK_EN); + save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; + save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; - if ((info->ChipFamily == CHIP_FAMILY_R200) || - IS_R300_VARIANT) { - save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_RATE_SEL_SDR); + if ((pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_INT) || + (pRADEONEnt->Controller[1].pPort->MonType == MT_LCD)) { - save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 | - RADEON_FP2_DVO_EN); - } else { - save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_MASK; - save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; - } + RADEONInitFPRegisters(pScrn, save, mode, FALSE); - if (pScrn->rgbBits == 8) - save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format */ - else - save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format */ + if (pRADEONEnt->Controller[1].pPort->MonType == MT_LCD) { + save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; + } else { + if ((IS_R300_VARIANT) || + (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; + } + } else { + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 | + RADEON_FP2_PANEL_FORMAT | + RADEON_FP2_BLANK_EN | + RADEON_FP2_ON | + RADEON_FP2_DVO_EN); + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (RADEON_FP2_SRC_SEL_CRTC2 | + RADEON_FP2_PANEL_FORMAT | + RADEON_FP2_BLANK_EN | + RADEON_FP2_ON | + RADEON_FP2_DVO_EN); + } + if (pScrn->rgbBits == 8) + save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + } + } + + + save->pixclks_cntl = ((info->SavedReg.pixclks_cntl & + ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); - } /* We must set SURFACE_CNTL properly on the second screen too */ save->surface_cntl = 0; #if X_BYTE_ORDER == X_BIG_ENDIAN - /* We must set both apertures as they can be both used to map the entire - * video memory. -BenH. - */ + /* Alhought we current onlu use aperture 0, also setting aperture 1 should not harm -ReneR */ switch (pScrn->bitsPerPixel) { case 16: save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; break; case 32: save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; break; } #endif - - RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", - save->crtc2_pitch, pScrn->virtualX, - info->CurrentLayout.displayWidth)); - + return TRUE; } -/* Define CRTC registers for requested video mode */ -static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, - RADEONSavePtr save, DisplayModePtr mode, - RADEONInfoPtr info) -{ - int xres = mode->HDisplay; - int yres = mode->VDisplay; - float Hratio, Vratio; - - /* If the FP registers have been initialized before for a panel, - * but the primary port is a CRT, we need to reinitialize - * FP registers in order for CRT to work properly - */ - - if ((info->DisplayType != MT_DFP) && (info->DisplayType != MT_LCD)) { - save->fp_crtc_h_total_disp = orig->fp_crtc_h_total_disp; - save->fp_crtc_v_total_disp = orig->fp_crtc_v_total_disp; - save->fp_gen_cntl = 0; - save->fp_h_sync_strt_wid = orig->fp_h_sync_strt_wid; - save->fp_horz_stretch = 0; - save->fp_v_sync_strt_wid = orig->fp_v_sync_strt_wid; - save->fp_vert_stretch = 0; - save->lvds_gen_cntl = orig->lvds_gen_cntl; - save->lvds_pll_cntl = orig->lvds_pll_cntl; - save->tmds_pll_cntl = orig->tmds_pll_cntl; - save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; - - save->lvds_gen_cntl |= ( RADEON_LVDS_DISPLAY_DIS | (1 << 23)); - save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); - save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - - return; - } - - if (info->PanelXRes == 0 || info->PanelYRes == 0) { - Hratio = 1.0; - Vratio = 1.0; - } else { - if (xres > info->PanelXRes) xres = info->PanelXRes; - if (yres > info->PanelYRes) yres = info->PanelYRes; - - Hratio = (float)xres/(float)info->PanelXRes; - Vratio = (float)yres/(float)info->PanelYRes; - } - - if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_horz_stretch = orig->fp_horz_stretch; - save->fp_horz_stretch &= ~(RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE); - save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO | - RADEON_HORZ_PANEL_SIZE); - save->fp_horz_stretch |= ((xres/8-1)<<16); - - } else { - save->fp_horz_stretch = - ((((unsigned long)(Hratio * RADEON_HORZ_STRETCH_RATIO_MAX + - 0.5)) & RADEON_HORZ_STRETCH_RATIO_MASK)) | - (orig->fp_horz_stretch & (RADEON_HORZ_PANEL_SIZE | - RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC)); - save->fp_horz_stretch |= (RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE); - - save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO | - RADEON_HORZ_PANEL_SIZE); - save->fp_horz_stretch |= ((info->PanelXRes / 8 - 1) << 16); - - } - - if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_vert_stretch = orig->fp_vert_stretch; - save->fp_vert_stretch &= ~(RADEON_VERT_STRETCH_ENABLE| - RADEON_VERT_STRETCH_BLEND); - save->fp_vert_stretch &= ~(RADEON_VERT_AUTO_RATIO_EN | - RADEON_VERT_PANEL_SIZE); - save->fp_vert_stretch |= ((yres-1) << 12); - } else { - save->fp_vert_stretch = - (((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX + - 0.5)) & RADEON_VERT_STRETCH_RATIO_MASK)) | - (orig->fp_vert_stretch & (RADEON_VERT_PANEL_SIZE | - RADEON_VERT_STRETCH_RESERVED))); - save->fp_vert_stretch |= (RADEON_VERT_STRETCH_ENABLE | - RADEON_VERT_STRETCH_BLEND); - - save->fp_vert_stretch &= ~(RADEON_VERT_AUTO_RATIO_EN | - RADEON_VERT_PANEL_SIZE); - save->fp_vert_stretch |= ((info->PanelYRes-1) << 12); - - } - - save->fp_gen_cntl = (orig->fp_gen_cntl & (CARD32) - ~(RADEON_FP_SEL_CRTC2 | - RADEON_FP_RMX_HVSYNC_CONTROL_EN | - RADEON_FP_DFP_SYNC_SEL | - RADEON_FP_CRT_SYNC_SEL | - RADEON_FP_CRTC_LOCK_8DOT | - RADEON_FP_USE_SHADOW_EN | - RADEON_FP_CRTC_USE_SHADOW_VEND | - RADEON_FP_CRT_SYNC_ALT)); - save->fp_gen_cntl |= (RADEON_FP_CRTC_DONT_SHADOW_VPAR | - RADEON_FP_CRTC_DONT_SHADOW_HEND ); - - if (pScrn->rgbBits == 8) - save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ - else - save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ - - if (IS_R300_VARIANT || - (info->ChipFamily == CHIP_FAMILY_R200)) { - save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - if (mode->Flags & RADEON_USE_RMX) - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; - else - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; - } else - save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; - - save->lvds_gen_cntl = orig->lvds_gen_cntl; - save->lvds_pll_cntl = orig->lvds_pll_cntl; - - info->PanelOff = FALSE; - /* This option is used to force the ONLY DEVICE in XFConfig to use - * CRT port, instead of default DVI port. - */ - if (xf86ReturnOptValBool(info->Options, OPTION_PANEL_OFF, FALSE)) { - info->PanelOff = TRUE; - } - - save->tmds_pll_cntl = orig->tmds_pll_cntl; - save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; - if (info->PanelOff && info->MergedFB) { - info->OverlayOnCRTC2 = TRUE; - if (info->DisplayType == MT_LCD) { - /* Turning off LVDS_ON seems to make panel white blooming. - * For now we just turn off display data ??? - */ - save->lvds_gen_cntl |= (RADEON_LVDS_DISPLAY_DIS); - save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); - - } else if (info->DisplayType == MT_DFP) - save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else { - if (info->DisplayType == MT_LCD) { - - save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); - save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - - } else if (info->DisplayType == MT_DFP) { - int i; - CARD32 tmp = orig->tmds_pll_cntl & 0xfffff; - for (i=0; i<4; i++) { - if (info->tmds_pll[i].freq == 0) break; - if (save->dot_clock_freq < info->tmds_pll[i].freq) { - tmp = info->tmds_pll[i].value ; - break; - } - } - if (IS_R300_VARIANT || - (info->ChipFamily == CHIP_FAMILY_RV280)) { - if (tmp & 0xfff00000) - save->tmds_pll_cntl = tmp; - else - save->tmds_pll_cntl = (orig->tmds_pll_cntl & 0xfff00000) | tmp; - } else save->tmds_pll_cntl = tmp; - - RADEONTRACE(("TMDS_PLL from %x to %x\n", - orig->tmds_pll_cntl, - save->tmds_pll_cntl)); - - save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); - if (IS_R300_VARIANT || - (info->ChipFamily == CHIP_FAMILY_R200) || !info->HasCRTC2) - save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); - else /* weird, RV chips got this bit reversed? */ - save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); - - save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } - } - - info->BiosHotkeys = TRUE; - /* - * Allow the bios to toggle outputs. see below for more. - */ - if (xf86ReturnOptValBool(info->Options, OPTION_BIOS_HOTKEYS, TRUE)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Enabled\n"); - } else { - info->BiosHotkeys = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Disabled\n"); - } - - if (info->IsMobility && (!info->BiosHotkeys)) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - /* To work correctly with laptop hotkeys. - * Since there is no machnism for accessing ACPI evnets - * and the driver currently doesn't know how to validate - * a mode dynamically, we have to tell BIOS don't do - * display switching after X has started. - * If LCD is on, lid close/open should still work - * with below settings - */ - if (info->DisplayType == MT_LCD) { - if (pRADEONEnt->MonType2 == MT_CRT) - save->bios_5_scratch = 0x0201; - else if (pRADEONEnt->MonType2 == MT_DFP) - save->bios_5_scratch = 0x0801; - else - save->bios_5_scratch = orig->bios_5_scratch; - } else { - if (pRADEONEnt->MonType2 == MT_CRT) - save->bios_5_scratch = 0x0200; - else if (pRADEONEnt->MonType2 == MT_DFP) - save->bios_5_scratch = 0x0800; - else - save->bios_5_scratch = 0x0; - } - save->bios_4_scratch = 0x4; - save->bios_6_scratch = orig->bios_6_scratch | 0x40000000; - - } else if (info->IsMobility && (info->DisplayType == MT_LCD)) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - /* BIOS will use this setting to reset displays upon lid close/open. - * Here we let BIOS controls LCD, but the driver will control the external CRT. - */ - if (info->MergedFB || pRADEONEnt->HasSecondary) - save->bios_5_scratch = 0x01020201; - else - save->bios_5_scratch = orig->bios_5_scratch; - - save->bios_4_scratch = orig->bios_4_scratch; - save->bios_6_scratch = orig->bios_6_scratch; - - } - - save->fp_crtc_h_total_disp = save->crtc_h_total_disp; - save->fp_crtc_v_total_disp = save->crtc_v_total_disp; - save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; - save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; -} - /* Define PLL registers for requested video mode */ -static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info, - RADEONSavePtr save, RADEONPLLPtr pll, - double dot_clock) +static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + RADEONPLLPtr pll, double dot_clock) { + RADEONInfoPtr info = RADEONPTR(pScrn); unsigned long freq = dot_clock * 100; struct { int divider; int bitvalue; } *post_div, post_divs[] = { /* From RAGE 128 VR/RAGE 128 GL Register * Reference Manual (Technical Reference @@ -8487,31 +6571,24 @@ save->post_div_2)); save->p2pll_ref_div = pll->reference_div; save->p2pll_div_0 = (save->feedback_div_2 | (post_div->bitvalue << 16)); save->htotal_cntl2 = 0; } -#if 0 -/* Define initial palette for requested video mode. This doesn't do - * anything for XFree86 4.0. - */ -static void RADEONInitPalette(RADEONSavePtr save) -{ - save->palette_valid = FALSE; -} -#endif - /* Define registers for a requested video mode */ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = NULL; + ScrnInfoPtr pScrn0 = NULL; double dot_clock = mode->Clock/1000.0; #if RADEON_DEBUG ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", mode->name, dot_clock, mode->HDisplay, @@ -8558,84 +6635,76 @@ ErrorF("\n"); #endif info->Flags = mode->Flags; RADEONInitMemMapRegisters(pScrn, save, info); RADEONInitCommonRegisters(save, info); if (info->IsSecondary) { - if (!RADEONInitCrtc2Registers(pScrn, save, mode, info)) - return FALSE; - RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT); - } else if (info->MergedFB) { - if (!RADEONInitCrtcRegisters(pScrn, save, - ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, info)) - return FALSE; - dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT1)->Clock / 1000.0; - if (dot_clock) { - RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock); - } else { - save->ppll_ref_div = info->SavedReg.ppll_ref_div; - save->ppll_div_3 = info->SavedReg.ppll_div_3; - save->htotal_cntl = info->SavedReg.htotal_cntl; - } - RADEONInitCrtc2Registers(pScrn, save, - ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info); - dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT2)->Clock / 1000.0; - RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->MergeType != MT_CRT); + pScrn0 = pRADEONEnt->pPrimaryScrn; + info0 = RADEONPTR(pScrn0); + RADEONInitCrtc2Registers(pScrn, save, mode, info); + RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock,info->DisplayType != MT_CRT); + /* Make sure primary has the same copy */ + memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); } else { - if (!RADEONInitCrtcRegisters(pScrn, save, mode, info)) - return FALSE; - dot_clock = mode->Clock/1000.0; + if (info->MergedFB) { + RADEONInitCrtcRegisters(pScrn, save, + ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, info); + dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT1)->Clock / 1000.0; + } else { + RADEONInitCrtcRegisters(pScrn, save, mode, info); + dot_clock = mode->Clock/1000.0; + } if (dot_clock) { - RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock); + RADEONInitPLLRegisters(pScrn, save, &info->pll, dot_clock); } else { save->ppll_ref_div = info->SavedReg.ppll_ref_div; save->ppll_div_3 = info->SavedReg.ppll_div_3; save->htotal_cntl = info->SavedReg.htotal_cntl; } - /* Not used for now: */ - /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ - } - - /* make RMX work for mergedfb modes on the LCD */ - if (info->MergedFB) { - if ((info->MergeType == MT_LCD) || (info->MergeType == MT_DFP)) { - /* I suppose crtc2 could drive the FP as well... */ - RADEONInitFPRegisters(pScrn, &info->SavedReg, save, + if (pRADEONEnt->HasSecondary) { + pScrn0 = pRADEONEnt->pSecondaryScrn; + info0 = RADEONPTR(pScrn0); + /* carry over to secondary screen */ + memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); + } else if (info->MergedFB) { + RADEONInitCrtc2Registers(pScrn, save, ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info); + dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT2)->Clock / 1000.0; + RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT); } - else { - RADEONInitFPRegisters(pScrn, &info->SavedReg, save, - ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, info); - } - } - else { - RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); } RADEONTRACE(("RADEONInit returns %p\n", save)); return TRUE; } /* Initialize a new mode */ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONTRACE(("RADEONModeInit()\n")); if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE; pScrn->vtSema = TRUE; - RADEONBlank(pScrn); - RADEONRestoreMode(pScrn, &info->ModeReg); - RADEONUnblank(pScrn); + + /* Make sure all restore routines are only called once + after everything is initialized + */ + if ((!pRADEONEnt->HasSecondary) || info->IsSwitching) { + RADEONBlank(pScrn); + RADEONRestoreMode(pScrn, &info->ModeReg); + RADEONUnblank(pScrn); + } info->CurrentLayout.mode = mode; if (info->DispPriority) RADEONInitDispBandwidth(pScrn); return TRUE; } @@ -8782,19 +6851,17 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; int reg, Base, regcntl, crtcoffsetcntl, xytilereg, crtcxytile; #ifdef XF86DRI RADEONSAREAPrivPtr pSAREAPriv; XF86DRISAREAPtr pSAREA; #endif -#if 0 /* Verbose */ RADEONTRACE(("RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone)); -#endif if (info->showCache && y) { int lastline = info->FbMapSize / ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); lastline -= pScrn->currentMode->VDisplay; y += (pScrn->virtualY - 1) * (y / 3 + 1); if (y > lastline) y = lastline; @@ -8837,24 +6904,23 @@ int byteshift = info->CurrentLayout.bitsPerPixel >> 4; /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); crtcoffsetcntl = crtcoffsetcntl | (y % 16); } } else { - int offset = y * info->CurrentLayout.displayWidth + x; + Base += y * info->CurrentLayout.displayWidth + x; switch (info->CurrentLayout.pixel_code) { case 15: - case 16: offset *= 2; break; - case 24: offset *= 3; break; - case 32: offset *= 4; break; + case 16: Base *= 2; break; + case 24: Base *= 3; break; + case 32: Base *= 4; break; } - Base += offset; } Base &= ~7; /* 3 lower bits are always 0 */ #ifdef XF86DRI if (info->directRenderingInited) { /* note cannot use pScrn->pScreen since this is unitialized when called from RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ @@ -8878,21 +6944,25 @@ } if (pSAREAPriv->pfCurrentPage == 1) { Base += info->backOffset; } } #endif + RADEONTRACE((" -> reg : 0x%04x = 0x%08x\n", reg, Base)); + OUTREG(reg, Base); if (IS_R300_VARIANT) { + RADEONTRACE((" regcntl : 0x%04x = 0x%08x\n", xytilereg, crtcxytile)); OUTREG(xytilereg, crtcxytile); } else { + RADEONTRACE((" regcntl : 0x%04x = 0x%08x\n", regcntl, crtcoffsetcntl)); OUTREG(regcntl, crtcoffsetcntl); } } _X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; @@ -8920,16 +6990,17 @@ /* Called when VT switching back to the X server. Reinitialize the * video mode. */ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONTRACE(("RADEONEnterVT\n")); if (INREG(RADEON_CONFIG_MEMSIZE) == 0) { /* Softboot V_BIOS */ xf86Int10InfoPtr pInt; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "zero MEMSIZE, probably at D3cold. Re-POSTing via int10.\n"); @@ -8939,36 +7010,34 @@ xf86ExecX86int10 (pInt); xf86FreeInt10 (pInt); } } /* Makes sure the engine is idle before doing anything */ RADEONWaitForIdleMMIO(pScrn); + if (!pRADEONEnt->HasSecondary) { + RADEONRestorePalette(pScrn, &info->ModeReg); + } + if (info->FBDev) { unsigned char *RADEONMMIO = info->MMIO; if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; - info->PaletteSavedOnVT = FALSE; + info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); } else if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; if (!info->IsSecondary) RADEONRestoreSurfaces(pScrn, &info->ModeReg); #ifdef XF86DRI if (info->directRenderingEnabled) { - if (info->cardType == CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19 && info->FbSecureSize) - { - /* we need to backup the PCIE GART TABLE from fb memory */ - memcpy(info->FB + info->pciGartOffset, info->pciGartBackup, info->pciGartSize); - } - /* get the DRI back into shape after resume */ RADEONDRIResume(pScrn->pScreen); RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg); } #endif /* this will get XVideo going again, but only if XVideo was initialised during server startup (hence the info->adaptor if). */ if (info->adaptor) @@ -8991,35 +7060,46 @@ /* Called when VT switching away from the X server. Restore the * original text mode. */ _X_EXPORT void RADEONLeaveVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = NULL; + ScrnInfoPtr pScrn0 = NULL; RADEONSavePtr save = &info->ModeReg; RADEONTRACE(("RADEONLeaveVT\n")); + + if (pRADEONEnt->HasSecondary) { + if (info->IsSecondary) + pScrn0 = pRADEONEnt->pPrimaryScrn; + else + pScrn0 = pRADEONEnt->pSecondaryScrn; + info0 = RADEONPTR(pScrn0); + } + #ifdef XF86DRI if (RADEONPTR(pScrn)->directRenderingInited) { DRILock(pScrn->pScreen, 0); RADEONCP_STOP(pScrn, info); - - if (info->cardType == CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19 && info->FbSecureSize) - { - /* we need to backup the PCIE GART TABLE from fb memory */ - memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize); - } } #endif + RADEONSavePalette(pScrn, &info->ModeReg); + if (info0) { /* copy to other screen with the same saved palette */ + memcpy ((char*)info0->ModeReg.palette, + (char*)info->ModeReg.palette, + sizeof(info->ModeReg.palette)*2); + } + if (info->FBDev) { - RADEONSavePalette(pScrn, save); - info->PaletteSavedOnVT = TRUE; RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); fbdevHWLeaveVT(scrnIndex,flags); } RADEONRestore(pScrn); @@ -9038,17 +7118,22 @@ RADEONTRACE(("RADEONCloseScreen\n")); /* Mark acceleration as stopped or we might try to access the engine at * wrong times, especially if we had DRI, after DRI has been stopped */ info->accelOn = FALSE; #ifdef XF86DRI - RADEONDRIStop(pScreen); + /* Disable direct rendering */ + if (info->directRenderingEnabled) { + RADEONDRICloseScreen(pScreen); + info->directRenderingEnabled = FALSE; + info->directRenderingInited = FALSE; + } #endif #ifdef USE_XAA if(!info->useEXA && info->RenderTex) { xf86FreeOffscreenLinear(info->RenderTex); info->RenderTex = NULL; } #endif /* USE_XAA */ @@ -9077,16 +7162,17 @@ RADEONTRACE(("Disposing cusor info\n")); if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); info->cursor = NULL; RADEONTRACE(("Disposing DGA\n")); if (info->DGAModes) xfree(info->DGAModes); info->DGAModes = NULL; + RADEONTRACE(("Unmapping memory\n")); RADEONUnmapMem(pScrn); pScrn->vtSema = FALSE; xf86ClearPrimInitDone(info->pEnt->index); pScreen->BlockHandler = info->BlockHandler; @@ -9140,267 +7226,16 @@ #ifdef WITH_VGAHW if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); #endif RADEONFreeRec(pScrn); } -/* - * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). - * - * Note for current DAC mapping when calling this function: - * For most of cards: - * single CRT: Driver doesn't change the existing CRTC->DAC mapping, - * CRTC1 could be driving either DAC or both DACs. - * CRT+CRT: CRTC1->TV DAC, CRTC2->Primary DAC - * DFP/LCD+CRT: CRTC2->TV DAC, CRTC2->Primary DAC. - * Some boards have two DACs reversed or don't even have a primary DAC, - * this is reflected in pRADEONEnt->ReversedDAC. And radeon 7200 doesn't - * have a second DAC. - * It's kind of messy, we'll need to redo DAC mapping part some day. - */ -static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (IsPrimaryDAC) { - CARD32 dac_cntl; - CARD32 dac_macro_cntl = 0; - dac_cntl = INREG(RADEON_DAC_CNTL); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); - if (IsOn) { - dac_cntl &= ~RADEON_DAC_PDWN; - dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | - RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - } else { - dac_cntl |= RADEON_DAC_PDWN; - dac_macro_cntl |= (RADEON_DAC_PDWN_R | - RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - } - OUTREG(RADEON_DAC_CNTL, dac_cntl); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); - } else { - if (info->ChipFamily != CHIP_FAMILY_R200) { - CARD32 tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - if (IsOn) { - tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } else { - tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } - OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); - } else { - CARD32 fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); - if (IsOn) { - fp2_gen_cntl |= RADEON_FP2_DVO_EN; - } else { - fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; - } - OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); - } - } -} - -/* Sets VESA Display Power Management Signaling (DPMS) Mode */ -static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, - int flags) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (!pScrn->vtSema) return; - - RADEONTRACE(("RADEONDisplayPowerManagementSet(%d,0x%x)\n", PowerManagementMode, flags)); - -#ifdef XF86DRI - if (info->CPStarted) DRILock(pScrn->pScreen, 0); -#endif - - if (info->accelOn) - RADEON_SYNC(info, pScrn); - - if (info->FBDev) { - fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); - } else { - int mask1 = (RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_VSYNC_DIS); - int mask2 = (RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS); - - switch (PowerManagementMode) { - case DPMSModeOn: - /* Screen: On; HSync: On, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); - } - break; - - case DPMSModeStandby: - /* Screen: Off; HSync: Off, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeSuspend: - /* Screen: Off; HSync: On, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); - } - break; - } - - if (PowerManagementMode == DPMSModeOn) { - if (info->IsSecondary) { - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); - } - } else if (info->DisplayType == MT_CRT) { - RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC); - } - } else { - if ((info->MergedFB) && (info->MergeType == MT_DFP)) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); - } - } - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), - ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - } else if (info->DisplayType == MT_LCD) { - - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); - usleep (info->PanelPwrDly * 1000); - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); - } else if (info->DisplayType == MT_CRT) { - if ((pRADEONEnt->HasSecondary) || info->MergedFB) { - RADEONDacPowerSet(pScrn, TRUE, pRADEONEnt->ReversedDAC); - } else { - RADEONDacPowerSet(pScrn, TRUE, TRUE); - if (info->HasCRTC2) - RADEONDacPowerSet(pScrn, TRUE, FALSE); - } - } - } - } else if ((PowerManagementMode == DPMSModeOff) || - (PowerManagementMode == DPMSModeSuspend) || - (PowerManagementMode == DPMSModeStandby)) { - if (info->IsSecondary) { - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); - } - } else if (info->DisplayType == MT_CRT) { - RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC); - } - } else { - if ((info->MergedFB) && (info->MergeType == MT_DFP)) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); - } - } - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - } else if (info->DisplayType == MT_LCD) { - unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - - OUTREGP (RADEON_LVDS_GEN_CNTL, 0, - ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); - - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); - } - } else if (info->DisplayType == MT_CRT) { - if ((pRADEONEnt->HasSecondary) || info->MergedFB) { - RADEONDacPowerSet(pScrn, FALSE, pRADEONEnt->ReversedDAC); - } else { - /* single CRT, turning both DACs off, we don't really know - * which DAC is actually connected. - */ - RADEONDacPowerSet(pScrn, FALSE, TRUE); - if (info->HasCRTC2) /* don't apply this to old radeon (singel CRTC) card */ - RADEONDacPowerSet(pScrn, FALSE, FALSE); - } - } - } - } - } - -#ifdef XF86DRI - if (info->CPStarted) DRIUnlock(pScrn->pScreen); -#endif -} - static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); char *strptr; char *default_hsync = "28-33"; char *default_vrefresh = "43-72"; @@ -9425,17 +7260,17 @@ info->NonRect = info->HaveNonRect = info->HaveOffsRegions = FALSE; info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; info->MouseRestrictions = TRUE; if (info->MergeType == MT_NONE) { info->MergedFB = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to detect secondary monitor, MergedFB/Clone mode disabled\n"); - } else if (!pRADEONEnt->MonInfo2) { + } else if (!pRADEONEnt->Controller[1].pPort->MonInfo) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to detect secondary monitor DDC, default HSync and VRefresh used\n"); default_range = TRUE; } if (xf86GetOptValBool(info->Options, OPTION_MERGEDFB, &val)) { if (val) { info->MergedFB = TRUE; @@ -9591,17 +7426,17 @@ currentm->next = newm; newm->prev = currentm; } currentm = newm; tempm = tempm->next; } /* xf86SetDDCproperties(info->CRT2pScrn, pRADEONEnt->MonInfo2); */ - info->CRT2pScrn->monitor->DDC = pRADEONEnt->MonInfo2; + info->CRT2pScrn->monitor->DDC = pRADEONEnt->Controller[1].pPort->MonInfo; if (default_range) { RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, default_hsync, MAX_HSYNC); RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, default_vrefresh, MAX_VREFRESH); } if(info->CRT2HSync) { info->CRT2pScrn->monitor->nHsync = RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, info->CRT2HSync, MAX_HSYNC); } @@ -9980,8 +7815,2303 @@ pScrn->HandleMessage = RADEONHandleMessage; #endif pScrn->AdjustFrame = RADEONAdjustFrame; pScrn->EnterVT = RADEONEnterVT; pScrn->LeaveVT = RADEONLeaveVT; pScrn->FreeScreen = RADEONFreeScreen; pScrn->ValidMode = RADEONValidMode; } + +extern int getRADEONEntityIndex(void); + +const char *MonTypeName[7] = +{ + "AUTO", + "NONE", + "CRT", + "LVDS", + "TMDS", + "CTV", + "STV" +}; + +const RADEONMonitorType MonTypeID[7] = +{ + MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ + MT_NONE, /* NONE -> NONE */ + MT_CRT, /* CRT -> CRT */ + MT_LCD, /* Laptop LCDs are driven via LVDS port */ + MT_DFP, /* DFPs are driven via TMDS */ + MT_CTV, /* CTV -> CTV */ + MT_STV, /* STV -> STV */ +}; + +const char *TMDSTypeName[3] = +{ + "NONE", + "Internal", + "External" +}; + +const char *DDCTypeName[5] = +{ + "NONE", + "MONID", + "DVI_DDC", + "VGA_DDC", + "CRT2_DDC" +}; + +const char *DACTypeName[3] = +{ + "Unknown", + "Primary", + "TVDAC/ExtDAC", +}; + +const char *ConnectorTypeName[8] = +{ + "None", + "Proprietary", + "VGA", + "DVI-I", + "DVI-D", + "CTV", + "STV", + "Unsupported" +}; + +const char *ConnectorTypeNameATOM[10] = +{ + "None", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "STV", + "CTV", + "LVDS", + "Digital", + "Unsupported" +}; + +static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = +{ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ + {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ +}; + +static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = +{ + 0x00000000, /* unknown */ + 0x00000000, /* legacy */ + 0x00000000, /* r100 */ + 0x00280000, /* rv100 */ + 0x00000000, /* rs100 */ + 0x00880000, /* rv200 */ + 0x00000000, /* rs200 */ + 0x00000000, /* r200 */ + 0x00770000, /* rv250 */ + 0x00290000, /* rs300 */ + 0x00560000, /* rv280 */ + 0x00780000, /* r300 */ + 0x00770000, /* r350 */ + 0x00780000, /* rv350 */ + 0x00780000, /* rv380 */ + 0x01080000, /* r420 */ +}; + +static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + /* Get the result */ + val = INREG(info->DDCReg); + + *Clock = (val & RADEON_GPIO_Y_1) != 0; + *data = (val & RADEON_GPIO_Y_0) != 0; +} + +static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); + val |= (Clock ? 0:RADEON_GPIO_EN_1); + val |= (data ? 0:RADEON_GPIO_EN_0); + OUTREG(info->DDCReg, val); + + /* read back to improve reliability on some cards. */ + val = INREG(info->DDCReg); +} + +Bool RADEONI2cInit(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->pI2CBus = xf86CreateI2CBusRec(); + if (!info->pI2CBus) return FALSE; + + info->pI2CBus->BusName = "DDC"; + info->pI2CBus->scrnIndex = pScrn->scrnIndex; + info->pI2CBus->I2CPutBits = RADEONI2CPutBits; + info->pI2CBus->I2CGetBits = RADEONI2CGetBits; + info->pI2CBus->AcknTimeout = 5; + + if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; + return TRUE; +} + +void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) +{ + MonPtr mon = pScrn->monitor; + xf86MonPtr ddc = mon->DDC; + int i; + + if (flag) { /* HSync */ + for (i = 0; i < 4; i++) { + if (ddc->det_mon[i].type == DS_RANGES) { + mon->nHsync = 1; + mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; + mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; + return; + } + } + /* If no sync ranges detected in detailed timing table, let's + * try to derive them from supported VESA modes. Are we doing + * too much here!!!? */ + i = 0; + if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ + mon->hsync[i].lo = mon->hsync[i].hi = 35.2; + i++; + } + if (ddc->timings1.t1 & 0x04) { /* 640x480@75 */ + mon->hsync[i].lo = mon->hsync[i].hi = 37.5; + i++; + } + if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) { + mon->hsync[i].lo = mon->hsync[i].hi = 37.9; + i++; + } + if (ddc->timings1.t2 & 0x40) { + mon->hsync[i].lo = mon->hsync[i].hi = 46.9; + i++; + } + if ((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) { + mon->hsync[i].lo = mon->hsync[i].hi = 48.1; + i++; + } + if (ddc->timings1.t2 & 0x04) { + mon->hsync[i].lo = mon->hsync[i].hi = 56.5; + i++; + } + if (ddc->timings1.t2 & 0x02) { + mon->hsync[i].lo = mon->hsync[i].hi = 60.0; + i++; + } + if (ddc->timings1.t2 & 0x01) { + mon->hsync[i].lo = mon->hsync[i].hi = 64.0; + i++; + } + mon->nHsync = i; + } else { /* Vrefresh */ + for (i = 0; i < 4; i++) { + if (ddc->det_mon[i].type == DS_RANGES) { + mon->nVrefresh = 1; + mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; + mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; + return; + } + } + + i = 0; + if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 56; + i++; + } + if ((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 60; + i++; + } + if (ddc->timings1.t2 & 0x04) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 70; + i++; + } + if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 72; + i++; + } + if ((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) || + (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 75; + i++; + } + mon->nVrefresh = i; + } +} + +static RADEONMonitorType +RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsPrimaryDac) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int bConnected = 0; + + /* the monitor either wasn't connected or it is a non-DDC monitor. + we need to try to detect connectedness another way.... + */ + if(IsPrimaryDac) + { + unsigned long ulOrigVCLK_ECP_CNTL; + unsigned long ulOrigDAC_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulOrigCRTC_EXT_CNTL; + unsigned long ulOrigDAC_CNTL2; + unsigned long ulData; + unsigned long ulMask; + + ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); + OUTREG(RADEON_DAC_CNTL2, 2); + + ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + + ulData = ulOrigVCLK_ECP_CNTL; + ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb + | RADEON_PIXCLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb + |RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); + ulData = ulOrigCRTC_EXT_CNTL; + ulData |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, ulData); + + ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); + ulData = ulOrigDAC_EXT_CNTL; + ulData &= ~RADEON_DAC_FORCE_DATA_MASK; + ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN + |RADEON_DAC_FORCE_DATA_EN + |RADEON_DAC_FORCE_DATA_SEL_MASK); + if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) + ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, ulData); + + ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); + ulData = ulOrigDAC_CNTL; + ulData |= RADEON_DAC_CMP_EN; + ulData &= ~(RADEON_DAC_RANGE_CNTL_MASK + | RADEON_DAC_PDWN); + ulData |= 0x2; + OUTREG(RADEON_DAC_CNTL, ulData); + + usleep(1000); + + ulData = INREG(RADEON_DAC_CNTL); + bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; + + ulData = ulOrigVCLK_ECP_CNTL; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); + OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); + OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); + OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); + } + else + { + if (info->ChipFamily == CHIP_FAMILY_R200) + { +#if 0 + unsigned long ulOrigGPIO_MONID; + unsigned long ulOrigFP2_GEN_CNTL; + unsigned long ulOrigDISP_OUTPUT_CNTL; + unsigned long ulOrigCRTC2_GEN_CNTL; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; + unsigned long ulOrigCRTC2_H_TOTAL_DISP; + unsigned long ulOrigCRTC2_V_TOTAL_DISP; + unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; + unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; + unsigned long ulData, i; +#endif + +/* This doesn't work on some cards, we always return false + for now, If one wants to connected a non-DDC monitor on + the DVI port, he has to specify it explicitly in + the config file with Option MonitorLayout. +*/ + return MT_NONE; /* **** code ends here ***** */ + +#if 0 + ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); + ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); + ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); + ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); + ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + + ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); + ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); + ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + ulData = INREG(RADEON_GPIO_MONID); + ulData &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, ulData); + + OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); + + OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) + { + ulData = INREG(RADEON_GPIO_MONID); + bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; + if (!bConnected) break; + + usleep(1000); + } + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); + OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); + OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); +#endif + } + else + { + unsigned long ulOrigPIXCLKSDATA; + unsigned long ulOrigTV_MASTER_CNTL; + unsigned long ulOrigTV_DAC_CNTL; + unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; + unsigned long ulOrigDAC_CNTL2; + unsigned long ulOrigCRTC2_GEN_CNTL; + unsigned long ulOrigDISP_OUTPUT_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulData; + unsigned long ulMask; + int i; + + ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + + ulData = ulOrigPIXCLKSDATA; + ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); + ulData = ulOrigTV_MASTER_CNTL; + ulData &= ~RADEON_TVCLK_ALWAYS_ONb; + OUTREG(RADEON_TV_MASTER_CNTL, ulData); + + ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); + ulData = ulOrigDAC_CNTL2; + ulData |= RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, ulData); + + ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); + ulData = ulOrigDISP_OUTPUT_CNTL & ~0xc; + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulData); + + ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); + ulData = ulOrigCRTC2_GEN_CNTL | RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, ulData); + + ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + ulData = (RADEON_Y_RED_EN + | RADEON_C_GRN_EN + | RADEON_CMP_BLU_EN + | RADEON_RED_MX_FORCE_DAC_DATA + | RADEON_GRN_MX_FORCE_DAC_DATA + | RADEON_BLU_MX_FORCE_DAC_DATA); + if (IS_R300_VARIANT) + ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + else + ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); + + ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); + + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + usleep(50000); + + ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); + ulData = ulOrigDAC_EXT_CNTL; + ulData &= ~RADEON_DAC_FORCE_DATA_MASK; + ulData |= (3 | RADEON_DAC_FORCE_DATA_SEL_MASK); + if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) + ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); + OUTREG(RADEON_DAC_EXT_CNTL, ulData); + + usleep(1000); + + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT) ? 1:0; +#if 1 + for (i = 0; i < 4; i++) { + ulData = 0x00880203; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + while(INREG(RADEON_TV_DAC_CNTL) & (1<<5)); + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + usleep(5000); + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT) ? 1:0; + if (!bConnected) break; + } +#endif + ulData = ulOrigPIXCLKSDATA; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); + OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); + OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL); + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); + OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); + } + } + + return (bConnected ? MT_CRT : MT_NONE); +} + + +static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, RADEONConnector* port) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long DDCReg; + RADEONMonitorType MonType = MT_NONE; + xf86MonPtr* MonInfo = &port->MonInfo; + int i, j; + + DDCReg = info->DDCReg; + switch(DDCType) + { + case DDC_MONID: + info->DDCReg = RADEON_GPIO_MONID; + break; + case DDC_DVI: + info->DDCReg = RADEON_GPIO_DVI_DDC; + break; + case DDC_VGA: + info->DDCReg = RADEON_GPIO_VGA_DDC; + break; + case DDC_CRT2: + if ((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) return MT_NONE; + info->DDCReg = RADEON_GPIO_CRT2_DDC; + break; + default: + info->DDCReg = DDCReg; + return MT_NONE; + } + + /* Read and output monitor info using DDC2 over I2C bus */ + if (info->pI2CBus && info->ddc2) { + OUTREG(info->DDCReg, INREG(info->DDCReg) & + (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); + + /* For some old monitors (like Compaq Presario FP500), we need + * following process to initialize/stop DDC + */ + OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); + for (j = 0; j < 3; j++) { + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(13000); + + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 10; i++) { + usleep(15000); + if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) + break; + } + if (i == 3) continue; + + usleep(15000); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); + usleep(15000); + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 5; i++) { + usleep(15000); + if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) + break; + } + usleep(15000); + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + if(*MonInfo) break; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); + MonType = MT_NONE; + } + + OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); + + if (*MonInfo) { + if ((*MonInfo)->rawData[0x14] & 0x80) { + if (port->TMDSType == TMDS_EXT) MonType = MT_DFP; + else { + if ((INREG(RADEON_FP_GEN_CNTL) & (1<<7)) || !info->IsMobility) MonType = MT_DFP; + else MonType = MT_LCD; + } + } else MonType = MT_CRT; + } else MonType = MT_NONE; + + info->DDCReg = DDCReg; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DDC Type: %d, Detected Type: %d\n", DDCType, MonType); + + return MonType; +} + +static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); + CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); + + info->PanelPwrDly = 200; + if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { + info->PanelYRes = (fp_vert_stretch>>12) + 1; + } else { + info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; + } + if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { + info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; + } else { + info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; + } + + if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { + info->PanelXRes = 640; + info->PanelYRes = 480; + } + + if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { + CARD32 ppll_div_sel, ppll_val; + + ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; + RADEONPllErrataAfterIndex(info); + ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); + if ((ppll_val & 0x000707ff) == 0x1bb) + goto noprobe; + info->FeedbackDivider = ppll_val & 0x7ff; + info->PostDivider = (ppll_val >> 16) & 0x7; + info->RefDivider = info->pll.reference_div; + info->UseBiosDividers = TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Existing panel PLL dividers will be used.\n"); + } + noprobe: + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Panel size %dx%d is derived, this may not be correct.\n" + "If not, use PanelSize option to overwrite this setting\n", + info->PanelXRes, info->PanelYRes); +} + +/* BIOS may not have right panel size, we search through all supported + * DDC modes looking for the maximum panel size. + */ +static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) +{ + int j; + RADEONInfoPtr info = RADEONPTR (pScrn); + xf86MonPtr ddc = pScrn->monitor->DDC; + DisplayModePtr p; + + if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) + return; + + /* Go thru detailed timing table first */ + for (j = 0; j < 4; j++) { + if (ddc->det_mon[j].type == 0) { + struct detailed_timings *d_timings = + &ddc->det_mon[j].section.d_timings; + int match = 0; + + /* If we didn't get a panel clock or guessed one, try to match the + * mode with the panel size. We do that because we _need_ a panel + * clock, or ValidateFPModes will fail, even when UseBiosDividers + * is set. + */ + if (info->DotClock == 0 && + info->PanelXRes == d_timings->h_active && + info->PanelYRes == d_timings->v_active) + match = 1; + + /* If we don't have a BIOS provided panel data with fixed dividers, + * check for a larger panel size + */ + if (info->PanelXRes < d_timings->h_active && + info->PanelYRes < d_timings->v_active && + !info->UseBiosDividers) + match = 1; + + if (match) { + info->PanelXRes = d_timings->h_active; + info->PanelYRes = d_timings->v_active; + info->DotClock = d_timings->clock / 1000; + info->HOverPlus = d_timings->h_sync_off; + info->HSyncWidth = d_timings->h_sync_width; + info->HBlank = d_timings->h_blanking; + info->VOverPlus = d_timings->v_sync_off; + info->VSyncWidth = d_timings->v_sync_width; + info->VBlank = d_timings->v_blanking; + info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); + if (d_timings->sync == 3) { + switch (d_timings->misc) { + case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; + case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; + case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; + case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", + info->PanelXRes, info->PanelYRes); + } + } + } + + if (info->UseBiosDividers && info->DotClock != 0) + return; + + /* Search thru standard VESA modes from EDID */ + for (j = 0; j < 8; j++) { + if ((info->PanelXRes < ddc->timings2[j].hsize) && + (info->PanelYRes < ddc->timings2[j].vsize)) { + for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + if ((ddc->timings2[j].hsize == p->HDisplay) && + (ddc->timings2[j].vsize == p->VDisplay)) { + float refresh = + (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; + + if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { + /* Is this good enough? */ + info->PanelXRes = ddc->timings2[j].hsize; + info->PanelYRes = ddc->timings2[j].vsize; + info->HBlank = p->HTotal - p->HDisplay; + info->HOverPlus = p->HSyncStart - p->HDisplay; + info->HSyncWidth = p->HSyncEnd - p->HSyncStart; + info->VBlank = p->VTotal - p->VDisplay; + info->VOverPlus = p->VSyncStart - p->VDisplay; + info->VSyncWidth = p->VSyncEnd - p->VSyncStart; + info->DotClock = p->Clock; + info->Flags = p->Flags; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", + info->PanelXRes, info->PanelYRes); + } + } + } + } + } +} + +static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (!RADEONGetLVDSInfoFromBIOS(pScrn)) + RADEONGetPanelInfoFromReg(pScrn); + /* The panel size we collected from BIOS may not be the + * maximum size supported by the panel. If not, we update + * it now. These will be used if no matching mode can be + * found from EDID data. + */ + RADEONUpdatePanelSize(pScrn); + + if (info->DotClock == 0) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + DisplayModePtr tmp_mode = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No valid timing info from BIOS.\n"); + /* No timing information for the native mode, + use whatever specified in the Modeline. + If no Modeline specified, we'll just pick + the VESA mode at 60Hz refresh rate which + is likely to be the best for a flat panel. + */ + tmp_mode = pScrn->monitor->Modes; + while(tmp_mode) { + if ((tmp_mode->HDisplay == info->PanelXRes) && + (tmp_mode->VDisplay == info->PanelYRes)) { + + float refresh = + (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; + if ((abs(60.0 - refresh) < 1.0) || + (tmp_mode->type == 0)) { + info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + info->DotClock = tmp_mode->Clock; + info->Flags = 0; + break; + } + tmp_mode = tmp_mode->next; + } + } + if ((info->DotClock == 0) && !pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Panel size is not correctly detected.\n" + "Please try to use PanelSize option for correct settings.\n"); + return FALSE; + } + } + + return TRUE; +} + +static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int i; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = 0; + info->tmds_pll[i].freq = 0; + } + + if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; + info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; + } +} + +void RADEONGetPanelInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + char* s; + + if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { + info->PanelPwrDly = 200; + if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); + RADEONGetPanelInfoFromReg(pScrn); + } + } else { + + if(info->DisplayType == MT_LCD) { + RADEONGetLVDSInfo(pScrn); + } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { + RADEONGetTMDSInfo(pScrn); + if (!pScrn->monitor->DDC) + RADEONGetHardCodedEDIDFromBIOS(pScrn); + else if (!info->IsSecondary) + RADEONUpdatePanelSize(pScrn); + } + } +} + +void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + /* Todo: get this setting from BIOS */ + info->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; + if (info->IsMobility) { /* some mobility chips may different */ + if (info->ChipFamily == CHIP_FAMILY_RV250) + info->tv_dac_adj = 0x00880000; + } +} + +static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + const char *s; + Bool ignore_edid = FALSE; + int i = 0, second = 0, max_mt = 5; + + /* We first get the information about all connectors from BIOS. + * This is how the card is phyiscally wired up. + * The information should be correct even on a OEM card. + * If not, we may have problem -- need to use MonitorLayout option. + */ + for (i = 0; i < 2; i++) + { + pRADEONEnt->PortInfo[i].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[i].MonInfo = NULL; + pRADEONEnt->PortInfo[i].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[i].DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[i].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[i].ConnectorType = CONNECTOR_NONE; + } + pRADEONEnt->Controller[0].IsUsed = FALSE; + pRADEONEnt->Controller[1].IsUsed = FALSE; + pRADEONEnt->Controller[0].IsActive = FALSE; + pRADEONEnt->Controller[1].IsActive = FALSE; + + if (!RADEONGetConnectorInfoFromBIOS(pScrn)) { + /* Below is the most common setting, but may not be true */ + pRADEONEnt->PortInfo[0].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[0].MonInfo = NULL; + pRADEONEnt->PortInfo[0].DDCType = DDC_DVI; + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; + pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_DVI_I; + + pRADEONEnt->PortInfo[1].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; + } + + /* always make TMDS_INT port first*/ + if (pRADEONEnt->PortInfo[1].TMDSType == TMDS_INT) { + RADEONConnector connector; + connector = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = connector; + } else if ((pRADEONEnt->PortInfo[0].TMDSType != TMDS_INT && + pRADEONEnt->PortInfo[1].TMDSType != TMDS_INT)) { + /* no TMDS_INT port, make primary DAC port first */ + if (pRADEONEnt->PortInfo[1].DACType == DAC_PRIMARY) { + RADEONConnector connector; + connector = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = connector; + } + } + + if (info->HasSingleDAC) { + /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ + if (pRADEONEnt->PortInfo[0].ConnectorType == CONNECTOR_CRT) { + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + } else { + pRADEONEnt->PortInfo[1].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; + } + } else if (!info->HasCRTC2) { + pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; + } + + /* IgnoreEDID option is different from the NoDDCxx options used by DDC module + * When IgnoreEDID is used, monitor detection will still use DDC + * detection, but all EDID data will not be used in mode validation. + * You can use this option when you have a DDC monitor but want specify your own + * monitor timing parameters by using HSync, VRefresh and Modeline, + */ + if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { + if (ignore_edid) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "IgnoreEDID is specified, EDID data will be ignored\n"); + } + + /* + * MonitorLayout option takes a string for two monitors connected in following format: + * Option "MonitorLayout" "primary-port-display, secondary-port-display" + * primary and secondary port displays can have one of following: + * NONE, CRT, LVDS, TMDS + * With this option, driver will bring up monitors as specified, + * not using auto-detection routines to probe monitors. + * + * This option can be used when the false monitor detection occurs. + * + * This option can also be used to disable one connected display. + * For example, if you have a laptop connected to an external CRT + * and you want to disable the internal LCD panel, you can specify + * Option "MonitorLayout" "NONE, CRT" + * + * This option can also used to disable Clone mode. One there is only + * one monitor is specified, clone mode will be turned off automatically + * even you have two monitors connected. + * + * Another usage of this option is you want to config the server + * to start up with a certain monitor arrangement even one monitor + * is not plugged in when server starts. + * For example, you can config your laptop with + * Option "MonitorLayout" "LVDS, CRT" + * Option "CloneHSync" "40-150" + * Option "CloneVRefresh" "60-120" + * With these options, you can connect in your CRT monitor later + * after the X server has started. + */ + if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { + char s1[5], s2[5]; + i = 0; + /* When using user specified monitor types, we will not do DDC detection + * + */ + do { + switch(*s) { + case ',': + s1[i] = '\0'; + i = 0; + second = 1; + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + if (second) + s2[i] = *s; + else + s1[i] = *s; + i++; + break; + } + if (i > 4) i = 4; + } while(*s++); + s2[i] = '\0'; + + for (i = 0; i < max_mt; i++) + { + if (strcmp(s1, MonTypeName[i]) == 0) + { + pRADEONEnt->PortInfo[0].MonType = MonTypeID[i]; + break; + } + } + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 1st port \n"); + + for (i = 0; i < max_mt; i++) + { + if (strcmp(s2, MonTypeName[i]) == 0) + { + pRADEONEnt->PortInfo[1].MonType = MonTypeID[i]; + break; + } + + } + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 2nd port \n"); + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2); + + if (pRADEONEnt->PortInfo[1].MonType == MT_CRT) { + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[0].ConnectorType = pRADEONEnt->PortInfo[0].MonType+1; + pRADEONEnt->PortInfo[0].MonInfo = NULL; + } + + /* some thinkpads and powerbooks use lvds and internal tmds + * at the same time. --AGD + */ + if ((pRADEONEnt->PortInfo[0].MonType == MT_LCD) && + (pRADEONEnt->PortInfo[1].MonType == MT_DFP)) { + pRADEONEnt->PortInfo[1].DDCType = DDC_DVI; + pRADEONEnt->PortInfo[0].DDCType = DDC_MONID; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_INT; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_DVI_I; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; + } + + if (!ignore_edid) { + if ((pRADEONEnt->PortInfo[0].MonType > MT_NONE) && + (pRADEONEnt->PortInfo[0].MonType < MT_STV)) + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, + &pRADEONEnt->PortInfo[0]); + if ((pRADEONEnt->PortInfo[1].MonType > MT_NONE) && + (pRADEONEnt->PortInfo[1].MonType < MT_STV)) + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, + &pRADEONEnt->PortInfo[1]); + } + + } + + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + + if((!info->HasCRTC2) && (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN)) { + if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, + &pRADEONEnt->PortInfo[0]))); + else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, + &pRADEONEnt->PortInfo[0]))); + else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, + &pRADEONEnt->PortInfo[0]))); + else + pRADEONEnt->PortInfo[0].MonType = MT_CRT; + + if (!ignore_edid) { + if (pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); + xf86PrintEDID( pRADEONEnt->PortInfo[0].MonInfo ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); + } + } + + pRADEONEnt->PortInfo[1].MonType = MT_NONE; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + pRADEONEnt->PortInfo[1].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[1].DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_NONE; + + pRADEONEnt->Controller[0].pPort = &pRADEONEnt->PortInfo[0]; + pRADEONEnt->Controller[1].pPort = &pRADEONEnt->PortInfo[1]; + return; + } + + /* Primary Head (DVI or Laptop Int. panel)*/ + /* A ddc capable display connected on DVI port */ + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, + pRADEONEnt->PortInfo[0].DDCType, + &pRADEONEnt->PortInfo[0]))); + else if (info->IsMobility && + (INREG(RADEON_BIOS_4_SCRATCH) & 4)) { + /* non-DDC laptop panel connected on primary */ + pRADEONEnt->PortInfo[0].MonType = MT_LCD; + } else { + /* CRT on DVI, TODO: not reliable, make it always return false for now*/ + pRADEONEnt->PortInfo[0].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[0].DACType)); + } + } + + /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ + if (pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[1].MonType = + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, + &pRADEONEnt->PortInfo[1]))); + else if (info->IsMobility && + (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON)) { + /* non-DDC TMDS panel connected through DVO */ + pRADEONEnt->PortInfo[1].MonType = MT_DFP; + } else + pRADEONEnt->PortInfo[1].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[1].DACType)); + } + } + + if(ignore_edid) { + pRADEONEnt->PortInfo[0].MonInfo = NULL; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + } else { + if (pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on 1st port ----------------------\n"); + xf86PrintEDID( pRADEONEnt->PortInfo[0].MonInfo ); + } + + if (pRADEONEnt->PortInfo[1].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on 2nd port -----------------------\n"); + xf86PrintEDID( pRADEONEnt->PortInfo[1].MonInfo ); + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); + +} + +Bool RADEONMapControllers(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + Bool head_reversed = FALSE; + + info->MergeType = MT_NONE; + + if (!info->IsSecondary) { + RADEONQueryConnectedDisplays(pScrn); + + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[0]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[1]); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Port1:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->Controller[0].pPort->MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->Controller[0].pPort->ConnectorType]: + ConnectorTypeName[pRADEONEnt->Controller[0].pPort->ConnectorType], + DACTypeName[pRADEONEnt->Controller[0].pPort->DACType+1], + TMDSTypeName[pRADEONEnt->Controller[0].pPort->TMDSType+1], + DDCTypeName[pRADEONEnt->Controller[0].pPort->DDCType]); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Port2:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->Controller[1].pPort->MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->Controller[1].pPort->ConnectorType]: + ConnectorTypeName[pRADEONEnt->Controller[1].pPort->ConnectorType], + DACTypeName[pRADEONEnt->Controller[1].pPort->DACType+1], + TMDSTypeName[pRADEONEnt->Controller[1].pPort->TMDSType+1], + DDCTypeName[pRADEONEnt->Controller[1].pPort->DDCType]); + + /* no display detected on primary port*/ + if (pRADEONEnt->Controller[0].pPort->MonType == MT_NONE) { + if (pRADEONEnt->Controller[1].pPort->MonType != MT_NONE) { + /* Only one detected on secondary, let it to be primary */ + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[1]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[0]); + head_reversed = TRUE; + } else { + /* None detected, Default to a CRT connected */ + pRADEONEnt->Controller[0].pPort->MonType = MT_CRT; + } + } + + if ((pRADEONEnt->Controller[0].pPort->MonType == MT_LCD) && + (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT)) { + if (!(INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON)) { + /* LCD is switched off, don't turn it on, otherwise it may casue lockup due to SS issue. */ + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[1]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[0]); + pRADEONEnt->Controller[1].pPort->MonType = MT_NONE; + head_reversed = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "LCD is switched off, only CRT will be used\n"); + } + } + + if ((pRADEONEnt->Controller[0].pPort->MonType != MT_NONE) && + (pRADEONEnt->Controller[1].pPort->MonType != MT_NONE)) { + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DISPLAY, FALSE)) { + if (info->IsMobility) { + /* Don't reverse display for mobility chips, as only CRTC1 path has RMX which + will be required by many LCD panels + */ + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Reverse Display cannot be used for mobility chip\n"); + } else { + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[1]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[0]); + head_reversed = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Primary and Secondary mapping is reversed\n"); + } + } + } + + if (pRADEONEnt->HasSecondary && pRADEONEnt->Controller[1].pPort->MonType == MT_NONE) { + pRADEONEnt->HasSecondary = FALSE; + } + } + + if(info->HasCRTC2) { + if(info->IsSecondary) { + info->DisplayType = pRADEONEnt->Controller[1].pPort->MonType; + pScrn->monitor->DDC = pRADEONEnt->Controller[1].pPort->MonInfo; + } else { + info->DisplayType = pRADEONEnt->Controller[0].pPort->MonType; + pScrn->monitor->DDC = pRADEONEnt->Controller[0].pPort->MonInfo; + } + + if(!pRADEONEnt->HasSecondary) { + info->MergeType = pRADEONEnt->Controller[1].pPort->MonType; + } + } else { + if (pRADEONEnt->Controller[0].pPort->MonType == MT_NONE) + pRADEONEnt->Controller[0].pPort->MonType = MT_CRT; + info->DisplayType = pRADEONEnt->Controller[0].pPort->MonType; + pScrn->monitor->DDC = pRADEONEnt->Controller[0].pPort->MonInfo; + pRADEONEnt->Controller[1].pPort->MonType = MT_NONE; + } + + if (!info->IsSecondary) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Primary Head: Port%d ---- \n", head_reversed?2:1); + if (pRADEONEnt->Controller[1].pPort->MonType != MT_NONE) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Port%d ----\n", head_reversed?1:2); + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Not used ----\n"); + } + + info->HBlank = 0; + info->HOverPlus = 0; + info->HSyncWidth = 0; + info->VBlank = 0; + info->VOverPlus = 0; + info->VSyncWidth = 0; + info->DotClock = 0; + info->UseBiosDividers = FALSE; + + info->OverlayOnCRTC2 = FALSE; + + return TRUE; +} + +/* + * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). + * + */ +static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (IsPrimaryDAC) { + CARD32 dac_cntl; + CARD32 dac_macro_cntl = 0; + + dac_cntl = INREG(RADEON_DAC_CNTL); + if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + if (IsOn) { + dac_cntl &= ~RADEON_DAC_PDWN; + dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + } else { + dac_cntl |= RADEON_DAC_PDWN; + dac_macro_cntl |= (RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + } + OUTREG(RADEON_DAC_CNTL, dac_cntl); + if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + } else { + CARD32 tv_dac_cntl; + CARD32 fp2_gen_cntl; + + switch(info->ChipFamily) + { + case CHIP_FAMILY_R420: + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + if (IsOn) { + tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } else { + tv_dac_cntl |= (R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + break; + + case CHIP_FAMILY_R200: + fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); + if (IsOn) { + fp2_gen_cntl |= RADEON_FP2_DVO_EN; + } else { + fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; + } + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + break; + + default: + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + if (IsOn) { + tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } else { + tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + break; + } + } +} + +/* This is to be used enable/disable displays dynamically */ +void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONController* pCRTC, BOOL bEnable) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSavePtr save = &info->ModeReg; + unsigned char * RADEONMMIO = info->MMIO; + unsigned long tmp; + + if (bEnable) { + if (pCRTC->pPort->MonType == MT_CRT) { + if (pCRTC->pPort->DACType == DAC_PRIMARY) { + tmp = INREG(RADEON_CRTC_EXT_CNTL); + tmp |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; + } else if (pCRTC->pPort->DACType == DAC_TVDAC) { + if (info->ChipFamily == CHIP_FAMILY_R200) { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp |= RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + } else { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } + } + RADEONDacPowerSet(pScrn, bEnable, (pCRTC->pPort->DACType == DAC_PRIMARY)); + } else if (pCRTC->pPort->MonType == MT_DFP) { + if (pCRTC->pPort->TMDSType == TMDS_INT) { + tmp = INREG(RADEON_FP_GEN_CNTL); + tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + OUTREG(RADEON_FP_GEN_CNTL, tmp); + save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } else if (pCRTC->pPort->TMDSType == TMDS_EXT) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } + } else if (pCRTC->pPort->MonType == MT_LCD) { + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); + tmp &= ~(RADEON_LVDS_DISPLAY_DIS); + usleep (info->PanelPwrDly * 1000); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); + save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); + } + } else { + if (pCRTC->pPort->MonType == MT_CRT || pCRTC->pPort->MonType == NONE) { + if (pCRTC->pPort->DACType == DAC_PRIMARY) { + tmp = INREG(RADEON_CRTC_EXT_CNTL); + tmp &= ~RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; + } else if (pCRTC->pPort->DACType == DAC_TVDAC) { + if (info->ChipFamily == CHIP_FAMILY_R200) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } else { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp &= ~RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; + } + } + RADEONDacPowerSet(pScrn, bEnable, (pCRTC->pPort->DACType == DAC_PRIMARY)); + } + + if (pCRTC->pPort->MonType == MT_DFP || pCRTC->pPort->MonType == NONE) { + if (pCRTC->pPort->TMDSType == TMDS_INT) { + tmp = INREG(RADEON_FP_GEN_CNTL); + tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + OUTREG(RADEON_FP_GEN_CNTL, tmp); + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } else if (pCRTC->pPort->TMDSType == TMDS_EXT) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } + } + + if (pCRTC->pPort->MonType == MT_LCD || + (pCRTC->pPort->MonType == NONE && pCRTC->pPort->ConnectorType == CONNECTOR_PROPRIETARY)) { + unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); + tmp &= ~(RADEON_LVDS_BLON); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); + save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON); + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + } + } + pCRTC->IsActive = bEnable; +} + +/* Calculate display buffer watermark to prevent buffer underflow */ +void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONInfoPtr info2 = NULL; + + DisplayModePtr mode1, mode2; + + CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; + float mem_tcas; + int k1, c; + CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; + float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; + + float mem_bw, peak_disp_bw; + float min_mem_eff = 0.8; + float sclk_eff, sclk_delay; + float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; + float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; + float pix_clk, pix_clk2; /* in MHz */ + int cur_size = 16; /* in octawords */ + int critical_point, critical_point2; + int stop_req, max_stop_req; + float read_return_rate, time_disp1_drop_priority; + + /* + * Set display0/1 priority up on r3/4xx in the memory controller for + * high res modes if the user specifies HIGH for displaypriority + * option. + */ + if ((info->DispPriority == 2) && IS_R300_VARIANT) { + CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); + if (info->MergedFB || pRADEONEnt->HasSecondary) { + mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ + } else { + mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ + } + OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); + } + + + /* R420 and RV410 family not supported yet */ + if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; + + if (pRADEONEnt->pSecondaryScrn) { + if (info->IsSecondary) return; + info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); + } else if (info->MergedFB) info2 = info; + + /* + * Determine if there is enough bandwidth for current display mode + */ + mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); + + mode1 = info->CurrentLayout.mode; + if (info->MergedFB) { + mode1 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; + mode2 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; + } else if ((pRADEONEnt->HasSecondary) && info2) { + mode2 = info2->CurrentLayout.mode; + } else { + mode2 = NULL; + } + + pix_clk = mode1->Clock/1000.0; + if (mode2) + pix_clk2 = mode2->Clock/1000.0; + else + pix_clk2 = 0; + + peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); + if (info2) + peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); + + if (peak_disp_bw >= mem_bw * min_mem_eff) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "You may not have enough display bandwidth for current mode\n" + "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); + } + + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; + + /* setup Max GRPH_STOP_REQ default value */ + if (IS_RV100_VARIANT) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* Get values from the EXT_MEM_CNTL register...converting its contents. */ + temp = INREG(RADEON_MEM_TIMING_CNTL); + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; + mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; + mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; + } else { /* RV200 and later */ + mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; + mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; + mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; + } + + /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ + temp = INREG(RADEON_MEM_SDRAM_MODE_REG); + data = (temp & (7<<20)) >> 20; + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_tcas = MemTcas [data]; + } else { + mem_tcas = MemTcas2 [data]; + } + + if (IS_R300_VARIANT) { + + /* on the R300, Tcas is included in Trbs. + */ + temp = INREG(RADEON_MEM_CNTL); + data = (R300_MEM_NUM_CHANNELS_MASK & temp); + if (data == 1) { + if (R300_MEM_USE_CD_CH_ONLY & temp) { + temp = INREG(R300_MC_IND_INDEX); + temp &= ~R300_MC_IND_ADDR_MASK; + temp |= R300_MC_READ_CNTL_CD_mcind; + OUTREG(R300_MC_IND_INDEX, temp); + temp = INREG(R300_MC_IND_DATA); + data = (R300_MEM_RBS_POSITION_C_MASK & temp); + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + + mem_trbs = MemTrbs[data]; + mem_tcas += mem_trbs; + } + + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + /* DDR64 SCLK_EFF = SCLK for analysis */ + sclk_eff = info->sclk; + } else { +#ifdef XF86DRI + if (info->directRenderingEnabled) + sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); + else +#endif + sclk_eff = info->sclk; + } + + /* Find the memory controller latency for the display client. + */ + if (IS_R300_VARIANT) { + /*not enough for R350 ???*/ + /* + if (!mode2) sclk_delay = 150; + else { + if (info->RamWidth == 256) sclk_delay = 87; + else sclk_delay = 97; + } + */ + sclk_delay = 250; + } else { + if ((info->ChipFamily == CHIP_FAMILY_RV100) || + info->IsIGP) { + if (info->IsDDR) sclk_delay = 41; + else sclk_delay = 33; + } else { + if (info->RamWidth == 128) sclk_delay = 57; + else sclk_delay = 41; + } + } + + mc_latency_sclk = sclk_delay / sclk_eff; + + if (info->IsDDR) { + if (info->RamWidth == 32) { + k1 = 40; + c = 3; + } else { + k1 = 20; + c = 1; + } + } else { + k1 = 40; + c = 3; + } + mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / + info->mclk) + (4.0 / sclk_eff); + + /* + HW cursor time assuming worst case of full size colour cursor. + */ + cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; + cur_latency_sclk = cur_size / sclk_eff; + + /* + Find the total latency for the display data. + */ + disp_latency_overhead = 8.0 / info->sclk; + mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; + mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; + disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); + + /* + Find the drain rate of the display buffer. + */ + disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); + if (info2) + disp_drain_rate2 = pix_clk2 / (16.0/info2->CurrentLayout.pixel_bytes); + else + disp_drain_rate2 = 0; + + /* + Find the critical point of the display buffer. + */ + critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); + + /* ???? */ + /* + temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; + if (critical_point < temp) critical_point = temp; + */ + if (info->DispPriority == 2) { + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) critical_point = 0; + + if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + critical_point = 0x10; + } + + temp = info->SavedReg.grph_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", + info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); + + if (mode2) { + stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; + + if (stop_req > max_stop_req) stop_req = max_stop_req; + + temp = info->SavedReg.grph2_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) + critical_point2 = 0; + else { + read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); + time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); + + critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + + disp_latency) * disp_drain_rate2 + 0.5); + + if (info->DispPriority == 2) { + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) critical_point2 = 0; + + } + + if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0 */ + critical_point2 = 0x10; + } + + OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", + info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); + } +} + +/* Blank screen. */ +void RADEONBlank (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); +#if 0 + static int ScreenCount = 0; + ScreenCount++; + + if (ScreenCount == 2) { + ScreenCount = 0; + return; + } +#endif + + if (!pRADEONEnt->HasSecondary || + (pRADEONEnt->HasSecondary && !info->IsSwitching) || + (info->IsSwitching && (!info->IsSecondary))) { + +/* if (!pRADEONEnt->HasSecondary || info->IsSwitching) ScreenCount = 0;*/ + + switch (pRADEONEnt->Controller[0].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, + ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[0].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + + break; + case MT_DFP: + if (pRADEONEnt->Controller[0].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); + + break; + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC_EXT_CNTL, + RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS, + ~(RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS)); + + if (!info->HasCRTC2) return; + + if (info->MergedFB) { + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, + ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); + break; + + case MT_NONE: + default: + break; + } + OUTREGP (RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS)); + } + } + + if ((pRADEONEnt->HasSecondary && !info->IsSwitching) || + (info->IsSwitching && info->IsSecondary)) { + + /*if (info->IsSwitching) ScreenCount = 0;*/ + + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, + ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + + break; + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); + + break; + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS)); + } +} + +/* Unblank screen. */ +void RADEONUnblank (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); +#if 0 + static int ScreenCount = 0; + ScreenCount++; +#endif + + if (!pRADEONEnt->HasSecondary || + /*ScreenCount == 2 ||*/ + (info->IsSwitching && !info->IsSecondary)) { + + /*if (ScreenCount == 1) ScreenCount = 0;*/ + + switch (pRADEONEnt->Controller[0].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[0].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[0].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); + break; + + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC_EXT_CNTL, + 0, + ~(RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS)); + + if (!info->HasCRTC2) return; + + if (info->MergedFB) { + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); + break; + + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC2_GEN_CNTL, 0, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS)); + } + } + + if (/*ScreenCount == 2 ||*/ + (info->IsSwitching && info->IsSecondary)) { + + /*ScreenCount = 0;*/ + + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); + + break; + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC2_GEN_CNTL, + 0, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS)); + + } +} + +/* Sets VESA Display Power Management Signaling (DPMS) Mode */ +void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, + int flags) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONMonitorType MonType; + RADEONTmdsType TmdsType; + RADEONDacType DacType; + unsigned long tmpPixclksCntl; + + if (!pScrn->vtSema) return; + + if (!info->IsSecondary) { + MonType = pRADEONEnt->Controller[0].pPort->MonType; + TmdsType = pRADEONEnt->Controller[0].pPort->TMDSType; + DacType = pRADEONEnt->Controller[0].pPort->DACType; + } else { + MonType = pRADEONEnt->Controller[1].pPort->MonType; + TmdsType = pRADEONEnt->Controller[1].pPort->TMDSType; + DacType = pRADEONEnt->Controller[1].pPort->DACType; + } + +#ifdef XF86DRI + if (info->CPStarted) DRILock(pScrn->pScreen, 0); +#endif + + if (info->accelOn) + RADEON_SYNC(info, pScrn); + + if (info->FBDev) { + fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); + } else { + int mask1 = (RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_VSYNC_DIS); + int mask2 = (RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS); + + switch (PowerManagementMode) { + case DPMSModeOn: + /* Screen: On; HSync: On, VSync: On */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); + } + break; + + case DPMSModeStandby: + /* Screen: Off; HSync: Off, VSync: On */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, + ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, + ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, + RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS, + ~mask1); + } + break; + + case DPMSModeSuspend: + /* Screen: Off; HSync: On, VSync: Off */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, + ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, + ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, + RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS, + ~mask1); + } + break; + + case DPMSModeOff: + /* Screen: Off; HSync: Off, VSync: Off */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); + } + break; + } + + if (PowerManagementMode == DPMSModeOn) { + switch (MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); + usleep (info->PanelPwrDly * 1000); + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); + break; + case MT_DFP: + if (TmdsType == TMDS_EXT) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, + ~RADEON_FP2_DVO_EN); + } + } else + OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), + ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + break; + case MT_CRT: + default: + RADEONDacPowerSet(pScrn, TRUE, (DacType == DAC_PRIMARY)); + break; + } + if (info->MergedFB) { + MonType = pRADEONEnt->Controller[1].pPort->MonType; + TmdsType = pRADEONEnt->Controller[1].pPort->TMDSType; + DacType = pRADEONEnt->Controller[1].pPort->DACType; + switch (MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); + usleep (info->PanelPwrDly * 1000); + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); + break; + case MT_DFP: + if (TmdsType == TMDS_EXT) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, + ~RADEON_FP2_DVO_EN); + } + } else + OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), + ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + break; + case MT_CRT: + default: + RADEONDacPowerSet(pScrn, TRUE, (DacType == DAC_PRIMARY)); + break; + } + } + } else if ((PowerManagementMode == DPMSModeOff) || + (PowerManagementMode == DPMSModeSuspend) || + (PowerManagementMode == DPMSModeStandby)) { + + switch (MonType) { + case MT_LCD: + tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, + ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + break; + case MT_DFP: + if (TmdsType == TMDS_EXT) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); + } + } else + OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + break; + case MT_CRT: + default: + RADEONDacPowerSet(pScrn, FALSE, (DacType == DAC_PRIMARY)); + break; + } + if (info->MergedFB) { + MonType = pRADEONEnt->Controller[1].pPort->MonType; + TmdsType = pRADEONEnt->Controller[1].pPort->TMDSType; + DacType = pRADEONEnt->Controller[1].pPort->DACType; + switch (MonType) { + case MT_LCD: + tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, + ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + break; + case MT_DFP: + if (TmdsType == TMDS_EXT) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); + } + } else + OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + break; + case MT_CRT: + default: + RADEONDacPowerSet(pScrn, FALSE, (DacType == DAC_PRIMARY)); + break; + } + } + } + } + + +#ifdef XF86DRI + if (info->CPStarted) DRIUnlock(pScrn->pScreen); +#endif +} + diff -dNau8 old-src/radeon_probe.h src/radeon_probe.h --- old-src/radeon_probe.h 2006-08-31 21:07:19.000000000 -0700 +++ src/radeon_probe.h 2006-08-31 21:14:13.000000000 -0700 @@ -110,35 +110,31 @@ RADEONTmdsType TMDSType; RADEONConnectorType ConnectorType; RADEONMonitorType MonType; xf86MonPtr MonInfo; } RADEONConnector; typedef struct { - Bool HasSecondary; + Bool IsUsed; + Bool IsActive; + DisplayModePtr pCurMode; + RADEONConnector* pPort; +} RADEONController; - /* - * The next two are used to make sure CRTC2 is restored before CRTC_EXT, - * otherwise it could lead to blank screens. - */ - Bool IsSecondaryRestored; - Bool RestorePrimary; +typedef struct +{ + Bool HasSecondary; ScrnInfoPtr pSecondaryScrn; ScrnInfoPtr pPrimaryScrn; - int MonType1; - int MonType2; - xf86MonPtr MonInfo1; - xf86MonPtr MonInfo2; - Bool ReversedDAC; /* TVDAC used as primary dac */ - Bool ReversedTMDS; /* DDC_DVI is used for external TMDS */ RADEONConnector PortInfo[2]; + RADEONController Controller[2]; } RADEONEntRec, *RADEONEntPtr; /* radeon_probe.c */ extern const OptionInfoRec *RADEONAvailableOptions(int, int); extern void RADEONIdentify(int); extern Bool RADEONProbe(DriverPtr, int); extern PciChipsets RADEONPciChipsets[]; diff -dNau8 old-src/radeon_reg.h src/radeon_reg.h --- old-src/radeon_reg.h 2006-08-31 21:07:19.000000000 -0700 +++ src/radeon_reg.h 2006-08-31 21:14:13.000000000 -0700 @@ -452,16 +452,17 @@ #define RADEON_DAC_CNTL 0x0058 # define RADEON_DAC_RANGE_CNTL (3 << 0) # define RADEON_DAC_RANGE_CNTL_MASK 0x03 # define RADEON_DAC_BLANKING (1 << 2) # define RADEON_DAC_CMP_EN (1 << 3) # define RADEON_DAC_CMP_OUTPUT (1 << 7) # define RADEON_DAC_8BIT_EN (1 << 8) +# define RADEON_DAC_TVO_EN (1 << 10) # define RADEON_DAC_VGA_ADR_EN (1 << 13) # define RADEON_DAC_PDWN (1 << 15) # define RADEON_DAC_MASK_ALL (0xff << 24) #define RADEON_DAC_CNTL2 0x007c # define RADEON_DAC2_DAC_CLK_SEL (1 << 0) # define RADEON_DAC2_DAC2_CLK_SEL (1 << 1) # define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5) #define RADEON_DAC_EXT_CNTL 0x0280 @@ -470,28 +471,50 @@ # define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6) # define RADEON_DAC_FORCE_DATA_MASK 0x0003ff00 # define RADEON_DAC_FORCE_DATA_SHIFT 8 #define RADEON_DAC_MACRO_CNTL 0x0d04 # define RADEON_DAC_PDWN_R (1 << 16) # define RADEON_DAC_PDWN_G (1 << 17) # define RADEON_DAC_PDWN_B (1 << 18) #define RADEON_TV_DAC_CNTL 0x088c +# define RADEON_TV_DAC_NBLANK (1 << 0) +# define RADEON_TV_DAC_NHOLD (1 << 1) +# define RADEON_TV_DAC_PEDESTAL (1 << 2) +# define RADEON_TV_MONITOR_DETECT_EN (1 << 4) +# define RADEON_TV_DAC_CMPOUT (1 << 5) +# define RADEON_TV_DAC_STD_NTSC (1 << 8) # define RADEON_TV_DAC_STD_MASK 0x0300 +# define RADEON_TV_DAC_STD_PS2 0x0200 # define RADEON_TV_DAC_BGSLEEP (1 << 6) +# define RADEON_TV_DAC_BGADJ_MASK (0xf << 16) +# define RADEON_TV_DAC_DACADJ_MASK (0xf << 20) # define RADEON_TV_DAC_RDACPD (1 << 24) # define RADEON_TV_DAC_GDACPD (1 << 25) # define RADEON_TV_DAC_BDACPD (1 << 26) +# define R420_TV_DAC_DACADJ_MASK (0x1f << 20) +# define R420_TV_DAC_RDACPD (1 << 25) +# define R420_TV_DAC_GDACPD (1 << 26) +# define R420_TV_DAC_BDACPD (1 << 27) +# define R420_TV_DAC_TVENABLE (1 << 28) #define RADEON_DISP_HW_DEBUG 0x0d14 # define RADEON_CRT2_DISP1_SEL (1 << 5) #define RADEON_DISP_OUTPUT_CNTL 0x0d64 # define RADEON_DISP_DAC_SOURCE_MASK 0x03 # define RADEON_DISP_DAC2_SOURCE_MASK 0x0c # define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 # define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 +# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03<<2) +# define RADEON_DISP_TVDAC_SOURCE_CRTC 0x0 +# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01<<2) +# define RADEON_DISP_TV_SOURCE_CRTC (1 << 16) /* crtc1 or crtc2 */ +# define RADEON_DISP_TV_SOURCE_LTU (0 << 16) /* linear transform unit */ +#define RADEON_DISP_TV_OUT_CNTL 0x0d6c +# define RADEON_DISP_TV_PATH_SRC_CRTC2 (1 << 16) +# define RADEON_DISP_TV_PATH_SRC_CRTC1 (0 << 16) #define RADEON_DAC_CRC_SIG 0x02cc #define RADEON_DAC_DATA 0x03c9 /* VGA */ #define RADEON_DAC_MASK 0x03c6 /* VGA */ #define RADEON_DAC_R_INDEX 0x03c7 /* VGA */ #define RADEON_DAC_W_INDEX 0x03c8 /* VGA */ #define RADEON_DDA_CONFIG 0x02e0 #define RADEON_DDA_ON_OFF 0x02e4 #define RADEON_DEFAULT_OFFSET 0x16e0 @@ -1445,16 +1468,19 @@ #define RADEON_VIPH_CH1_SBCNT 0x0c24 #define RADEON_VIPH_CH2_SBCNT 0x0c28 #define RADEON_VIPH_CH3_SBCNT 0x0c2c #define RADEON_VIPH_CH0_ABCNT 0x0c30 #define RADEON_VIPH_CH1_ABCNT 0x0c34 #define RADEON_VIPH_CH2_ABCNT 0x0c38 #define RADEON_VIPH_CH3_ABCNT 0x0c3c #define RADEON_VIPH_CONTROL 0x0c40 +# define RADEON_VIP_BUSY 0 +# define RADEON_VIP_IDLE 1 +# define RADEON_VIP_RESET 2 #define RADEON_VIPH_DV_LAT 0x0c44 #define RADEON_VIPH_BM_CHUNK 0x0c48 #define RADEON_VIPH_DV_INT 0x0c4c #define RADEON_VIPH_TIMEOUT_STAT 0x0c50 #define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010 #define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK 0x00000010 #define RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000 @@ -3008,20 +3034,80 @@ #define RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR 32 #define RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR 48 #define RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR 49 #define RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR 50 #define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 51 #define RADEON_SS_SHININESS 60 #define RADEON_TV_MASTER_CNTL 0x0800 +# define RADEON_TV_ASYNC_RST (1 << 0) +# define RADEON_CRT_ASYNC_RST (1 << 1) +# define RADEON_RESTART_PHASE_FIX (1 << 3) +# define RADEON_CRT_FIFO_CE_EN (1 << 9) +# define RADEON_TV_FIFO_CE_EN (1 << 10) # define RADEON_TVCLK_ALWAYS_ONb (1 << 30) -#define RADEON_TV_DAC_CNTL 0x088c -# define RADEON_TV_DAC_CMPOUT (1 << 5) #define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 # define RADEON_Y_RED_EN (1 << 0) # define RADEON_C_GRN_EN (1 << 1) # define RADEON_CMP_BLU_EN (1 << 2) +# define RADEON_DAC_DITHER_EN (1 << 3) # define RADEON_RED_MX_FORCE_DAC_DATA (6 << 4) # define RADEON_GRN_MX_FORCE_DAC_DATA (6 << 8) # define RADEON_BLU_MX_FORCE_DAC_DATA (6 << 12) # define RADEON_TV_FORCE_DAC_DATA_SHIFT 16 +#define RADEON_TV_RGB_CNTL 0x0804 +# define RADEON_SWITCH_TO_BLUE (1 << 4) +# define RADEON_RGB_DITHER_EN (1 << 5) +# define RADEON_RGB_SRC_SEL_MASK (3 << 8) +# define RADEON_RGB_SRC_SEL_CRTC1 (0 << 8) +# define RADEON_RGB_SRC_SEL_RMX (1 << 8) +# define RADEON_RGB_SRC_SEL_CRTC2 (2 << 8) +# define RADEON_RGB_CONVERT_BY_PASS (1 << 10) +#define RADEON_TV_SYNC_CNTL 0x0808 +#define RADEON_TV_HTOTAL 0x080c +#define RADEON_TV_HDISP 0x0810 +#define RADEON_TV_HSTART 0x0818 +#define RADEON_TV_HCOUNT 0x081C +#define RADEON_TV_VTOTAL 0x0820 +#define RADEON_TV_VDISP 0x0824 +#define RADEON_TV_VCOUNT 0x0828 +#define RADEON_TV_FTOTAL 0x082c +#define RADEON_TV_FCOUNT 0x0830 +#define RADEON_TV_FRESTART 0x0834 +#define RADEON_TV_HRESTART 0x0838 +#define RADEON_TV_VRESTART 0x083c +#define RADEON_TV_HOST_READ_DATA 0x0840 +#define RADEON_TV_HOST_WRITE_DATA 0x0844 +#define RADEON_TV_HOST_RD_WT_CNTL 0x0848 +#define RADEON_TV_VSCALER_CNTL1 0x084c +# define RADEON_RESTART_FIELD (1 << 29) /* restart on field 0 */ +# define RADEON_Y_DEL_W_SIG_SHIFT 26 +#define RADEON_TV_TIMING_CNTL 0x0850 +#define RADEON_TV_VSCALER_CNTL2 0x0854 +# define RADEON_DITHER_MODE (1 << 0) +# define RADEON_Y_OUTPUT_DITHER_EN (1 << 1) +# define RADEON_UV_OUTPUT_DITHER_EN (1 << 2) +# define RADEON_UV_TO_BUF_DITHER_EN (1 << 3) +#define RADEON_TV_Y_FALL_CNTL 0x0858 +# define RADEON_Y_FALL_PING_PONG (1 << 16) +#define RADEON_TV_Y_RISE_CNTL 0x085c +# define RADEON_Y_RISE_PING_PONG (1 << 16) +#define RADEON_TV_Y_SAW_TOOTH_CNTL 0x0860 +#define RADEON_TV_UPSAMP_AND_GAIN_CNTL 0x0864 +#define RADEON_TV_GAIN_LIMIT_SETTINGS 0x0868 +#define RADEON_TV_LINEAR_GAIN_SETTINGS 0x086c +#define RADEON_TV_MODULATOR_CNTL1 0x0870 +# define RADEON_ALT_PHASE_EN (1 << 6) +# define RADEON_SYNC_TIP_LEVEL (1 << 7) +#define RADEON_TV_MODULATOR_CNTL2 0x0874 +#define RADEON_TV_CRC_CNTL 0x0890 +#define RADEON_TV_UV_ADR 0x08ac +#define RADEON_TV_PLL_FINE_CNTL 0x0020 /* PLL */ +#define RADEON_TV_PLL_CNTL 0x0021 /* PLL */ +# define RADEON_TV_SLIP_EN (1 << 23) +# define RADEON_TV_DTO_EN (1 << 28) +#define RADEON_TV_PLL_CNTL1 0x0022 /* PLL */ +# define RADEON_TVPLL_TEST_DIS (1 << 31) +# define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) +# define RADEON_TVPLL_SLEEP (1 << 3) +# define RADEON_TVPLL_REFCLK_SEL (1 << 4) #endif