Blob Blame History Raw
diff --git a/configure.ac b/configure.ac
index 5f18d2b..5216eff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,7 +79,7 @@ sdkdir=$(pkg-config --variable=sdkdir xorg-server)
 # Checks for header files.
 AC_HEADER_STDC
 
-if test "$DRI" != no; then
+if test "x$DRI" = xauto; then
 	AC_CHECK_FILE([${sdkdir}/dri.h],
                       [have_dri_h="yes"], [have_dri_h="no"])
 	AC_CHECK_FILE([${sdkdir}/sarea.h],
diff --git a/man/radeon.man b/man/radeon.man
index 35dd701..9168254 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -383,6 +383,14 @@ case.  This is only useful for LVDS panels (laptop internal panels).
 The default is
 .B on.
 .TP
+.BI "Option \*qLVDSBiosNativeMode\*q \*q" boolean \*q
+On some laptops, the LVDS mode from the timing tables in the bios does 
+not work properly.  In those cases, a CVT mode seems to work better.  
+If you get a blank screen or have LVDS display problems, disable this 
+option to use a CVT mode.  
+The default is
+.B on.
+.TP
 .BI "Option \*qDRI\*q \*q" boolean \*q
 Enable DRI support.  This option allows you to enable to disable the DRI.  
 The default is
diff --git a/src/Makefile.am b/src/Makefile.am
index 1eea432..ff1e225 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,6 +66,17 @@ atimisc_drv_la_SOURCES = \
 	atiload.c atimisc.c atimach64probe.c $(ATIMISC_CPIO_SOURCES) \
 	$(ATIMISC_DGA_SOURCES) $(ATIMISC_DRI_SRCS) $(ATIMISC_EXA_SOURCES)
 
+if XSERVER_LIBPCIACCESS
+# r128 has not been ported yet
+else
+r128_drv_la_LTLIBRARIES = r128_drv.la
+r128_drv_la_LDFLAGS = -module -avoid-version
+r128_drv_ladir = @moduledir@/drivers
+r128_drv_la_SOURCES = \
+	r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \
+	r128_video.c r128_misc.c r128_probe.c $(R128_DRI_SRCS)
+endif
+
 radeon_drv_la_LTLIBRARIES = radeon_drv.la
 radeon_drv_la_LDFLAGS = -module -avoid-version
 radeon_drv_ladir = @moduledir@/drivers
@@ -76,16 +87,6 @@ radeon_drv_la_SOURCES = \
 	radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \
 	$(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES)
 
-if XSERVER_LIBPCIACCESS
-# r128 and theatre have not been ported yet
-else
-r128_drv_la_LTLIBRARIES = r128_drv.la
-r128_drv_la_LDFLAGS = -module -avoid-version
-r128_drv_ladir = @moduledir@/drivers
-r128_drv_la_SOURCES = \
-	r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \
-	r128_video.c r128_misc.c r128_probe.c $(R128_DRI_SRCS)
-
 theatre_detect_drv_la_LTLIBRARIES = theatre_detect_drv.la
 theatre_detect_drv_la_LDFLAGS = -module -avoid-version
 theatre_detect_drv_ladir = @moduledir@/multimedia
@@ -106,7 +107,6 @@ theatre200_drv_la_CFLAGS = \
 	$(AM_CFLAGS) -DMICROC_DIR=\"$(theatre200_drv_ladir)\"
 theatre200_drv_la_SOURCES = \
 	theatre200.c theatre200_module.c
-endif
 
 EXTRA_DIST = \
 	atimach64render.c \
diff --git a/src/atiprint.c b/src/atiprint.c
index 60d9c21..3a1debb 100644
--- a/src/atiprint.c
+++ b/src/atiprint.c
@@ -26,6 +26,7 @@
 
 #include <string.h>
 #include <ctype.h>
+#include <stdint.h>
 
 #include "ati.h"
 #include "atichip.h"
diff --git a/src/atiprobe.c b/src/atiprobe.c
index 78b3edd..38ce90d 100644
--- a/src/atiprobe.c
+++ b/src/atiprobe.c
@@ -26,6 +26,7 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <stdint.h>
 
 #include "ati.h"
 #include "atibus.h"
diff --git a/src/radeon.h b/src/radeon.h
index ad94cc5..6ee43b2 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -157,7 +157,8 @@ typedef enum {
 #if defined(__powerpc__)
     OPTION_MAC_MODEL,
 #endif
-    OPTION_DEFAULT_TMDS_PLL
+    OPTION_DEFAULT_TMDS_PLL,
+    OPTION_LVDS_BIOS_NATIVE_MODE
 } RADEONOpts;
 
 
@@ -816,6 +817,8 @@ typedef struct {
     RADEONMacModel    MacModel;
 #endif
 
+    Bool              LVDSBiosNativeMode;
+
     Rotation rotation;
     void (*PointerMoved)(int, int, int);
     CreateScreenResourcesProcPtr CreateScreenResources;
@@ -910,6 +913,8 @@ extern void        RADEONRestoreFP2Registers(ScrnInfoPtr pScrn,
 					     RADEONSavePtr restore);
 extern void        RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn,
 					      RADEONSavePtr restore);
+extern void        RADEONRestoreBIOSRegisters(ScrnInfoPtr pScrn,
+					      RADEONSavePtr restore);
 extern void        RADEONRestoreRMXRegisters(ScrnInfoPtr pScrn,
 					     RADEONSavePtr restore);
 extern void        RADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index 65c2bb0..1b46746 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -176,6 +176,9 @@ static Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
 		case RADEON_LCD_GPIO_MASK:
 		    info->BiosConnector[i].DDCType = DDC_LCD;
 		    break;
+		case RADEON_MDGPIO_EN_REG:
+		    info->BiosConnector[i].DDCType = DDC_GPIO;
+		    break;
 		default:
 		    info->BiosConnector[i].DDCType = DDC_NONE_DETECTED;
 		    break;
@@ -254,6 +257,23 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
 		info->BiosConnector[i].DDCType = DDC_MONID;
 	    }
 
