summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/radeon.h28
-rw-r--r--src/radeon_display.c1940
-rw-r--r--src/radeon_driver.c2581
-rw-r--r--src/radeon_probe.h13
-rw-r--r--src/radeon_reg.h90
6 files changed, 2451 insertions, 2203 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7e6af9c1..ad64d557 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -81,7 +81,7 @@ radeon_drv_ladir = @moduledir@/drivers
radeon_drv_la_SOURCES = \
radeon_accel.c radeon_mergedfb.c radeon_cursor.c radeon_dga.c \
radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \
- radeon_vip.c radeon_misc.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES)
+ radeon_vip.c radeon_misc.c radeon_display.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES)
theatre_detect_drv_la_LTLIBRARIES = theatre_detect_drv.la
theatre_detect_drv_la_LDFLAGS = -module -avoid-version
diff --git a/src/radeon.h b/src/radeon.h
index 6402e488..247cc6f9 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -79,6 +79,13 @@
#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
+
typedef enum {
OPTION_NOACCEL,
OPTION_SW_CURSOR,
@@ -254,6 +261,7 @@ typedef struct {
CARD32 dac2_cntl;
CARD32 disp_output_cntl;
+ CARD32 disp_tv_out_cntl;
CARD32 disp_hw_debug;
CARD32 disp2_merge_cntl;
CARD32 grph2_buffer_cntl;
@@ -267,14 +275,16 @@ typedef struct {
/* 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;
@@ -291,6 +301,7 @@ typedef struct {
unsigned ppll_ref_div;
unsigned ppll_div_3;
CARD32 htotal_cntl;
+ CARD32 vclk_cntl;
/* Computed values for PLL2 */
CARD32 dot_clock_freq_2;
@@ -302,6 +313,7 @@ typedef struct {
CARD32 p2pll_ref_div;
CARD32 p2pll_div_0;
CARD32 htotal_cntl2;
+ CARD32 pixclks_cntl;
/* Pallet */
Bool palette_valid;
@@ -797,6 +809,8 @@ typedef struct {
int MaxSurfaceWidth;
int MaxLines;
+ CARD32 tv_dac_adj;
+
} RADEONInfoRec, *RADEONInfoPtr;
#define RADEONWaitForFifo(pScrn, entries) \
@@ -861,6 +875,16 @@ extern Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn);
extern Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn);
extern Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn);
+extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn);
+extern Bool RADEONI2cInit(ScrnInfoPtr pScrn);
+extern void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag);
+extern void RADEONGetPanelInfo(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);
diff --git a/src/radeon_display.c b/src/radeon_display.c
new file mode 100644
index 00000000..250b5437
--- /dev/null
+++ b/src/radeon_display.c
@@ -0,0 +1,1940 @@
+/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.116 2006/04/29 21:30:23 daenzer 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
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+/* X and server generic header files */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "fbdevhw.h"
+#include "vgaHW.h"
+
+/* Driver data structures */
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_version.h"
+#include "radeon_mergedfb.h"
+
+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 */
+ 0x01080000, /* rv410 */ /* FIXME: just values from r420 used... */
+ 0x00780000, /* rs400 */ /* FIXME: just values from rv380 used... */
+};
+
+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 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_MACRO_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);
+
+ if (ulOrigDAC_CNTL & RADEON_DAC_PDWN) {
+ /* turn on power so testing can go through */
+ ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
+ ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
+ RADEON_DAC_PDWN_B);
+ OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_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);
+
+ if (!bConnected) {
+ /* Power DAC down if CRT is not connected */
+ ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
+ ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
+ RADEON_DAC_PDWN_B);
+ OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
+
+ ulData = INREG(RADEON_DAC_CNTL);
+ ulData |= RADEON_DAC_PDWN ;
+ OUTREG(RADEON_DAC_CNTL, ulData);
+ }
+ } 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 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 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);
+
+ /* 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;
+ }
+}
+
+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;
+ }
+}
+
+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;
+
+
+
+ max_mt = 5;
+
+ if(info->IsSecondary) {
+ pScrn->monitor->DDC = pRADEONEnt->Controller[1].pPort->MonInfo;
+ info->DisplayType = (RADEONMonitorType)pRADEONEnt->Controller[1].pPort->MonType;
+ 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;
+ }
+ 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_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 0
+ 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;
+ }
+#endif
+
+ 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->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];
+
+ info->MergeType = MT_NONE;
+ info->DisplayType = pRADEONEnt->Controller[0].pPort->MonType;
+
+ 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->Controller[0].pPort = &pRADEONEnt->PortInfo[0];
+ pRADEONEnt->Controller[1].pPort = &pRADEONEnt->PortInfo[1];
+ if (pRADEONEnt->PortInfo[0].MonType == MT_NONE) {
+ if (pRADEONEnt->PortInfo[1].MonType == MT_NONE) {
+ pRADEONEnt->Controller[0].pPort->MonType = MT_CRT;
+ } else {
+ pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[1]);
+ pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[0]);
+ }
+ }
+
+ pScrn->monitor->DDC = pRADEONEnt->Controller[0].pPort->MonInfo;
+ info->DisplayType = pRADEONEnt->Controller[0].pPort->MonType;
+
+ pRADEONEnt->ReversedDAC = FALSE;
+ info->OverlayOnCRTC2 = FALSE;
+ info->MergeType = MT_NONE;
+ if (pRADEONEnt->Controller[1].pPort->MonType != MT_NONE) {
+ if(!pRADEONEnt->HasSecondary) {
+ info->MergeType = pRADEONEnt->Controller[1].pPort->MonType;
+ }
+
+ 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;
+}
+
+
+/*
+ * 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:
+ case CHIP_FAMILY_RV410:
+ 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;
+ }
+ }
+}
+
+/* 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",
+ (unsigned int)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",
+ (unsigned int)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;
+
+ 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 */
+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;
+ }
+ }
+}
+
+static void RADEONDPMSSetOn(ScrnInfoPtr pScrn, int controller)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ RADEONMonitorType MonType;
+ RADEONTmdsType TmdsType;
+ RADEONDacType DacType;
+
+ MonType = pRADEONEnt->Controller[controller].pPort->MonType;
+ TmdsType = pRADEONEnt->Controller[controller].pPort->TMDSType;
+ DacType = pRADEONEnt->Controller[controller].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;
+ }
+}
+
+static void RADEONDPMSSetOff(ScrnInfoPtr pScrn, int controller)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ RADEONMonitorType MonType;
+ RADEONTmdsType TmdsType;
+ RADEONDacType DacType;
+ unsigned long tmpPixclksCntl;
+
+ MonType = pRADEONEnt->Controller[controller].pPort->MonType;
+ TmdsType = pRADEONEnt->Controller[controller].pPort->TMDSType;
+ DacType = pRADEONEnt->Controller[controller].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;
+ }
+}
+
+
+/* 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;
+
+ 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) {
+ RADEONDPMSSetOn(pScrn, info->IsSecondary ? 1 : 0);
+ if (info->MergedFB)
+ RADEONDPMSSetOn(pScrn, 1);
+ } else if ((PowerManagementMode == DPMSModeOff) ||
+ (PowerManagementMode == DPMSModeSuspend) ||
+ (PowerManagementMode == DPMSModeStandby)) {
+
+ RADEONDPMSSetOff(pScrn, info->IsSecondary ? 1 : 0);
+ if (info->MergedFB)
+ RADEONDPMSSetOff(pScrn, 1);
+ }
+ }
+
+#ifdef XF86DRI
+ if (info->CPStarted) DRIUnlock(pScrn->pScreen);
+#endif
+}
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 8468c285..5ef7d15d 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -112,12 +112,7 @@
#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);
@@ -125,10 +120,6 @@ 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);
@@ -457,27 +448,6 @@ static struct
{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, 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)
@@ -862,77 +832,6 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn)
}
}
-/* 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)
@@ -950,366 +849,6 @@ 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_MACRO_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);
-
- if (ulOrigDAC_CNTL & RADEON_DAC_PDWN) {
- /* turn on power so testing can go through */
- ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
- ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
- RADEON_DAC_PDWN_B);
- OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_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);
-
- if (!bConnected) {
- /* Power DAC down if CRT is not connected */
- ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
- ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
- RADEON_DAC_PDWN_B);
- OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
-
- ulData = INREG(RADEON_DAC_CNTL);
- ulData |= RADEON_DAC_PDWN ;
- OUTREG(RADEON_DAC_CNTL, ulData);
- }
- } 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);
@@ -1512,155 +1051,6 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn)
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);
@@ -1752,421 +1142,6 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
}
}
-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 0
- 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;
- }
-#endif
-
- 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 */
@@ -2997,52 +1972,6 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn)
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)
{
@@ -3070,102 +1999,6 @@ static void RADEONPreInitDDC(ScrnInfoPtr pScrn)
}
-/* 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.
@@ -3712,93 +2545,6 @@ static Bool RADEONPreInitGamma(ScrnInfoPtr pScrn)
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)
{
@@ -4012,7 +2758,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
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)
@@ -4023,11 +2769,6 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
"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,
@@ -4817,6 +3558,19 @@ static Bool RADEONPreInitXv(ScrnInfoPtr pScrn)
return TRUE;
}
+static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
+{
+ RADEONGetBIOSInfo(pScrn, pInt10);
+ if (!RADEONQueryConnectedMonitors(pScrn))
+ goto fail;
+ RADEONGetClockInfo(pScrn);
+ RADEONGetTVDacAdjInfo(pScrn);
+
+ return TRUE;
+ fail:
+ return FALSE;
+}
+
static void
RADEONProbeDDC(ScrnInfoPtr pScrn, int indx)
{
@@ -5140,9 +3894,8 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
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.
@@ -6493,6 +5246,12 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
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_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_CRTC_OFFSET, restore->crtc_offset);
OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl);
OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch);
@@ -6535,9 +5294,14 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
OUTREG(RADEON_TV_DAC_CNTL, 0x00280203);
+ //if ((info->ChipFamily != CHIP_FAMILY_RADEON) &&
+ // (info->ChipFamily != CHIP_FAMILY_R200))
+ //OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
+
if ((info->ChipFamily == CHIP_FAMILY_R200) ||
IS_R300_VARIANT) {
OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl);
+ OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl);
} else {
OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
}
@@ -6546,6 +5310,12 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
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_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid);
+ OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid);
+ OUTREG(RADEON_FP_CRTC2_H_TOTAL_DISP, restore->fp_crtc2_h_total_disp);
+ OUTREG(RADEON_FP_CRTC2_V_TOTAL_DISP, restore->fp_crtc2_v_total_disp);
+
OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset);
OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl);
OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch);
@@ -6553,8 +5323,6 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
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);
}
@@ -6573,10 +5341,6 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
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);
@@ -7196,6 +5960,12 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
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->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);
+ 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->crtc_offset = INREG(RADEON_CRTC_OFFSET);
save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL);
save->crtc_pitch = INREG(RADEON_CRTC_PITCH);
@@ -7216,12 +5986,9 @@ 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->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL);
save->fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH);
- 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);
@@ -7244,7 +6011,9 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
unsigned char *RADEONMMIO = info->MMIO;
save->dac2_cntl = INREG(RADEON_DAC_CNTL2);
+ save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
+ save->disp_tv_out_cntl = INREG(RADEON_DISP_TV_OUT_CNTL);
save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG);
save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
@@ -7256,9 +6025,11 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
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->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL);
+ 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->fp_crtc2_h_total_disp = INREG(RADEON_FP_CRTC2_H_TOTAL_DISP);
+ save->fp_crtc2_v_total_disp = INREG(RADEON_FP_CRTC2_V_TOTAL_DISP);
+
save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL);
}
@@ -7268,6 +6039,7 @@ 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%08lx\n",
save->ppll_ref_div,
@@ -7285,6 +6057,7 @@ 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%08lx 0x%08lx 0x%08lx\n",
save->p2pll_ref_div,
@@ -7499,331 +6272,242 @@ static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info)
}
-/* Calculate display buffer watermark to prevent buffer underflow */
-static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
+/* Define CRTC registers for requested video mode */
+static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
+ RADEONSavePtr save, DisplayModePtr mode)
{
- 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);
- }
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ 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
+ */
- /* R420 and RV410 family not supported yet */
- if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return;
+ 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;
- if (pRADEONEnt->pSecondaryScrn) {
- if (info->IsSecondary) return;
- info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn);
- } else if (info->MergedFB) info2 = info;
+ 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);
- /*
- * Determine if there is enough bandwidth for current display mode
- */
- mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
+ return;
+ }
- 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;
+ if (info->PanelXRes == 0 || info->PanelYRes == 0) {
+ Hratio = 1.0;
+ Vratio = 1.0;
} else {
- mode2 = NULL;
- }
+ if (xres > info->PanelXRes) xres = info->PanelXRes;
+ if (yres > info->PanelYRes) yres = info->PanelYRes;
- pix_clk = mode1->Clock/1000.0;
- if (mode2)
- pix_clk2 = mode2->Clock/1000.0;
- else
- pix_clk2 = 0;
+ Hratio = (float)xres/(float)info->PanelXRes;
+ Vratio = (float)yres/(float)info->PanelYRes;
+ }
- peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes);
- if (info2)
- peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes);
+ 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);
- 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");
- }
+ } 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);
- /* 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;
+ save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO |
+ RADEON_HORZ_PANEL_SIZE);
+ save->fp_horz_stretch |= ((info->PanelXRes / 8 - 1) << 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) {
+ 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);
- /* 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);
- }
+ save->fp_vert_stretch &= ~(RADEON_VERT_AUTO_RATIO_EN |
+ RADEON_VERT_PANEL_SIZE);
+ save->fp_vert_stretch |= ((info->PanelYRes-1) << 12);
- 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);
+ 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
-#endif
- sclk_eff = info->sclk;
- }
+ save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
+ } else
+ save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1;
- /* 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;
- }
+ 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;
}
- mc_latency_sclk = sclk_delay / sclk_eff;
-
- if (info->IsDDR) {
- if (info->RamWidth == 32) {
- k1 = 40;
- c = 3;
- } else {
- k1 = 20;
- c = 1;
- }
+ 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 {
- 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);
+ if (info->DisplayType == MT_LCD) {
- /*
- 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;
+ save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON);
+ save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
- /*
- 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);
+ } 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;
- /*
- 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;
+ RADEONTRACE(("TMDS_PLL from %lx to %lx\n",
+ orig->tmds_pll_cntl,
+ save->tmds_pll_cntl));
- /*
- Find the critical point of the display buffer.
- */
- critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5);
+ 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);
- /* ???? */
- /*
- 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;
+ save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+ }
}
+ info->BiosHotkeys = FALSE;
/*
- 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",
- (unsigned int)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;
- }
+ * 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");
+ }
+ }
- if (max_stop_req - critical_point2 < 4) critical_point2 = 0;
+ 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 {
+ 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;
}
+ save->bios_4_scratch = 0x4;
+ save->bios_6_scratch |= 0x40000000;
- if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) {
- /* some R300 cards have problem with this set to 0 */
- critical_point2 = 0x10;
- }
+ } else if (info->IsMobility && (info->DisplayType == MT_LCD)) {
- OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
- (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+ /* 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;
- RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n",
- (unsigned int)info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL)));
}
-}
+
+ 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 CRTC registers for requested video mode */
static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
@@ -7836,6 +6520,12 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
int hsync_wid;
int vsync_wid;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+
+ 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;
@@ -7850,24 +6540,6 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
return FALSE;
}
- 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)
@@ -7901,43 +6573,74 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
RADEON_CRTC_CRT_ON);
}
- save->dac_cntl = (RADEON_DAC_MASK_ALL
- | RADEON_DAC_VGA_ADR_EN
- | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN));
+ save->surface_cntl = 0;
+ save->disp_merge_cntl = info->SavedReg.disp_merge_cntl;
+ save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+
+#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;
+
+ case 32:
+ save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP;
+ save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP;
+ break;
+ }
+#endif
+
+ 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;
+ }
+
+ 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));
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)
+ | (hsync_wid << 16)
| ((mode->Flags & V_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
-#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?
- */
- save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
- | ((mode->CrtcVDisplay
- * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
- << 16));
-#endif
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)
+ | (vsync_wid << 16)
| ((mode->Flags & V_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0));
@@ -7966,35 +6669,10 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
(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->surface_cntl = 0;
- save->disp_merge_cntl = info->SavedReg.disp_merge_cntl;
- save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
-
-#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;
-
- case 32:
- save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP;
- save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP;
- break;
- }
-#endif
+ save->dac_cntl = (RADEON_DAC_MASK_ALL
+ | RADEON_DAC_VGA_ADR_EN
+ | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN));
if (info->IsDellServer) {
save->dac2_cntl = info->SavedReg.dac2_cntl;
@@ -8031,6 +6709,10 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
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;
@@ -8045,93 +6727,31 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
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;
- }
- }
- }
-
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)
+ | (hsync_wid << 16)
| ((mode->Flags & V_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
-#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?
- */
- save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
- | ((mode->CrtcVDisplay
- * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
- << 16));
-#endif
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)
+ | (vsync_wid << 16)
| ((mode->Flags & V_NVSYNC)
? RADEON_CRTC2_V_SYNC_POL
: 0));
@@ -8169,14 +6789,70 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
(pScrn->bitsPerPixel * 8));
save->crtc2_pitch |= save->crtc2_pitch << 16;
}
+
+ 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));
+
save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl;
save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN);
+ /* 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->Controller[0].pPort->MonType != 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->Controller[0].pPort->MonType != 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;
+ }
+ }
+ }
+
+
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->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid;
+ save->fp_v2_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);
@@ -8225,248 +6901,6 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
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 %lx to %lx\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 = FALSE;
- /*
- * Allow the bios to toggle outputs. see below for more.
- */
- 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");
- }
-
- 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,
@@ -8532,6 +6966,10 @@ static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info,
save->ppll_ref_div = pll->reference_div;
save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16));
save->htotal_cntl = 0;
+
+ save->vclk_cntl = (info->SavedReg.vclk_cntl &
+ ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
+
}
/* Define PLL2 registers for requested video mode */
@@ -8539,6 +6977,7 @@ static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
RADEONPLLPtr pll, double dot_clock,
int no_odd_postdiv)
{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned long freq = dot_clock * 100;
struct {
@@ -8595,6 +7034,11 @@ static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
save->p2pll_div_0 = (save->feedback_div_2 |
(post_div->bitvalue << 16));
save->htotal_cntl2 = 0;
+
+ save->pixclks_cntl = ((info->SavedReg.pixclks_cntl &
+ ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
+ RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
+
}
#if 0
@@ -8708,15 +7152,15 @@ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode,
if ((info->MergeType == MT_LCD) || (info->MergeType == MT_DFP)) {
/* I suppose crtc2 could drive the FP as well... */
RADEONInitFPRegisters(pScrn, &info->SavedReg, save,
- ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info);
+ ((RADEONMergedDisplayModePtr)mode->Private)->CRT2);
}
else {
RADEONInitFPRegisters(pScrn, &info->SavedReg, save,
- ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, info);
+ ((RADEONMergedDisplayModePtr)mode->Private)->CRT1);
}
}
else {
- RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info);
+ RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode);
}
RADEONTRACE(("RADEONInit returns %p\n", save));
@@ -9276,257 +7720,6 @@ _X_EXPORT void RADEONFreeScreen(int scrnIndex, int flags)
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)
{
@@ -9561,7 +7754,7 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn)
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;
@@ -9727,7 +7920,7 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn)
}
/* 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);
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index a4f20e7b..ce4c5388 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -115,6 +115,14 @@ typedef struct
typedef struct
{
+ Bool IsUsed;
+ Bool IsActive;
+ DisplayModePtr pCurMode;
+ RADEONConnector* pPort;
+} RADEONController;
+
+typedef struct
+{
Bool HasSecondary;
/*
@@ -127,13 +135,10 @@ typedef struct
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 */
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index b7c6e263..d873a961 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -457,6 +457,7 @@
# 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)
@@ -475,11 +476,25 @@
# 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
@@ -487,6 +502,14 @@
# 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 */
@@ -1450,6 +1473,9 @@
#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
@@ -3014,15 +3040,75 @@
#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