+	    /* XPRESS desktop chips seem to have a proprietary connector listed for
+	     * DVI-D, try and do the right thing here.
+	    */
+	    if ((!info->IsMobility) &&
+		(info->BiosConnector[i].ConnectorType == CONNECTOR_PROPRIETARY)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "Proprietary connector found, assuming DVI-D\n");
+		info->BiosConnector[i].DACType = DAC_NONE;
+		info->BiosConnector[i].TMDSType = TMDS_EXT;
+		info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D;
+	    }
+
+	    if (info->BiosConnector[i].ConnectorType >= CONNECTOR_UNSUPPORTED) {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown connector type: %d!\n",
+			   info->BiosConnector[i].ConnectorType);
+		info->BiosConnector[i].valid = FALSE;
+	    }
 
 	}
     } else {
@@ -277,7 +297,7 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
 		    tmp1 = RADEON_BIOS8(tmp0+2) & 0x07;
 		    if (tmp1) {	    
 			info->BiosConnector[4].DDCType	= tmp1;      
-			if (info->BiosConnector[4].DDCType > DDC_LCD) {
+			if (info->BiosConnector[4].DDCType > DDC_GPIO) {
 			    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 				       "Unknown DDCType %d found\n",
 				       info->BiosConnector[4].DDCType);
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index 47e46f3..eeb1c6c 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -311,7 +311,7 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
 	return FALSE;
     }
 
-    save->bios_4_scratch = info->SavedReg.bios_4_scratch;
+    /*save->bios_4_scratch = info->SavedReg.bios_4_scratch;*/
     save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
 			   | RADEON_CRTC_EN
 			   | (format << 8)
@@ -348,11 +348,10 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
 
     hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
     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 << 16)
+				  | ((hsync_wid & 0x3f) << 16)
 				  | ((mode->Flags & V_NHSYNC)
 				     ? RADEON_CRTC_H_SYNC_POL
 				     : 0));
@@ -363,10 +362,9 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
 
     vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
     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 << 16)
+				  | ((vsync_wid & 0x1f) << 16)
 				  | ((mode->Flags & V_NVSYNC)
 				     ? RADEON_CRTC_V_SYNC_POL
 				     : 0));
@@ -545,11 +543,10 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
 
     hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
     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 << 16)
+				   | ((hsync_wid & 0x3f) << 16)
 				   | ((mode->Flags & V_NHSYNC)
 				      ? RADEON_CRTC_H_SYNC_POL
 				      : 0));
@@ -560,10 +557,9 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
 
     vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
     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 << 16)
+				   | ((vsync_wid & 0x1f) << 16)
 				   | ((mode->Flags & V_NVSYNC)
 				      ? RADEON_CRTC2_V_SYNC_POL
 				      : 0));
@@ -768,6 +764,18 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
 }
 
 static void
+RADEONInitBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info      = RADEONPTR(pScrn);
+
+    /* tell the bios not to muck with the hardware on events */
+    save->bios_4_scratch = 0;
+    save->bios_5_scratch = 0xff00;
+    save->bios_6_scratch = info->SavedReg.bios_6_scratch | 0x40000000;
+
+}
+
+static void
 radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore)
 {
     /* pixclks_cntl controls tv clock routing */
@@ -813,6 +821,9 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	}
     }
 
+    if (info->IsMobility)
+	RADEONInitBIOSRegisters(pScrn, &info->ModeReg);
+
     ErrorF("init memmap\n");
     RADEONInitMemMapRegisters(pScrn, &info->ModeReg, info);
     ErrorF("init common\n");
@@ -868,6 +879,9 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	}
     }
 
+    if (info->IsMobility)
+	RADEONRestoreBIOSRegisters(pScrn, &info->ModeReg);
+
     ErrorF("restore memmap\n");
     RADEONRestoreMemMapRegisters(pScrn, &info->ModeReg);
     ErrorF("restore common\n");
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 03f531e..40e1d98 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -190,6 +190,7 @@ static const OptionInfoRec RADEONOptions[] = {
 #if defined(__powerpc__)
     { OPTION_MAC_MODEL,      "MacModel",         OPTV_STRING,  {0}, FALSE },
 #endif
+    { OPTION_LVDS_BIOS_NATIVE_MODE, "LVDSBiosNativeMode", OPTV_BOOLEAN, {0}, TRUE },
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
@@ -4235,14 +4236,27 @@ void RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
 
     if (info->IsMobility) {
 	OUTREG(RADEON_LVDS_GEN_CNTL,  restore->lvds_gen_cntl);
-	OUTREG(RADEON_LVDS_PLL_CNTL,  restore->lvds_pll_cntl);  
-	/*OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch);
-	OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch);
-	OUTREG(RADEON_BIOS_6_SCRATCH, restore->bios_6_scratch);*/
+	OUTREG(RADEON_LVDS_PLL_CNTL,  restore->lvds_pll_cntl);
     }
 
 }
 
+void RADEONRestoreBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 bios_6_scratch = INREG(RADEON_BIOS_6_SCRATCH);
+
+    OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch);
+    OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch);
+    if (restore->bios_6_scratch & 0x40000000)
+	bios_6_scratch |= 0x40000000;
+    else
+	bios_6_scratch &= ~0x40000000;
+    OUTREG(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+
+}
+
 /* Write to TV FIFO RAM */
 static void RADEONWriteTVFIFO(ScrnInfoPtr pScrn, CARD16 addr,
 			      CARD32 value)
@@ -5082,6 +5096,16 @@ static void RADEONSaveDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
 
 }
 
+static void RADEONSaveBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->bios_4_scratch       = INREG(RADEON_BIOS_4_SCRATCH);
+    save->bios_5_scratch       = INREG(RADEON_BIOS_5_SCRATCH);
+    save->bios_6_scratch       = INREG(RADEON_BIOS_6_SCRATCH);
+}
+
 /* Read flat panel registers */
 static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
 {
@@ -5096,9 +5120,6 @@ static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
     save->lvds_pll_cntl        = INREG(RADEON_LVDS_PLL_CNTL);
     save->tmds_pll_cntl        = INREG(RADEON_TMDS_PLL_CNTL);
     save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL);
-    save->bios_4_scratch       = INREG(RADEON_BIOS_4_SCRATCH);
-    save->bios_5_scratch       = INREG(RADEON_BIOS_5_SCRATCH);
-    save->bios_6_scratch       = INREG(RADEON_BIOS_6_SCRATCH);
 
     if (info->ChipFamily == CHIP_FAMILY_RV280) {
 	/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
@@ -5325,7 +5346,7 @@ static void RADEONSave(ScrnInfoPtr pScrn)
 	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
 # else
 	/* Save mode * & fonts & cmap */
-	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
+	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
 # endif
 	vgaHWLock(hwp);
     }
@@ -5340,6 +5361,7 @@ static void RADEONSave(ScrnInfoPtr pScrn)
     RADEONSavePLLRegisters(pScrn, save);
     RADEONSaveCrtcRegisters(pScrn, save);
     RADEONSaveFPRegisters(pScrn, save);
+    RADEONSaveBIOSRegisters(pScrn, save);
     RADEONSaveDACRegisters(pScrn, save);
     if (pRADEONEnt->HasCRTC2) {
 	RADEONSaveCrtc2Registers(pScrn, save);
@@ -5386,6 +5408,7 @@ void RADEONRestore(ScrnInfoPtr pScrn)
 	RADEONRestorePLL2Registers(pScrn, restore);
     }
 
+    RADEONRestoreBIOSRegisters(pScrn, restore);
     RADEONRestoreCrtcRegisters(pScrn, restore);
     RADEONRestorePLLRegisters(pScrn, restore);
     RADEONRestoreRMXRegisters(pScrn, restore);
@@ -5417,7 +5440,7 @@ void RADEONRestore(ScrnInfoPtr pScrn)
 	*/
        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
 # else
-       vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
+       vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL );
 # endif
        vgaHWLock(hwp);
     }
diff --git a/src/radeon_modes.c b/src/radeon_modes.c
index ea2c229..e01c1e1 100644
--- a/src/radeon_modes.c
+++ b/src/radeon_modes.c
@@ -95,20 +95,45 @@ static DisplayModePtr RADEONTVModes(xf86OutputPtr output)
 static DisplayModePtr RADEONFPNativeMode(xf86OutputPtr output)
 {
     ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     DisplayModePtr  new   = NULL;
+    char            stmp[32];
 
     if (radeon_output->PanelXRes != 0 &&
 	radeon_output->PanelYRes != 0 &&
 	radeon_output->DotClock != 0) {
 
-	/* Add native panel size */
-	new = xf86CVTMode(radeon_output->PanelXRes, radeon_output->PanelYRes, 60.0, TRUE, FALSE);
+	if (info->LVDSBiosNativeMode) {
+	    new             = xnfcalloc(1, sizeof (DisplayModeRec));
+	    sprintf(stmp, "%dx%d", radeon_output->PanelXRes, radeon_output->PanelYRes);
+	    new->name       = xnfalloc(strlen(stmp) + 1);
+	    strcpy(new->name, stmp);
+	    new->HDisplay   = radeon_output->PanelXRes;
+	    new->VDisplay   = radeon_output->PanelYRes;
 
-	new->type       = M_T_DRIVER | M_T_PREFERRED;
+	    new->HTotal     = new->HDisplay + radeon_output->HBlank;
+	    new->HSyncStart = new->HDisplay + radeon_output->HOverPlus;
+	    new->HSyncEnd   = new->HSyncStart + radeon_output->HSyncWidth;
+	    new->VTotal     = new->VDisplay + radeon_output->VBlank;
+	    new->VSyncStart = new->VDisplay + radeon_output->VOverPlus;
+	    new->VSyncEnd   = new->VSyncStart + radeon_output->VSyncWidth;
 
-	new->next       = NULL;
-	new->prev       = NULL;
+	    new->Clock      = radeon_output->DotClock;
+	    new->Flags      = 0;
+
+	} else {
+	    /* Add native panel size */
+	    new = xf86CVTMode(radeon_output->PanelXRes, radeon_output->PanelYRes, 60.0, FALSE, FALSE);
+
+	}
+
+	if (new) {
+	    new->type       = M_T_DRIVER | M_T_PREFERRED;
+
+	    new->next       = NULL;
+	    new->prev       = NULL;
+	}
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Added native panel mode: %dx%d\n",
 		   radeon_output->PanelXRes, radeon_output->PanelYRes);
@@ -159,7 +184,7 @@ static void RADEONAddScreenModes(xf86OutputPtr output, DisplayModePtr *modeList)
 	    }
 	}
 
-	new = xf86CVTMode(width, height, 60.0, TRUE, FALSE);
+	new = xf86CVTMode(width, height, 60.0, FALSE, FALSE);
 
 	new->type      |= M_T_USERDEF;
 
@@ -199,11 +224,13 @@ RADEONProbeOutputModes(xf86OutputPtr output)
 
     if (output->status == XF86OutputStatusConnected) {
 	if (radeon_output->type == OUTPUT_DVI || radeon_output->type == OUTPUT_VGA) {
-	    edid_mon = xf86OutputGetEDID (output, radeon_output->pI2CBus);
-	    xf86OutputSetEDID (output, edid_mon);
+	    if (output->MonInfo) {
+		edid_mon = xf86OutputGetEDID (output, radeon_output->pI2CBus);
+		xf86OutputSetEDID (output, edid_mon);
 
-	    modes = xf86OutputGetEDIDModes (output);
-	    return modes;
+		modes = xf86OutputGetEDIDModes (output);
+		return modes;
+	    }
 	}
 	if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) {
 	    modes = RADEONTVModes(output);
diff --git a/src/radeon_output.c b/src/radeon_output.c
index a6da78e..e2f26e7 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -75,13 +75,14 @@ const char *TMDSTypeName[4] = {
   "None"
 };
 
-const char *DDCTypeName[6] = {
+const char *DDCTypeName[7] = {
   "None",
   "MONID",
   "DVI_DDC",
   "VGA_DDC",
   "CRT2_DDC",
-  "LCD_DDC"
+  "LCD_DDC",
+  "GPIO_DDC"
 };
 
 const char *DACTypeName[4] = {
@@ -277,7 +278,7 @@ RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output)
     DDCReg = radeon_output->DDCReg;
 
     /* Read and output monitor info using DDC2 over I2C bus */
-    if (radeon_output->pI2CBus && info->ddc2 && (DDCReg != RADEON_LCD_GPIO_MASK)) {
+    if (radeon_output->pI2CBus && info->ddc2 && (DDCReg != RADEON_LCD_GPIO_MASK) && (DDCReg != RADEON_MDGPIO_EN_REG)) {
 	OUTREG(DDCReg, INREG(DDCReg) &
 	       (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
 
@@ -331,7 +332,7 @@ RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output)
 	    usleep(15000);
 	    if(*MonInfo)  break;
 	}
-    } else if (radeon_output->pI2CBus && info->ddc2 && DDCReg == RADEON_LCD_GPIO_MASK) {
+    } else if (radeon_output->pI2CBus && info->ddc2 && ((DDCReg == RADEON_LCD_GPIO_MASK) || (DDCReg == RADEON_MDGPIO_EN_REG))) {
          *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, radeon_output->pI2CBus);
     } else {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n");
@@ -669,9 +670,19 @@ static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     RADEONMonitorType MonType = MT_NONE;
 
-
     if (radeon_output->type == OUTPUT_LVDS) {
-	    MonType =  MT_LCD;
+#if defined(__powerpc__)
+	/* not sure on ppc, OF? */
+#else
+	if (!info->IsAtomBios) {
+	    /* see if the lid is closed -- only works at boot */
+	    if (INREG(RADEON_BIOS_6_SCRATCH) & 0x10)
+		MonType = MT_NONE;
+	    else
+		MonType = MT_LCD;
+	} else
+#endif
+	    MonType = MT_LCD;
     } else if (radeon_output->type == OUTPUT_DVI) {
 	if (radeon_output->TMDSType == TMDS_INT) {
 	    if (INREG(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE)
@@ -765,10 +776,14 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 	}
     }
 
-    /* update clock for LVDS always and DFP if RMX is active */
-    if ((radeon_output->MonType == MT_LCD) ||
-	((radeon_output->MonType == MT_DFP) &&
-	 (radeon_output->Flags & RADEON_USE_RMX))) {
+    /* update timing for LVDS and DFP if RMX is active */
+    if (radeon_output->Flags & RADEON_USE_RMX) {
+	adjusted_mode->CrtcHTotal     = mode->CrtcHDisplay + radeon_output->HBlank;
+	adjusted_mode->CrtcHSyncStart = mode->CrtcHDisplay + radeon_output->HOverPlus;
+	adjusted_mode->CrtcHSyncEnd   = mode->CrtcHSyncStart + radeon_output->HSyncWidth;
+	adjusted_mode->CrtcVTotal     = mode->CrtcVDisplay + radeon_output->VBlank;
+	adjusted_mode->CrtcVSyncStart = mode->CrtcVDisplay + radeon_output->VOverPlus;
+	adjusted_mode->CrtcVSyncEnd   = mode->CrtcVSyncStart + radeon_output->VSyncWidth;
 	adjusted_mode->Clock          = radeon_output->DotClock;
 	adjusted_mode->Flags          = radeon_output->Flags;
     }
@@ -1636,6 +1651,16 @@ radeon_detect(xf86OutputPtr output)
 	  break;
       }
 
+      if (!connected) {
+	  /* default to unknown for flaky chips/connectors
+	   * so we can get something on the screen
+	   */
+	  if (((radeon_output->type == OUTPUT_VGA || radeon_output->type == OUTPUT_DVI) &&
+	       radeon_output->DACType == DAC_TVDAC) ||
+	      (info->IsIGP && radeon_output->type == OUTPUT_DVI))
+	      return XF86OutputStatusUnknown;
+      }
+
       if (connected)
 	  return XF86OutputStatusConnected;
       else
@@ -1911,7 +1936,7 @@ radeon_create_resources(xf86OutputPtr output)
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "RRConfigureOutputProperty error, %d\n", err);
 	}
-	/* Set the current value of the backlight property */
+	/* Set the current value of the property */
 	switch (radeon_output->default_tvStd) {
 	case TV_STD_PAL:
 	    s = "pal";
@@ -2081,47 +2106,23 @@ radeon_set_property(xf86OutputPtr output, Atom property,
 	    return FALSE;
 	s = (char*)value->data;
 	if (value->size == strlen("ntsc") && !strncmp("ntsc", s, strlen("ntsc"))) {
-	    if (radeon_output->SupportedTVStds & TV_STD_NTSC) {
-		radeon_output->tvStd = TV_STD_NTSC;
-		return TRUE;
-	    } else {
-		return FALSE;
-	    }
+	    radeon_output->tvStd = TV_STD_NTSC;
+	    return TRUE;
 	} else if (value->size == strlen("pal") && !strncmp("pal", s, strlen("pal"))) {
-	    if (radeon_output->SupportedTVStds & TV_STD_PAL) {
-		radeon_output->tvStd = TV_STD_PAL;
-		return TRUE;
-	    } else {
-		return FALSE;
-	    }
+	    radeon_output->tvStd = TV_STD_PAL;
+	    return TRUE;
 	} else if (value->size == strlen("pal-m") && !strncmp("pal-m", s, strlen("pal-m"))) {
-	    if (radeon_output->SupportedTVStds & TV_STD_PAL_M) {
-		radeon_output->tvStd = TV_STD_PAL_M;
-		return TRUE;
-	    } else {
-		return FALSE;
-	    }
+	    radeon_output->tvStd = TV_STD_PAL_M;
+	    return TRUE;
 	} else if (value->size == strlen("pal-60") && !strncmp("pal-60", s, strlen("pal-60"))) {
-	    if (radeon_output->SupportedTVStds & TV_STD_PAL_60) {
-		radeon_output->tvStd = TV_STD_PAL_60;
-		return TRUE;
-	    } else {
-		return FALSE;
-	    }
+	    radeon_output->tvStd = TV_STD_PAL_60;
+	    return TRUE;
 	} else if (value->size == strlen("ntsc-j") && !strncmp("ntsc-j", s, strlen("ntsc-j"))) {
-	    if (radeon_output->SupportedTVStds & TV_STD_NTSC_J) {
-		radeon_output->tvStd = TV_STD_NTSC_J;
-		return TRUE;
-	    } else {
-		return FALSE;
-	    }
+	    radeon_output->tvStd = TV_STD_NTSC_J;
+	    return TRUE;
 	} else if (value->size == strlen("scart-pal") && !strncmp("scart-pal", s, strlen("scart-pal"))) {
-	    if (radeon_output->SupportedTVStds & TV_STD_SCART_PAL) {
-		radeon_output->tvStd = TV_STD_SCART_PAL;
-		return TRUE;
-	    } else {
-		return FALSE;
-	    }
+	    radeon_output->tvStd = TV_STD_SCART_PAL;
+	    return TRUE;
 	}
 	return FALSE;
     }
@@ -2206,6 +2207,10 @@ static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data)
         val = INREG(b->DriverPrivate.uval+4);
         *Clock = (val & (1<<13)) != 0;
         *data  = (val & (1<<12)) != 0;
+    } else if (b->DriverPrivate.uval == RADEON_MDGPIO_EN_REG) {
+        val = INREG(b->DriverPrivate.uval+4);
+        *Clock = (val & (1<<19)) != 0;
+        *data  = (val & (1<<18)) != 0;
     } else {
         val = INREG(b->DriverPrivate.uval);
         *Clock = (val & RADEON_GPIO_Y_1) != 0;
@@ -2225,6 +2230,11 @@ static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data)
         val |= (Clock ? 0:(1<<13));
         val |= (data ? 0:(1<<12));
         OUTREG(b->DriverPrivate.uval, val);
+    } else if (b->DriverPrivate.uval == RADEON_MDGPIO_EN_REG) {
+        val = INREG(b->DriverPrivate.uval) & (CARD32)~((1<<18) | (1<<19));
+        val |= (Clock ? 0:(1<<19));
+        val |= (data ? 0:(1<<18));
+        OUTREG(b->DriverPrivate.uval, val);
     } else {
         val = INREG(b->DriverPrivate.uval) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1);
         val |= (Clock ? 0:RADEON_GPIO_EN_1);
@@ -2430,6 +2440,15 @@ RADEONGetLVDSInfo (xf86OutputPtr output)
 	}
     }
 
+    info->LVDSBiosNativeMode = TRUE;
+    if (!xf86ReturnOptValBool(info->Options, OPTION_LVDS_BIOS_NATIVE_MODE, TRUE)) {
+	info->LVDSBiosNativeMode = FALSE;
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using CVT mode for LVDS\n");
+    } else {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using LVDS Native Mode\n");
+    }
+
+
     /* 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
@@ -2547,6 +2566,7 @@ void RADEONInitConnector(xf86OutputPtr output)
     case DDC_VGA  : DDCReg = RADEON_GPIO_VGA_DDC; break;
     case DDC_CRT2 : DDCReg = RADEON_GPIO_CRT2_DDC; break;
     case DDC_LCD  : DDCReg = RADEON_LCD_GPIO_MASK; break;
+    case DDC_GPIO : DDCReg = RADEON_MDGPIO_EN_REG; break;
     default: break;
     }
 
@@ -2791,6 +2811,78 @@ static void RADEONSetupGenericConnectors(ScrnInfoPtr pScrn)
 
 }
 
+#if defined(__powerpc__)
+
+/*
+ * Returns RADEONMacModel or 0 based on lines 'detected as' and 'machine'
+ * in /proc/cpuinfo (on Linux) */
+static RADEONMacModel RADEONDetectMacModel(ScrnInfoPtr pScrn)
+{
+    RADEONMacModel ret = 0;
+#ifdef __linux__
+    char cpuline[50];  /* 50 should be sufficient for our purposes */
+    FILE *f = fopen ("/proc/cpuinfo", "r");
+
+    if (f != NULL) {
+	while (fgets(cpuline, sizeof cpuline, f)) {
+	    if (!strncmp(cpuline, "machine", strlen ("machine"))) {
+		if (strstr(cpuline, "PowerBook5,6") ||
+		    strstr(cpuline, "PowerBook5,7") ||
+		    strstr(cpuline, "PowerBook5,8") ||
+		    strstr(cpuline, "PowerBook5,9")) {
+		    ret = RADEON_MAC_POWERBOOK_DL;
+		    break;
+		}
+
+		if (strstr(cpuline, "PowerMac10,1") ||
+		    strstr(cpuline, "PowerMac10,2")) {
+		    ret = RADEON_MAC_MINI;
+		    break;
+		}
+	    } else if (!strncmp(cpuline, "detected as", strlen("detected as"))) {
+                if (strstr(cpuline, "iBook")) {
+                    ret = RADEON_MAC_IBOOK;
+		    break;
+		} else if (strstr(cpuline, "PowerBook")) {
+		    ret = RADEON_MAC_POWERBOOK_DL;
+		    break;
+                }
+
+                /* No known PowerMac model detected */
+                break;
+            }
+        }
+
+	fclose (f);
+    } else
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Cannot detect PowerMac model because /proc/cpuinfo not "
+		   "readable.\n");
+
+#endif /* __linux */
+
+    if (ret) {
+	xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Detected %s.\n",
+		   ret == RADEON_MAC_POWERBOOK_DL ? "PowerBook with dual link DVI" :
+		   ret == RADEON_MAC_POWERBOOK ? "PowerBook with single link DVI" :
+		   ret == RADEON_MAC_IBOOK ? "iBook" :
+		   "Mac Mini");
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "If this is not correct, try Option \"MacModel\" and "
+		   "consider reporting to the\n");
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "xorg-driver-ati@lists.x.org mailing list"
+#ifdef __linux__
+		   " with the contents of /proc/cpuinfo"
+#endif
+		   ".\n");
+    }
+
+    return ret;
+}
+
+#endif /* __powerpc__ */
+
 /*
  * initialise the static data sos we don't have to re-do at randr change */
 Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
@@ -2816,9 +2908,8 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
     }
 
 #if defined(__powerpc__)
-    optstr = (char *)xf86GetOptValString(info->Options, OPTION_MAC_MODEL);
-
     info->MacModel = 0;
+    optstr = (char *)xf86GetOptValString(info->Options, OPTION_MAC_MODEL);
     if (optstr) {
 	if (!strncmp("ibook", optstr, strlen("ibook")))
 	    info->MacModel = RADEON_MAC_IBOOK;
@@ -2830,12 +2921,16 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 	    info->MacModel = RADEON_MAC_MINI;
 	else {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid Mac Model: %s\n", optstr);
-	    return FALSE;
 	}
+    }
+
+    if (!info->MacModel) {
+	info->MacModel = RADEONDetectMacModel(pScrn);
+    }
 
+    if (info->MacModel){
 	if (!RADEONSetupAppleConnectors(pScrn))
 	    RADEONSetupGenericConnectors(pScrn);
-
     } else
 #endif
     if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_CONNECTOR_TABLE, FALSE)) {
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index dbd50d7..66ece94 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -60,6 +60,7 @@ typedef enum
     DDC_VGA,
     DDC_CRT2,
     DDC_LCD,
+    DDC_GPIO,
 } RADEONDDCType;
 
 typedef enum