summaryrefslogtreecommitdiff
path: root/src/i830_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i830_driver.c')
-rw-r--r--src/i830_driver.c1472
1 files changed, 942 insertions, 530 deletions
diff --git a/src/i830_driver.c b/src/i830_driver.c
index afc2bd41..85d3d739 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -222,8 +222,8 @@ typedef enum {
OPTION_MONITOR_LAYOUT,
OPTION_CLONE,
OPTION_CLONE_REFRESH,
- OPTION_CHECKLID,
- OPTION_FLIP_PRIMARY
+ OPTION_CHECKDEVICES,
+ OPTION_FIXEDPIPE
} I830Opts;
static OptionInfoRec I830BIOSOptions[] = {
@@ -241,8 +241,8 @@ static OptionInfoRec I830BIOSOptions[] = {
{OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE},
{OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER, {0}, FALSE},
- {OPTION_CHECKLID, "CheckLid", OPTV_BOOLEAN, {0}, FALSE},
- {OPTION_FLIP_PRIMARY,"FlipPrimary", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_FIXEDPIPE, "FixedPipe", OPTV_ANYSTR, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
/* *INDENT-ON* */
@@ -255,7 +255,7 @@ static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack);
static Bool I830BIOSEnterVT(int scrnIndex, int flags);
static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode,
VbeCRTCInfoBlock *block);
-static CARD32 I830LidTimer(OsTimerPtr timer, CARD32 now, pointer arg);
+static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
static Bool SetPipeAccess(ScrnInfoPtr pScrn);
static Bool IsPrimary(ScrnInfoPtr pScrn);
@@ -397,7 +397,28 @@ Check5fStatus(ScrnInfoPtr pScrn, int func, int ax)
}
}
-#if 0
+static int
+GetToggleList(ScrnInfoPtr pScrn, int toggle)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetToggleList\n");
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x500;
+
+ pVbe->pInt10->bx |= toggle;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Toggle (%d) 0x%x\n", toggle, pVbe->pInt10->cx);
+ return pVbe->pInt10->cx & 0xffff;
+ }
+
+ return 0;
+}
+
static int
BitToRefresh(int bits)
{
@@ -410,7 +431,7 @@ BitToRefresh(int bits)
}
static int
-GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh)
+GetRefreshRate(ScrnInfoPtr pScrn, int mode, int *availRefresh)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
@@ -420,8 +441,6 @@ GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh)
if (mode & 0x100)
return 0;
- SetPipeAccess(pScrn);
-
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f05;
pVbe->pInt10->bx = (mode & 0xff) | 0x100;
@@ -434,7 +453,6 @@ GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh)
} else
return 0;
}
-#endif
struct panelid {
short hsize;
@@ -593,6 +611,23 @@ SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
}
static Bool
+SetPowerStatus(ScrnInfoPtr pScrn, int mode)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x0800 | mode;
+ pVbe->pInt10->cx = 0x0000;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool
GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
int devicesPipeA, int devicesPipeB, int *maxBandwidth,
int *bandwidthPipeA, int *bandwidthPipeB)
@@ -604,7 +639,7 @@ GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
/* Only 8-bit mode numbers are supported. */
if ((modePipeA & 0x100) || (modePipeB & 0x100))
- return 0;
+ return FALSE;
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f28;
@@ -709,9 +744,102 @@ GetDisplayDevices(ScrnInfoPtr pScrn)
}
}
-/* This is needed for SetDisplayDevices to work correctly on I915G
- * and possibly later Video BIOS builds around 3272 (but not sure here).
- * So enable for all chipsets now as it has no bad side effects, apart
+static int
+GetBIOSPipe(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ int pipe;
+
+ DPRINTF(PFX, "GetBIOSPipe:\n");
+
+ /* single pipe machines should always return Pipe A */
+ if (pI830->availablePipes == 1) return 0;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f1c;
+ pVbe->pInt10->bx = 0x100;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
+ if (pI830->newPipeSwitch) {
+ pipe = ((pVbe->pInt10->bx & 0x0001));
+ } else {
+ pipe = ((pVbe->pInt10->cx & 0x0100) >> 8);
+ }
+ return pipe;
+ }
+
+ /* failed, assume pipe A */
+ return 0;
+}
+
+static Bool
+SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+
+ DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
+
+ /* single pipe machines should always return TRUE */
+ if (pI830->availablePipes == 1) return TRUE;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f1c;
+ if (pI830->newPipeSwitch) {
+ pVbe->pInt10->bx = pipe;
+ pVbe->pInt10->cx = 0;
+ } else {
+ pVbe->pInt10->bx = 0x0;
+ pVbe->pInt10->cx = pipe << 8;
+ }
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+SetPipeAccess(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ /* Don't try messing with the pipe, unless we're dual head */
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->origPipe != pI830->pipe) {
+ if (!SetBIOSPipe(pScrn, pI830->pipe))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830Set640x480(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int m = 0x30; /* 640x480 8bpp */
+
+ switch (pScrn->depth) {
+ case 15:
+ m = 0x40;
+ break;
+ case 16:
+ m = 0x41;
+ break;
+ case 24:
+ m = 0x50;
+ break;
+ }
+ m |= (1 << 15) | (1 << 14);
+ return VBESetVBEMode(pI830->pVbe, m, NULL);
+}
+
+/* This is needed for SetDisplayDevices to work correctly on I915G.
+ * Enable for all chipsets now as it has no bad side effects, apart
* from slightly longer startup time.
*/
#define I915G_WORKAROUND
@@ -722,35 +850,28 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
I830Ptr pI830 = I830PTR(pScrn);
vbeInfoPtr pVbe = pI830->pVbe;
CARD32 temp;
+ int singlepipe = 0;
#ifdef I915G_WORKAROUND
- int getmode;
- int mode;
- switch (pScrn->depth) {
- case 8:
- mode = 0x30;
- break;
- case 15:
- mode = 0x40;
- break;
- case 16:
- mode = 0x41;
- break;
- case 24:
- mode = 0x50;
- break;
- default:
- mode = 0x30;
- break;
- }
- mode |= (1 << 15) | (1 << 14);
+ int getmode1;
+ Bool setmode = FALSE;
#endif
DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices);
+ if (!pI830->specifiedMonitor)
+ return TRUE;
+
#ifdef I915G_WORKAROUND
- if (pI830->bios_version >= 3272) {
- VBEGetVBEMode(pVbe, &getmode);
- I830VESASetVBEMode(pScrn, mode, NULL);
+ if (pI830->preinit)
+ setmode = TRUE;
+ if (pI830->leaving)
+ setmode = FALSE;
+ if (pI830->closing)
+ setmode = FALSE;
+
+ if (setmode) {
+ VBEGetVBEMode(pVbe, &getmode1);
+ I830Set640x480(pScrn);
}
#endif
@@ -762,40 +883,134 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
#ifdef I915G_WORKAROUND
- if (pI830->bios_version >= 3272)
- I830VESASetVBEMode(pScrn, getmode, NULL);
+ if (setmode) {
+ VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
+ }
#endif
+ pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
+ pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
+
return TRUE;
}
#ifdef I915G_WORKAROUND
- if (pI830->bios_version >= 3272)
- I830VESASetVBEMode(pScrn, getmode, NULL);
+ if (setmode)
+ VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
#endif
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "SetDisplayDevices call failed, writing config directly to SWF0.\n");
- temp = INREG(SWF0);
- OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
+ if (devices & 0xff) {
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x1;
+ pVbe->pInt10->cx = devices & 0xff;
- /* Now try to program the registers directly if the BIOS failed.
- * This currently only turns on the CRT, but should be made to handle
- * SDVO, TV, LFP etc. etc.
- */
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Successfully set display devices to 0x%x.\n",devices & 0xff);
+ singlepipe = devices & 0xff00; /* set alternate */
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set display devices to 0x%x.\n",devices & 0xff);
+ singlepipe = devices;
+ }
+ } else
+ singlepipe = devices;
+
+ if (singlepipe == devices && devices & 0xff00) {
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x1;
+ pVbe->pInt10->cx = devices & 0xff00;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Successfully set display devices to 0x%x.\n",devices & 0xff00);
+ singlepipe = devices & 0xff; /* set alternate */
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set display devices to 0x%x.\n",devices & 0xff00);
+ singlepipe = devices;
+ }
+ }
+
+ /* LVDS doesn't exist on these */
+ if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))
+ singlepipe &= ~(PIPE_LFP | (PIPE_LFP<<8));
+
+ if (pI830->availablePipes == 1)
+ singlepipe &= 0xFF;
+
+ /* Disable LVDS */
+ if (singlepipe & PIPE_LFP) {
+ /* LFP on PipeA is unlikely! */
+ OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
+ OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
+ while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+ /* Fix up LVDS */
+ OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300);
+ /* Enable LVDS */
+ OUTREG(0x61200, INREG(0x61200) | 0x80000000);
+ OUTREG(0x61204, INREG(0x61204) | 0x00000001);
+ while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Enabling LVDS directly. Pipe A.\n");
+ } else
+ if (singlepipe & (PIPE_LFP << 8)) {
+ OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
+ OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
+ while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+ /* Fix up LVDS */
+ OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300);
+ /* Enable LVDS */
+ OUTREG(0x61200, INREG(0x61200) | 0x80000000);
+ OUTREG(0x61204, INREG(0x61204) | 0x00000001);
+ while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Enabling LVDS directly. Pipe B.\n");
+ }
+ else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) {
+ if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) {
+ OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
+ OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
+ while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+ /* Fix up LVDS */
+ OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling LVDS directly.\n");
+ }
+ }
+
+ /* Now try to program the registers directly if the BIOS failed. */
temp = INREG(ADPA);
- temp &= ~0xc0000c00;
+ temp &= ~(ADPA_DAC_ENABLE | ADPA_PIPE_SELECT_MASK);
+ temp &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
/* Turn on ADPA */
- if (devices & PIPE_CRT) {
+ if (singlepipe & PIPE_CRT) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "BIOS call failed, turning ADPA on directly. Pipe A.\n");
- temp |= 0x80000000;
- }
- if ((devices >> 8) & PIPE_CRT) {
+ "Enabling ADPA directly. Pipe A.\n");
+ temp |= ADPA_DAC_ENABLE | ADPA_PIPE_A_SELECT;
+ OUTREG(ADPA, temp);
+ } else
+ if (singlepipe & (PIPE_CRT << 8)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "BIOS call failed, turning ADPA on directly. Pipe B.\n");
- temp |= 0xC0000000;
+ "Enabling ADPA directly. Pipe B.\n");
+ temp |= ADPA_DAC_ENABLE | ADPA_PIPE_B_SELECT;
+ OUTREG(ADPA, temp);
+ }
+ else {
+ if (!(devices & (PIPE_CRT | PIPE_CRT<<8))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling ADPA directly.\n");
+ temp |= ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE;
+ OUTREG(ADPA, temp);
+ }
}
- OUTREG(ADPA, temp);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,"Writing config directly to SWF0.\n");
+ temp = INREG(SWF0);
+ OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
if (GetDisplayDevices(pScrn) != devices) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -804,6 +1019,9 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
return FALSE;
}
+ pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
+ pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
+
return TRUE;
}
@@ -1480,95 +1698,97 @@ SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize)
}
}
-/*
- * Use the native method instead of the vgahw method. So far this is
- * only used for 8-bit mode.
- *
- * XXX Look into using the 10-bit gamma correction mode for 15/16/24 bit,
- * and see if a DirectColor visual can be offered.
- */
static void
I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
{
I830Ptr pI830;
- int i, index;
+ int i,j, index;
unsigned char r, g, b;
CARD32 val, temp;
+ int palreg;
+ int dspreg, dspbase;
DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
pI830 = I830PTR(pScrn);
if (pI830->pipe == 0) {
- /* It seems that an initial read is needed. */
- temp = INREG(PALETTE_A);
+ palreg = PALETTE_A;
+ dspreg = DSPACNTR;
+ dspbase = DSPABASE;
+ } else {
+ palreg = PALETTE_B;
+ dspreg = DSPBCNTR;
+ dspbase = DSPBBASE;
+ }
+
+ if (pScrn->depth > 8) {
+ OUTREG(dspreg, INREG(dspreg) | DISPPLANE_GAMMA_ENABLE);
+ } else {
+ OUTREG(dspreg, INREG(dspreg) & ~DISPPLANE_GAMMA_ENABLE);
+ }
+ OUTREG(dspbase, INREG(dspbase));
+
+ /* It seems that an initial read is needed. */
+ temp = INREG(palreg);
+
+ switch(pScrn->depth) {
+ case 15:
for (i = 0; i < numColors; i++) {
- index = indices[i];
- r = colors[index].red;
- g = colors[index].green;
- b = colors[index].blue;
- val = (r << 16) | (g << 8) | b;
- OUTREG(PALETTE_A + index * 4, val);
+ index = indices[i];
+ r = colors[index].red;
+ g = colors[index].green;
+ b = colors[index].blue;
+ for (j = 0; j < 8; j++) {
+ val = (r << 16) | (g << 8) | b;
+ OUTREG(palreg + index * 32 + (j * 4), val);
+ }
}
- }
- if (pI830->pipe == 1) {
- /* It seems that an initial read is needed. */
- temp = INREG(PALETTE_B);
+ break;
+ case 16:
for (i = 0; i < numColors; i++) {
+ index = indices[i / 2];
+ r = colors[index].red;
+ b = colors[index].blue;
+ index = indices[i];
+ g = colors[index].green;
+
+ val = (r << 16) | (g << 8) | b;
+ OUTREG(palreg + index * 16, val);
+ OUTREG(palreg + index * 16 + 4, val);
+ OUTREG(palreg + index * 16 + 8, val);
+ OUTREG(palreg + index * 16 + 12, val);
+
+ i++;
+ index = indices[i];
+ g = colors[index].green;
+
+ val = (r << 16) | (g << 8) | b;
+ OUTREG(palreg + index * 16, val);
+ OUTREG(palreg + index * 16 + 4, val);
+ OUTREG(palreg + index * 16 + 8, val);
+ OUTREG(palreg + index * 16 + 12, val);
+ }
+ break;
+ default:
+ for(i = 0; i < numColors; i++) {
index = indices[i];
r = colors[index].red;
g = colors[index].green;
b = colors[index].blue;
val = (r << 16) | (g << 8) | b;
- OUTREG(PALETTE_B + index * 4, val);
+ OUTREG(palreg + index * 4, val);
}
+ break;
}
}
-static void
-PreInitCleanup(ScrnInfoPtr pScrn)
-{
- I830Ptr pI830 = I830PTR(pScrn);
-
- if (IsPrimary(pScrn) && pI830->LpRing) {
- xfree(pI830->LpRing);
- pI830->LpRing = NULL;
- }
- if (IsPrimary(pScrn) && pI830->CursorMem) {
- xfree(pI830->CursorMem);
- pI830->CursorMem = NULL;
- }
- if (IsPrimary(pScrn) && pI830->CursorMemARGB) {
- xfree(pI830->CursorMemARGB);
- pI830->CursorMemARGB = NULL;
- }
- if (IsPrimary(pScrn) && pI830->OverlayMem) {
- xfree(pI830->OverlayMem);
- pI830->OverlayMem = NULL;
- }
- if (IsPrimary(pScrn) && pI830->overlayOn) {
- xfree(pI830->overlayOn);
- pI830->overlayOn = NULL;
- }
- if (!IsPrimary(pScrn) && pI830->entityPrivate)
- pI830->entityPrivate->pScrn_2 = NULL;
- RestoreBIOSMemSize(pScrn);
- if (pI830->swfSaved) {
- OUTREG(SWF0, pI830->saveSWF0);
- OUTREG(SWF4, pI830->saveSWF4);
- }
- if (pI830->MMIOBase)
- I830UnmapMMIO(pScrn);
- I830BIOSFreeRec(pScrn);
-}
-
static int
I830UseDDC(ScrnInfoPtr pScrn)
{
xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
struct detailed_monitor_section* detMon;
struct monitor_ranges *mon_range = NULL;
- Bool ret = FALSE;
int i;
if (!DDC) return 0;
@@ -1583,7 +1803,7 @@ I830UseDDC(ScrnInfoPtr pScrn)
if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 ||
mon_range->min_v == 0 || mon_range->max_v == 0)
- return FALSE; /* bad ddc */
+ return 0; /* bad ddc */
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using detected DDC timings\n");
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tHorizSync %d-%d\n",
@@ -1597,7 +1817,7 @@ I830UseDDC(ScrnInfoPtr pScrn)
pScrn->monitor->hsync[i].lo ||
(1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h <
pScrn->monitor->hsync[i].hi) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"config file hsync range %g-%gkHz not within DDC "
"hsync range %d-%dkHz\n",
pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi,
@@ -1614,7 +1834,7 @@ I830UseDDC(ScrnInfoPtr pScrn)
pScrn->monitor->vrefresh[i].lo ||
(1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v <
pScrn->monitor->vrefresh[i].hi) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"config file vrefresh range %g-%gHz not within DDC "
"vrefresh range %d-%dHz\n",
pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi,
@@ -1628,75 +1848,43 @@ I830UseDDC(ScrnInfoPtr pScrn)
return mon_range->max_clock;
}
-static int
-GetBIOSPipe(ScrnInfoPtr pScrn)
+static void
+PreInitCleanup(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
- vbeInfoPtr pVbe = pI830->pVbe;
- int pipe;
-
- DPRINTF(PFX, "GetBIOSPipe:\n");
-
- /* single pipe machines should always return Pipe A */
- if (pI830->availablePipes == 1) return 0;
- pVbe->pInt10->num = 0x10;
- pVbe->pInt10->ax = 0x5f1c;
- pVbe->pInt10->bx = 0x100;
-
- xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
- if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
- if (pI830->newPipeSwitch) {
- pipe = ((pVbe->pInt10->bx & 0x0001));
- } else {
- pipe = ((pVbe->pInt10->cx & 0x0100) >> 8);
- }
- return pipe;
+ if (IsPrimary(pScrn))
+ pI830->entityPrivate->pScrn_1 = NULL;
+ if (IsPrimary(pScrn) && pI830->LpRing) {
+ xfree(pI830->LpRing);
+ pI830->LpRing = NULL;
}
-
- return -1;
-}
-
-static Bool
-SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
-{
- I830Ptr pI830 = I830PTR(pScrn);
- vbeInfoPtr pVbe = pI830->pVbe;
-
- DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
-
- /* single pipe machines should always return TRUE */
- if (pI830->availablePipes == 1) return TRUE;
-
- pVbe->pInt10->num = 0x10;
- pVbe->pInt10->ax = 0x5f1c;
- if (pI830->newPipeSwitch) {
- pVbe->pInt10->bx = pipe;
- pVbe->pInt10->cx = 0;
- } else {
- pVbe->pInt10->bx = 0x0;
- pVbe->pInt10->cx = pipe << 8;
+ if (IsPrimary(pScrn) && pI830->CursorMem) {
+ xfree(pI830->CursorMem);
+ pI830->CursorMem = NULL;
}
-
- xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
- if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax))
- return TRUE;
-
- return FALSE;
-}
-
-static Bool
-SetPipeAccess(ScrnInfoPtr pScrn)
-{
- I830Ptr pI830 = I830PTR(pScrn);
-
- /* Don't try messing with the pipe, unless we're dual head */
- if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
- if (!SetBIOSPipe(pScrn, pI830->pipe))
- return FALSE;
+ if (IsPrimary(pScrn) && pI830->CursorMemARGB) {
+ xfree(pI830->CursorMemARGB);
+ pI830->CursorMemARGB = NULL;
}
-
- return TRUE;
+ if (IsPrimary(pScrn) && pI830->OverlayMem) {
+ xfree(pI830->OverlayMem);
+ pI830->OverlayMem = NULL;
+ }
+ if (IsPrimary(pScrn) && pI830->overlayOn) {
+ xfree(pI830->overlayOn);
+ pI830->overlayOn = NULL;
+ }
+ if (!IsPrimary(pScrn) && pI830->entityPrivate)
+ pI830->entityPrivate->pScrn_2 = NULL;
+ RestoreBIOSMemSize(pScrn);
+ if (pI830->swfSaved) {
+ OUTREG(SWF0, pI830->saveSWF0);
+ OUTREG(SWF4, pI830->saveSWF4);
+ }
+ if (pI830->MMIOBase)
+ I830UnmapMMIO(pScrn);
+ I830BIOSFreeRec(pScrn);
}
static Bool
@@ -1728,7 +1916,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
int DDCclock = 0;
char *s;
DisplayModePtr p, pMon;
- pointer pDDCModule, pVBEModule;
+ pointer pDDCModule = NULL, pVBEModule = NULL;
Bool enable;
const char *chipname;
unsigned int ver;
@@ -2096,8 +2284,19 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
}
#endif
+ pI830->fixedPipe = -1;
+ if ((s = xf86GetOptValString(pI830->Options, OPTION_FIXEDPIPE)) &&
+ IsPrimary(pScrn)) {
+
+ if (strstr(s, "A") || strstr(s, "a") || strstr(s, "0"))
+ pI830->fixedPipe = 0;
+ else if (strstr(s, "B") || strstr(s, "b") || strstr(s, "1"))
+ pI830->fixedPipe = 1;
+ }
+
pI830->MonType1 = PIPE_NONE;
pI830->MonType2 = PIPE_NONE;
+ pI830->specifiedMonitor = FALSE;
if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
IsPrimary(pScrn)) {
@@ -2177,6 +2376,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
"Monitor 1 and 2 cannot be type NONE\n");
return FALSE;
}
+
+ pI830->specifiedMonitor = TRUE;
}
if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
@@ -2193,22 +2394,24 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Clone Mode\n");
- pI830->CloneRefresh = 60; /* default to 60Hz */
- if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
+ pI830->Clone = TRUE;
+ }
+
+ pI830->CloneRefresh = 60; /* default to 60Hz */
+ if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
&(pI830->CloneRefresh))) {
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Clone Monitor Refresh Rate %d\n",
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Clone Monitor Refresh Rate %d\n",
pI830->CloneRefresh);
- }
- /* See above i830refreshes on why 120Hz is commented out */
- if (pI830->CloneRefresh < 60 || pI830->CloneRefresh > 85 /* 120 */) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad Clone Refresh Rate\n");
- PreInitCleanup(pScrn);
- return FALSE;
- }
- pI830->Clone = TRUE;
}
- if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) {
+ /* See above i830refreshes on why 120Hz is commented out */
+ if (pI830->CloneRefresh < 60 || pI830->CloneRefresh > 85 /* 120 */) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad Clone Refresh Rate\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) {
if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout "
"defined for use in a DualHead or Clone setup.\n");
@@ -2228,22 +2431,22 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
* Let's setup the mobile systems to check the lid status
*/
if (IS_MOBILE(pI830)) {
- pI830->checkLid = TRUE;
+ pI830->checkDevices = TRUE;
- if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKLID, TRUE)) {
- pI830->checkLid = FALSE;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status disabled\n");
+ if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKDEVICES, TRUE)) {
+ pI830->checkDevices = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
} else
if (pI830->entityPrivate && !IsPrimary(pScrn) &&
- !I830PTR(pI830->entityPrivate->pScrn_1)->checkLid) {
+ !I830PTR(pI830->entityPrivate->pScrn_1)->checkDevices) {
/* If checklid is off, on the primary head, then
* turn it off on the secondary*/
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status disabled\n");
- pI830->checkLid = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
+ pI830->checkDevices = FALSE;
} else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status enabled\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays enabled\n");
} else
- pI830->checkLid = FALSE;
+ pI830->checkDevices = FALSE;
/*
* The "VideoRam" config file parameter specifies the total amount of
@@ -2446,8 +2649,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version);
- /* BIOS build 3062 changed the pipe switching functionality */
+ if (IS_I915G(pI830) || IS_I915GM(pI830))
+ pI830->newPipeSwitch = TRUE;
+ else
if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) {
+ /* BIOS build 3062 changed the pipe switching functionality */
pI830->newPipeSwitch = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n");
} else
@@ -2481,18 +2687,29 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
pI830->savedDevices = GetDisplayDevices(pScrn);
if (IsPrimary(pScrn)) {
- pI830->pipe = GetBIOSPipe(pScrn);
-
- if (xf86ReturnOptValBool(pI830->Options, OPTION_FLIP_PRIMARY, FALSE)) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Primary flipping enabled\n");
- pI830->pipe = !pI830->pipe;
+ pI830->pipe = pI830->origPipe = GetBIOSPipe(pScrn);
+
+ /* Override */
+ if (pI830->fixedPipe != -1) {
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
+ pI830->pipe = pI830->fixedPipe;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Fixed Pipe setting primary to pipe %s.\n",
+ pI830->fixedPipe ? "B" : "A");
+ }
}
-
+
/* If the monitors aren't setup, read from the current config */
- if (pI830->MonType1 == PIPE_NONE)
+ if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) {
pI830->MonType1 = pI830->savedDevices & 0xff;
- if (pI830->MonType2 == PIPE_NONE)
pI830->MonType2 = (pI830->savedDevices & 0xff00) >> 8;
+ } else {
+ /* Here, we've switched pipes from our primary */
+ if (pI830->MonType1 == PIPE_NONE && pI830->pipe == 0)
+ pI830->pipe = 1;
+ if (pI830->MonType2 == PIPE_NONE && pI830->pipe == 1)
+ pI830->pipe = 0;
+ }
pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
@@ -2504,15 +2721,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
pI830->operatingDevices = pI830->MonType1;
else
pI830->operatingDevices = pI830->MonType2 << 8;
-
- if (pI830->operatingDevices & 0xFF00)
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Primary Pipe is %s, switching off second monitor (0x%x)\n",
- pI830->pipe ? "B" : "A", pI830->operatingDevices);
}
+
+ if (pI830->pipe != pI830->origPipe)
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Primary Pipe has been switched from original pipe (%s to %s)\n",
+ pI830->origPipe ? "B" : "A", pI830->pipe ? "B" : "A");
} else {
I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
pI830->operatingDevices = pI8301->operatingDevices;
+ pI830->pipe = !pI8301->pipe;
+ pI830->MonType1 = pI8301->MonType1;
+ pI830->MonType2 = pI8301->MonType2;
}
/* Buggy BIOS 3066 is known to cause this, so turn this off */
@@ -2540,26 +2760,25 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
- if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ if (IsPrimary(pScrn)) {
+ if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to switch to monitor configuration (0x%x)\n",
pI830->operatingDevices);
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Please check the devices specified in your MonitorLayout\n");
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"is configured correctly.\n");
- PreInitCleanup(pScrn);
- return FALSE;
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
}
PrintDisplayDeviceInfo(pScrn);
if (xf86IsEntityShared(pScrn->entityList[0])) {
if (!IsPrimary(pScrn)) {
- I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
-
pI830Ent->pScrn_2 = pScrn;
- pI830->pipe = !pI8301->pipe;
/* This could be made to work with a little more fiddling */
pI830->directRenderingDisabled = TRUE;
@@ -2604,7 +2823,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
pI830->CursorNeedsPhysical = FALSE;
/* Force ring buffer to be in low memory for the 845G and later. */
+#if 0
if (IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I915GM(pI830))
+#endif
pI830->NeedRingBufferLow = TRUE;
/*
@@ -2645,24 +2866,16 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
SetPipeAccess(pScrn);
- if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
- PreInitCleanup(pScrn);
- return FALSE;
- }
-
/* Check we have an LFP connected, before trying to
* read PanelID information. */
if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
- (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
+ (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) )
vbeDoPanelID(pI830->pVbe);
- }
- /* If we managed to get PanelID, then try EDID too, and if we get that
- * it'll override the PanelID information above */
- if (!pI830->vesa->monitor &&
- (pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule)) != NULL) {
- xf86PrintEDID(pI830->vesa->monitor);
- }
+ pDDCModule = xf86LoadSubModule(pScrn, "ddc");
+
+ pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
+
if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL)
xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
xf86UnloadSubModule(pDDCModule);
@@ -2772,11 +2985,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
/*
* Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
- * functions. For that reason it's important to set only
- * V_MODETYPE_VGA in the flags.
+ * functions.
*/
- pScrn->modePool = i830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo,
- V_MODETYPE_VGA);
+ pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
if (!pScrn->modePool) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -3001,7 +3212,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
#endif
SetPipeAccess(pScrn);
- i830PrintModes(pScrn);
+ I830PrintModes(pScrn);
if (!pI830->vesa->useDefaultRefresh) {
/*
@@ -3012,7 +3223,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
* if there are no non-CRT devices attached.
*/
SetPipeAccess(pScrn);
- i830SetModeParameters(pScrn, pI830->pVbe);
+ I830SetModeParameters(pScrn, pI830->pVbe);
}
/* PreInit shouldn't leave any state changes, so restore this. */
@@ -3051,11 +3262,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
}
- if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Failed to switch to saved display devices, continuing.\n");
- }
-
I830UnmapMMIO(pScrn);
/* We won't be using the VGA access after the probe. */
@@ -3064,7 +3270,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr);
VBEFreeVBEInfo(pI830->vbeInfo);
+ pI830->vbeInfo = NULL;
vbeFree(pI830->pVbe);
+ pI830->pVbe = NULL;
/* Use the VBE mode restore workaround by default. */
pI830->vbeRestoreWorkaround = TRUE;
@@ -3283,12 +3491,16 @@ SaveHWState(ScrnInfoPtr pScrn)
DPRINTF(PFX, "SaveHWState\n");
- SetPipeAccess(pScrn);
+ if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
+ SetBIOSPipe(pScrn, pI830->origPipe);
+ else
+ SetPipeAccess(pScrn);
pVesa = pI830->vesa;
/* Make sure we save at least this information in case of failure. */
VBEGetVBEMode(pVbe, &pVesa->stateMode);
+ pVesa->stateRefresh = GetRefreshRate(pScrn, pVesa->stateMode, NULL);
modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode);
pVesa->savedScanlinePitch = 0;
if (modeInfo) {
@@ -3354,6 +3566,11 @@ RestoreHWState(ScrnInfoPtr pScrn)
DPRINTF(PFX, "RestoreHWState\n");
+ if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
+ SetBIOSPipe(pScrn, pI830->origPipe);
+ else
+ SetPipeAccess(pScrn);
+
pVesa = pI830->vesa;
/*
@@ -3361,26 +3578,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
* Temporarily program a 640x480 mode before switching back to
* text mode.
*/
- if (pVesa->useDefaultRefresh) {
- int mode = 0;
-
- switch (pScrn->depth) {
- case 8:
- mode = 0x30;
- break;
- case 15:
- mode = 0x40;
- break;
- case 16:
- mode = 0x41;
- break;
- case 24:
- mode = 0x50;
- break;
- }
- mode |= (1 << 15) | (1 << 14);
- I830VESASetVBEMode(pScrn, mode, NULL);
- }
+ if (pVesa->useDefaultRefresh)
+ I830Set640x480(pScrn);
if (pVesa->state && pVesa->stateSize) {
CARD16 imr = INREG16(IMR);
@@ -3413,6 +3612,9 @@ RestoreHWState(ScrnInfoPtr pScrn)
"Setting the original video mode instead of restoring\n\t"
"the saved state\n");
I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
+ if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) {
+ SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh);
+ }
}
if (pVesa->savedScanlinePitch)
VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
@@ -3424,13 +3626,10 @@ RestoreHWState(ScrnInfoPtr pScrn)
vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
vgaHWLock(hwp);
+
return TRUE;
}
-#ifndef USE_VBE
-#define USE_VBE 1
-#endif
-
static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh)
{
I830Ptr pI830 = I830PTR(pScrn);
@@ -3466,8 +3665,7 @@ static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock
#endif
if (clock)
block->PixelClock = clock;
- block->RefreshRate = ((double)(block->PixelClock) /
- (double)(p->HTotal * p->VTotal)) * 100;
+ block->RefreshRate = RefreshRate;
return;
}
}
@@ -3477,62 +3675,137 @@ static Bool
I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
{
I830Ptr pI830 = I830PTR(pScrn);
+ Bool ret = FALSE;
+ int Mon;
DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
- if (pI830->Clone && !pI830->preinit) {
+ if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay &&
+ !pI830->preinit && !pI830->closing) {
VbeCRTCInfoBlock newblock;
- int Mon;
+ int newmode = mode;
- if (pI830->pipe == 0)
+ if (pI830->pipe == 1)
Mon = pI830->MonType1;
else
Mon = pI830->MonType2;
SetBIOSPipe(pScrn, !pI830->pipe);
- /* The reason for this code is if we've not got a CRT on this pipe, then
- * make sure we're using a 60Hz refresh */
+ /* Now recheck refresh operations we can use */
+ pI830->useExtendedRefresh = FALSE;
+ pI830->vesa->useDefaultRefresh = FALSE;
+
+ if (Mon != PIPE_CRT) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "A non-CRT device is attached to Clone pipe %c.\n"
+ "\tNo refresh rate overrides will be attempted (0x%x).\n",
+ PIPE_NAME(!pI830->pipe), newmode);
+ pI830->vesa->useDefaultRefresh = TRUE;
+ }
+ /*
+ * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
+ * would need to be set to FALSE for those cases.
+ */
+ if (!pI830->vesa->useDefaultRefresh)
+ pI830->useExtendedRefresh = TRUE;
+
+ newmode |= 1 << 11;
+ if (pI830->vesa->useDefaultRefresh)
+ newmode &= ~(1 << 11);
+
if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
- (mode & (1 << 11)) && block) {
- /* we'll call 5F05 to set the refresh later.... */
- if (Mon != PIPE_CRT)
- VBESetVBEMode(pI830->pVbe, mode, NULL);
- else
- VBESetVBEMode(pI830->pVbe, mode, block);
- } else {
- if (Mon != PIPE_CRT)
- /* Set clone head to 60Hz because we ain't got a CRT on it */
- I830SetCloneVBERefresh(pScrn, mode, &newblock, 6000);
- else
- /* Set clone head to specified clone refresh rate */
- I830SetCloneVBERefresh(pScrn, mode, &newblock, pI830->CloneRefresh * 100);
- if (newblock.RefreshRate == 0)
+ (newmode & (1 << 11))) {
+ if (!SetRefreshRate(pScrn, newmode, 60)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS call 0x5f05 not supported on Clone Head, "
+ "setting refresh with VBE 3 method.\n");
+ pI830->useExtendedRefresh = FALSE;
+ }
+ }
+
+ if (!pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
+ I830SetCloneVBERefresh(pScrn, newmode, &newblock, pI830->CloneRefresh * 100);
+
+ if (!VBESetVBEMode(pI830->pVbe, newmode, &newblock)) {
+ if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set mode for Clone head.\n");
+ else
+ newmode &= ~(1 << 11);
+ }
+ } else {
+ if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set mode for Clone head.\n");
+ }
+
+ if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
+ (newmode & (1 << 11))) {
+ if (!SetRefreshRate(pScrn, newmode, pI830->CloneRefresh))
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Failed to setup clone head mode resolution and refresh.\n");
+ "Failed to set refresh rate to %dHz on Clone head.\n",
+ pI830->CloneRefresh);
else
- VBESetVBEMode(pI830->pVbe, mode, &newblock);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Set refresh rate to %dHz on Clone head.\n",
+ pI830->CloneRefresh);
}
+ SetPipeAccess(pScrn);
}
- SetPipeAccess(pScrn);
+ if (pI830->pipe == 0)
+ Mon = pI830->MonType1;
+ else
+ Mon = pI830->MonType2;
-#if USE_VBE
- return VBESetVBEMode(pI830->pVbe, mode, block);
-#else
- {
- vbeInfoPtr pVbe = pI830->pVbe;
- pVbe->pInt10->num = 0x10;
- pVbe->pInt10->ax = 0x80 | (mode & 0x7f);
- xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
- pVbe->pInt10->ax = 0x0f00;
- xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
- if ((pVbe->pInt10->ax & 0x7f) == (mode & 0x7f))
- return TRUE;
- else
- return FALSE;
+ /* Now recheck refresh operations we can use */
+ pI830->useExtendedRefresh = FALSE;
+ pI830->vesa->useDefaultRefresh = FALSE;
+
+ if (Mon != PIPE_CRT)
+ pI830->vesa->useDefaultRefresh = TRUE;
+
+ mode |= 1 << 11;
+ if (pI830->vesa->useDefaultRefresh)
+ mode &= ~(1 << 11);
+ /*
+ * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
+ * would need to be set to FALSE for those cases.
+ */
+ if (!pI830->vesa->useDefaultRefresh)
+ pI830->useExtendedRefresh = TRUE;
+
+
+ if (!SetRefreshRate(pScrn, mode, 60)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS call 0x5f05 not supported, "
+ "setting refresh with VBE 3 method.\n");
+ pI830->useExtendedRefresh = FALSE;
}
-#endif
+
+ if (!pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && block) {
+ ret = VBESetVBEMode(pI830->pVbe, mode, block);
+ if (!ret)
+ ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
+ } else {
+ ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
+ }
+
+ /* Might as well bail now if we've failed */
+ if (!ret) return FALSE;
+
+ if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
+ (mode & (1 << 11)) && block) {
+ if (!SetRefreshRate(pScrn, mode, block->RefreshRate / 100)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set refresh rate to %dHz.\n",
+ block->RefreshRate / 100);
+ pI830->useExtendedRefresh = FALSE;
+ }
+ }
+
+ return ret;
}
static Bool
@@ -3561,21 +3834,6 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
}
#endif
- /*
- * Do this early to find out if we can support it or not....
- * Test if the extendedRefresh BIOS function is supported.
- */
- if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
- (mode & (1 << 11)) && data && data->data && data->block) {
- SetPipeAccess(pScrn);
- if (!SetRefreshRate(pScrn, mode, 60)) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "BIOS call 0x5f05 not supported, "
- "setting refresh with VBE 3 method.\n");
- pI830->useExtendedRefresh = FALSE;
- }
- }
-
if (pI830->Clone) {
pI830->CloneHDisplay = pMode->HDisplay;
pI830->CloneVDisplay = pMode->VDisplay;
@@ -3593,20 +3851,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
if (pI830->vesa->useDefaultRefresh)
mode &= ~(1 << 11);
+ SetPipeAccess(pScrn);
+
if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
- if ((data->block && (mode & (1 << 11))) &&
- I830VESASetVBEMode(pScrn, (mode & ~(1 << 11)), NULL) == TRUE) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Set VBE Mode rejected this modeline.\n\t"
- "Trying standard mode instead!\n");
- DPRINTF(PFX, "OOPS!\n");
- xfree(data->block);
- data->block = NULL;
- data->mode &= ~(1 << 11);
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
- return FALSE;
- }
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
+ return FALSE;
}
/*
@@ -3632,49 +3881,6 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
VBESetGetDACPaletteFormat(pVbe, 8);
}
- /*
- * When it's OK to set better than default refresh rates, set them here.
- */
- if (pI830->Clone) {
- int Mon;
- if (pI830->pipe == 0)
- Mon = pI830->MonType1;
- else
- Mon = pI830->MonType2;
- SetBIOSPipe(pScrn, !pI830->pipe);
- if (pI830->CloneRefresh && (Mon == PIPE_CRT)) {
- if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
- (mode & (1 << 11)) && data && data->data && data->block) {
- refresh = SetRefreshRate(pScrn, mode, pI830->CloneRefresh);
- if (!refresh)
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Failed to set refresh rate to %dHz on Clone head.\n",
- pI830->CloneRefresh);
- else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Set refresh rate to %dHz on Clone head.\n",
- pI830->CloneRefresh);
- } else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Will use VBE3 method to set refresh on Clone head.\n");
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Not attempting to override default refresh on non-CRT clone head\n");
- }
- }
-
- if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
- (mode & (1 << 11)) && data && data->data && data->block) {
- SetPipeAccess(pScrn);
- refresh = SetRefreshRate(pScrn, mode, data->block->RefreshRate / 100);
- if (!refresh) {
- refresh = 60;
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Failed to set refresh rate to %dHz.\n",
- data->block->RefreshRate / 100);
- }
- }
-
/* XXX Fix plane A with pipe A, and plane B with pipe B. */
planeA = INREG(DSPACNTR);
planeB = INREG(DSPBCNTR);
@@ -3690,36 +3896,18 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
pI830->planeEnabled[1] ? "enabled" : "disabled",
planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
- if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
+ if (pI830->operatingDevices & 0xff) {
pI830->planeEnabled[0] = 1;
- pI830->pipeEnabled[0] = 1;
- pI830->planeEnabled[1] = 1;
- pI830->pipeEnabled[1] = 1;
+ } else {
+ pI830->planeEnabled[0] = 0;
}
- /*
- * Sometimes it seems that no display planes are enabled at this point.
- * For mobile platforms pick the plane(s) connected to enabled pipes.
- * For others choose plane A.
- */
- if (!pI830->planeEnabled[0] && !pI830->planeEnabled[1]) {
- if (pI830->availablePipes == 2) {
- if ((pI830->pipeEnabled[0] &&
- ((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
- (pI830->pipeEnabled[1] &&
- ((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
- pI830->planeEnabled[0] = TRUE;
- }
- if ((pI830->pipeEnabled[0] &&
- ((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
- (pI830->pipeEnabled[1] &&
- ((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
- pI830->planeEnabled[1] = TRUE;
- }
- } else {
- pI830->planeEnabled[0] = TRUE;
- }
+ if (pI830->operatingDevices & 0xff00) {
+ pI830->planeEnabled[1] = 1;
+ } else {
+ pI830->planeEnabled[1] = 0;
}
+
if (pI830->planeEnabled[0]) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
planeA |= DISPLAY_PLANE_ENABLE;
@@ -3763,6 +3951,8 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp);
}
+
+
if (xf86IsEntityShared(pScrn->entityList[0])) {
/* Clean this up !! */
if (IsPrimary(pScrn)) {
@@ -3941,6 +4131,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
}
}
+#if 0
{
int ret;
@@ -3950,6 +4141,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
"LFP compensation mode: 0x%x\n", ret);
}
}
+#endif
#if MODESWITCH_RESET_STATE
ResetState(pScrn, TRUE);
@@ -4268,26 +4460,22 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
* If we're changing the BIOS's view of the video memory size, do that
* first, then re-initialise the VBE information.
*/
+ if (pI830->pVbe)
+ vbeFree(pI830->pVbe);
pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
if (!pI830->pVbe)
return FALSE;
+ if (pI830->vbeInfo)
+ VBEFreeVBEInfo(pI830->vbeInfo);
pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
miClearVisualTypes();
- if (!xf86SetDefaultVisual(pScrn, -1))
- return FALSE;
- if (pScrn->bitsPerPixel > 8) {
- if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
- pScrn->rgbBits, TrueColor))
- return FALSE;
- } else {
- if (!miSetVisualTypes(pScrn->depth,
+ if (!miSetVisualTypes(pScrn->depth,
miGetDefaultVisualMask(pScrn->depth),
pScrn->rgbBits, pScrn->defaultVisual))
return FALSE;
- }
if (!miSetPixmapDepths())
return FALSE;
@@ -4366,7 +4554,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
*/
if (pI830->directRenderingEnabled) {
- if (pI830->noAccel || pI830->SWCursor || pI830->StolenOnly) {
+ if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && IsPrimary(pScrn))) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
"needs HW cursor, 2D accel and AGPGART.\n");
pI830->directRenderingEnabled = FALSE;
@@ -4513,7 +4701,8 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n");
if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, 0,
- CMAP_RELOAD_ON_MODE_SWITCH)) {
+ CMAP_RELOAD_ON_MODE_SWITCH |
+ CMAP_PALETTED_TRUECOLOR)) {
return FALSE;
}
@@ -4551,9 +4740,6 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI830->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = I830BIOSCloseScreen;
- if (pI830->checkLid)
- pI830->lidTimer = TimerSet(NULL, 0, 1000, I830LidTimer, pScrn);
-
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
@@ -4665,12 +4851,24 @@ I830BIOSLeaveVT(int scrnIndex, int flags)
DPRINTF(PFX, "Leave VT\n");
+ pI830->leaving = TRUE;
+
+ if (pI830->devicesTimer)
+ TimerCancel(pI830->devicesTimer);
+ pI830->devicesTimer = NULL;
+
+ if (pI830->Clone) {
+ /* Ensure we don't try and setup modes on a clone head */
+ pI830->CloneHDisplay = 0;
+ pI830->CloneVDisplay = 0;
+ }
+
if (!IsPrimary(pScrn)) {
I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
if (!pI8301->GttBound) {
return;
}
- }
+ }
#ifdef XF86DRI
if (pI830->directRenderingOpen) {
@@ -4687,7 +4885,22 @@ I830BIOSLeaveVT(int scrnIndex, int flags)
SaveHWOperatingState(pScrn);
#endif
+ if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
+ pI830->CursorInfoRec->HideCursor(pScrn);
+
ResetState(pScrn, TRUE);
+
+ if (IsPrimary(pScrn)) {
+ if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to switch back to original display devices (0x%x)\n",
+ pI830->savedDevices);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Successfully set original devices\n");
+ }
+ }
+
RestoreHWState(pScrn);
RestoreBIOSMemSize(pScrn);
if (IsPrimary(pScrn))
@@ -4695,14 +4908,15 @@ I830BIOSLeaveVT(int scrnIndex, int flags)
if (pI830->AccelInfoRec)
pI830->AccelInfoRec->NeedToSync = FALSE;
+ /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
if (IsPrimary(pScrn)) {
if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Failed to switch back to original display devices (0x%x)\n",
+ "Failed to switch back to original display devices (0x%x) (2)\n",
pI830->savedDevices);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Successfully set original devices\n");
+ "Successfully set original devices (2)\n");
}
}
}
@@ -4711,10 +4925,9 @@ static Bool
I830DetectMonitorChange(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
- pointer pDDCModule;
+ pointer pDDCModule = NULL;
DisplayModePtr p, pMon;
- xf86MonPtr DDC;
- int i, memsize;
+ int memsize;
int DDCclock = 0;
int displayWidth = pScrn->displayWidth;
int curHDisplay = pScrn->currentMode->HDisplay;
@@ -4725,12 +4938,10 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
SetPipeAccess(pScrn);
/* Re-read EDID */
- if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL)
- return FALSE;
+ pDDCModule = xf86LoadSubModule(pScrn, "ddc");
if (pI830->vesa->monitor)
xfree(pI830->vesa->monitor);
- if ((pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule)) != NULL)
- xf86PrintEDID(pI830->vesa->monitor);
+ pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
xf86UnloadSubModule(pDDCModule);
if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL)
xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
@@ -4745,11 +4956,9 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
/*
* Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
- * functions. For that reason it's important to set only
- * V_MODETYPE_VGA in the flags.
+ * functions.
*/
- pScrn->modePool = i830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo,
- V_MODETYPE_VGA);
+ pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
if (!pScrn->modePool) {
/* This is bad, which would cause the Xserver to exit, maybe
@@ -4774,6 +4983,7 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
pScrn->display->virtualY,
memsize, LOOKUP_BEST_REFRESH);
+if (DDCclock > 0) {
p = pScrn->modes;
if (p == NULL)
return FALSE;
@@ -4799,11 +5009,15 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
}
p = p->next;
} while (p != NULL && p != pScrn->modes);
+}
pScrn->displayWidth = displayWidth; /* restore old displayWidth */
xf86PruneDriverModes(pScrn);
- i830PrintModes(pScrn);
+ I830PrintModes(pScrn);
+
+ if (!pI830->vesa->useDefaultRefresh)
+ I830SetModeParameters(pScrn, pI830->pVbe);
/* Now check if the previously used mode is o.k. for the current monitor.
* This allows VT switching to continue happily when not disconnecting
@@ -4849,6 +5063,32 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn)
return TRUE;
}
+
+Bool
+I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ Bool ret = TRUE;
+
+ if (pI830->Clone) {
+ if (pI830->pipeDisplaySize[0].x2 != 0) {
+ if (x > pI830->pipeDisplaySize[0].x2 ||
+ y > pI830->pipeDisplaySize[0].y2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
+ return FALSE;
+ }
+ }
+ if (pI830->pipeDisplaySize[1].x2 != 0) {
+ if (x > pI830->pipeDisplaySize[1].x2 ||
+ y > pI830->pipeDisplaySize[1].y2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
+ return FALSE;
+ }
+ }
+ }
+
+ return ret;
+}
/*
* This gets called when gaining control of the VT, and from ScreenInit().
@@ -4861,19 +5101,34 @@ I830BIOSEnterVT(int scrnIndex, int flags)
DPRINTF(PFX, "Enter VT\n");
+ /*
+ * Only save state once per server generation since that's what most
+ * drivers do. Could change this to save state at each VT enter.
+ */
+ if (pI830->SaveGeneration != serverGeneration) {
+ pI830->SaveGeneration = serverGeneration;
+ SaveHWState(pScrn);
+ }
+
+ pI830->leaving = FALSE;
+
if (IsPrimary(pScrn)) {
/*
* This is needed for restoring from ACPI modes (especially S3)
* so that we warmboot the Video BIOS. Some platforms have problems,
* warm booting when we don't need to, so check that we can call
- * the Video BIOS with our display devices, and only when that fails,
+ * the Video BIOS with our saved devices, and only when that fails,
* we'll warm boot it.
*/
- if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
- xf86Int10InfoPtr pInt = xf86InitInt10(pI830->pEnt->index);
+ /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/
+ CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF);
+ if (!I830Set640x480(pScrn) || !(temp & 0x80000000)) {
+ xf86Int10InfoPtr pInt;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "SetDisplayDevices failed, re-trying.\n");
+ "Detected resume, re-POSTing.\n");
+
+ pInt = xf86InitInt10(pI830->pEnt->index);
/* Now perform our warm boot */
if (pInt) {
@@ -4885,17 +5140,17 @@ I830BIOSEnterVT(int scrnIndex, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Re-POSTing via int10 failed, trying to continue.\n");
}
-
- /* Finally, re-setup the display devices */
- if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ }
+
+ /* Finally, re-setup the display devices */
+ if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Failed to switch to configured display devices\n");
- return FALSE;
- }
+ return FALSE;
}
}
- /* Setup for checking lid status */
+ /* Setup for device monitoring status */
pI830->monitorSwitch = INREG(SWF0) & 0x0000FFFF;
if (IsPrimary(pScrn))
@@ -4906,14 +5161,6 @@ I830BIOSEnterVT(int scrnIndex, int flags)
if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
- /*
- * Only save state once per server generation since that's what most
- * drivers do. Could change this to save state at each VT enter.
- */
- if (pI830->SaveGeneration != serverGeneration) {
- pI830->SaveGeneration = serverGeneration;
- SaveHWState(pScrn);
- }
ResetState(pScrn, FALSE);
SetHWOperatingState(pScrn);
@@ -4946,7 +5193,7 @@ I830BIOSEnterVT(int scrnIndex, int flags)
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
if (!pI830->starting) {
- /* gdg DRM driver 1.2 supports resume */
+ /* i915 DRM driver 1.2 supports resume */
if (pI830->drmMinor >= 2)
I830DRIResume(screenInfo.screens[scrnIndex]);
@@ -4962,6 +5209,9 @@ I830BIOSEnterVT(int scrnIndex, int flags)
}
#endif
+ if (pI830->checkDevices)
+ pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
+
return TRUE;
}
@@ -4969,8 +5219,6 @@ static Bool
I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
- int _head;
- int _tail;
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I830Ptr pI830 = I830PTR(pScrn);
int ret = TRUE;
@@ -4978,13 +5226,8 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode);
/* Stops head pointer freezes for 845G */
- if (!pI830->noAccel && (1 || IS_845G(pI830))) {
- do {
- _head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
- _tail = INREG(LP_RING + RING_TAIL) & I830_TAIL_MASK;
- DELAY(1000);
- } while (_head != _tail);
- }
+ if (!pI830->noAccel)
+ (*pI830->AccelInfoRec->Sync)(pScrn);
#ifndef BINDUNBIND
#define BINDUNBIND 0
@@ -5018,30 +5261,27 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode)
I830Ptr pI830 = I830PTR(pScrn);
Bool on = xf86IsUnblank(mode);
CARD32 temp, ctrl, base;
- int i;
DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
if (pScrn->vtSema) {
- for (i = 0; i < pI830->availablePipes; i++) {
- if (i == 0) {
- ctrl = DSPACNTR;
- base = DSPABASE;
- } else {
- ctrl = DSPBCNTR;
- base = DSPBADDR;
- }
- if (pI830->planeEnabled[i]) {
- temp = INREG(ctrl);
- if (on)
- temp |= DISPLAY_PLANE_ENABLE;
- else
- temp &= ~DISPLAY_PLANE_ENABLE;
- OUTREG(ctrl, temp);
- /* Flush changes */
- temp = INREG(base);
- OUTREG(base, temp);
- }
+ if (pI830->pipe == 0) {
+ ctrl = DSPACNTR;
+ base = DSPABASE;
+ } else {
+ ctrl = DSPBCNTR;
+ base = DSPBADDR;
+ }
+ if (pI830->planeEnabled[pI830->pipe]) {
+ temp = INREG(ctrl);
+ if (on)
+ temp |= DISPLAY_PLANE_ENABLE;
+ else
+ temp &= ~DISPLAY_PLANE_ENABLE;
+ OUTREG(ctrl, temp);
+ /* Flush changes */
+ temp = INREG(base);
+ OUTREG(base, temp);
}
if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
@@ -5134,6 +5374,10 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen)
I830BIOSLeaveVT(scrnIndex, 0);
}
+ if (pI830->devicesTimer)
+ TimerCancel(pI830->devicesTimer);
+ pI830->devicesTimer = NULL;
+
DPRINTF(PFX, "\nUnmapping memory\n");
I830UnmapMem(pScrn);
vgaHWUnmapMem(pScrn);
@@ -5170,9 +5414,6 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen)
pI830->overlayOn = NULL;
}
- if (pI830->lidTimer)
- TimerCancel(pI830->lidTimer);
-
pScrn->vtSema = FALSE;
pI830->closing = FALSE;
pScreen->CloseScreen = pI830->CloseScreen;
@@ -5252,58 +5493,229 @@ I830PMEvent(int scrnIndex, pmEvent event, Bool undo)
return TRUE;
}
+static int CountBits(int a)
+{
+ int i;
+ int b = 0;
+
+ for (i=0;i<8;i++) {
+ if (a & (1<<i))
+ b+=1;
+ }
+
+ return b;
+}
+
static CARD32
-I830LidTimer(OsTimerPtr timer, CARD32 now, pointer arg)
+I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg)
{
ScrnInfoPtr pScrn = (ScrnInfoPtr) arg;
I830Ptr pI830 = I830PTR(pScrn);
+ int cloned = 0;
if (pScrn->vtSema) {
/* Check for monitor lid being closed/opened and act accordingly */
- int temp = INREG(SWF0) & 0x0000FFFF;
+ CARD32 adjust;
+ CARD32 temp = INREG(SWF0) & 0x0000FFFF;
+ int fixup = 0;
+ /* this avoids a BIOS call if possible */
if (pI830->monitorSwitch != temp) {
- int conf = pI830->operatingDevices;
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Detected possible lid operation, fixing up.\n");
- if ((temp & 0x0808) == 0x0000) {
- /* LFP (PIPE A or B) GOING OFF - PROBABLE LID CLOSURE */
- conf = pI830->operatingDevices & 0xF7F7;
-#if 0
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Lid is being closed.\n");
-#endif
- } else {
-#if 0
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Lid is being opened.\n");
-#endif
+ I830Ptr pI8301;
+ I830Ptr pI8302 = NULL;
+ unsigned int toggle = GetToggleList(pScrn, 1);
+
+ GetToggleList(pScrn, 2);
+ GetToggleList(pScrn, 3);
+ GetToggleList(pScrn, 4);
+
+ if (IsPrimary(pScrn))
+ pI8301 = pI830;
+ else
+ pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+ if (xf86IsEntityShared(pScrn->entityList[0]))
+ pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+
+ pI8301->lastDevice1 = pI8301->lastDevice2;
+ pI8301->lastDevice2 = pI8301->monitorSwitch;
+
+ if (CountBits(temp & 0xff) > 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected cloned pipe mode (A).\n");
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
+ temp = pI8301->MonType2 << 8 | pI8301->MonType1;
+ } else
+ if (CountBits((temp & 0xff00) >> 8) > 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected cloned pipe mode (B).\n");
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
+ temp = pI8301->MonType2 << 8 | pI8301->MonType1;
+ } else
+ if (pI8301->lastDevice1 && pI8301->lastDevice2) {
+ if ( ((pI8301->lastDevice1 & 0xFF00) == 0) &&
+ ((pI8301->lastDevice2 & 0x00FF) == 0) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected last devices (1).\n");
+ cloned = 1;
+ } else if ( ((pI8301->lastDevice2 & 0xFF00) == 0) &&
+ ((pI8301->lastDevice1 & 0x00FF) == 0) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected last devices (2).\n");
+ cloned = 1;
+ } else
+ cloned = 0;
}
- /* If we've defined our own monitors, then get them and set them
- * up when switching in single head mode, no effect in dual heads
- * NOTE: This assumes that the LCD is always on Pipe B..... */
- conf |= pI830->MonType1;
- if (IsPrimary(pScrn)) {
- if (!SetDisplayDevices(pScrn, conf))
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch "
- "to configured display devices during lid operation.\n");
+ if (cloned &&
+ ((CountBits(pI830->lastDevice1 & 0xff) > 1) ||
+ ((CountBits((pI830->lastDevice1 & 0xff00) >> 8) > 1))) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected duplicate (1).\n");
+ cloned = 0;
+ } else
+ if (cloned &&
+ ((CountBits(pI830->lastDevice2 & 0xff) > 1) ||
+ ((CountBits((pI830->lastDevice2 & 0xff00) >> 8) > 1))) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected duplicate (2).\n");
+ cloned = 0;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Requested display devices 0x%lx.\n", temp);
+
+
+ /* If the BIOS doesn't flip between CRT, LFP and CRT+LFP we fake
+ * it here as it seems some just flip between CRT and LFP. Ugh!
+ *
+ * So this pushes them onto Pipe B and clones the displays, which
+ * is what most BIOS' should be doing.
+ *
+ * Cloned pipe mode should only be done when running single head.
+ */
+ if (xf86IsEntityShared(pScrn->entityList[0]))
+ cloned = 0;
+
+ if (cloned) {
+ if (pI830->Clone)
+ temp = pI8301->MonType2 << 8 | pI8301->MonType1;
+ else if (pI8301->lastDevice1 & 0xFF)
+ temp = pI8301->lastDevice1 << 8 | pI8301->lastDevice2;
+ else
+ temp = pI8301->lastDevice2 << 8 | pI8301->lastDevice1;
+ }
+
+ /* Jump to our next mode if we detect we've been here before */
+ if (temp == pI830->lastDevice1 || temp == pI830->lastDevice2) {
+ temp = toggle;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected duplicate devices. Toggling (0x%lx)\n", temp);
}
- pI830->monitorSwitch = conf;
-
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected display change operation (0x%x, 0x%x, 0x%lx).\n",
+ pI8301->lastDevice1, pI8301->lastDevice2, temp);
+
+ /* double check the display devices are what's configured and try
+ * not to do it twice because of dual heads with the code above */
+ if (!SetDisplayDevices(pScrn, temp)) {
+ if ( cloned &&
+ ((CountBits(temp & 0xff) > 1) ||
+ (CountBits((temp & 0xff00) >> 8) > 1)) ) {
+ temp = pI8301->lastDevice2 | pI8301->lastDevice1;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cloning failed, "
+ "trying dual pipe clone mode (0x%lx)\n", temp);
+ if (!SetDisplayDevices(pScrn, temp))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch "
+ "to configured display devices (0x%lx).\n", temp);
+ else
+ pI830->Clone = TRUE;
+ }
+ }
+ pI8301->monitorSwitch = temp;
+ pI8301->operatingDevices = temp;
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ pI8302->operatingDevices = temp;
+ pI8302->monitorSwitch = temp;
+ }
+
+ fixup = 1;
+ } else {
+ int offset = pScrn->fbOffset + ((pScrn->frameY0 * pScrn->displayWidth + pScrn->frameX0) * pI830->cpp);
+
+ if (pI830->pipe == 0)
+ adjust = INREG(DSPABASE);
+ else
+ adjust = INREG(DSPBBASE);
+
+ if (adjust != offset) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Fixing display offsets.\n");
+
+ I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
+ }
+ }
+
+ if (fixup) {
+ ScreenPtr pCursorScreen;
+ int x = 0, y = 0;
+
+ pCursorScreen = miPointerCurrentScreen();
+ if (pScrn->pScreen == pCursorScreen)
+ miPointerPosition(&x, &y);
+
/* Now, when we're single head, make sure we switch pipes */
- if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)) {
- if ((temp & 0xFF00) == 0x0000)
- pI830->pipe = 0;
- if ((temp & 0x00FF) == 0x0000)
+ if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) || cloned) {
+ if (temp & 0xFF00)
pI830->pipe = 1;
- }
+ else
+ pI830->pipe = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Primary pipe is now %s.\n", pI830->pipe ? "B" : "A");
+ }
+
I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
-
- /* Everything should be o.k. now, so make sure the HW cursor is
- * on the correct pipe */
- if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
- pI830->CursorInfoRec->ShowCursor(pScrn);
- pI830->cursorOn = TRUE;
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ ScrnInfoPtr pScrn2;
+ I830Ptr pI8302;
+
+ if (IsPrimary(pScrn)) {
+ pScrn2 = pI830->entityPrivate->pScrn_2;
+ pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+ } else {
+ pScrn2 = pI830->entityPrivate->pScrn_1;
+ pI8302 = I830PTR(pI830->entityPrivate->pScrn_1);
+ }
+
+ I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
+ I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
+ if (pScrn2->pScreen == pCursorScreen) {
+ int sigstate = xf86BlockSIGIO ();
+ miPointerWarpCursor(pScrn2->pScreen,x,y);
+
+ /* xf86Info.currentScreen = pScrn->pScreen; */
+ xf86UnblockSIGIO (sigstate);
+ if (pI8302->CursorInfoRec && !pI8302->SWCursor && pI8302->cursorOn) {
+ pI8302->CursorInfoRec->HideCursor(pScrn);
+ pI8302->CursorInfoRec->ShowCursor(pScrn);
+ pI8302->cursorOn = TRUE;
+ }
+ }
+ }
+
+ if (pScrn->pScreen == pCursorScreen) {
+ int sigstate = xf86BlockSIGIO ();
+ miPointerWarpCursor(pScrn->pScreen,x,y);
+
+ /* xf86Info.currentScreen = pScrn->pScreen; */
+ xf86UnblockSIGIO (sigstate);
+ if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
+ pI830->CursorInfoRec->HideCursor(pScrn);
+ pI830->CursorInfoRec->ShowCursor(pScrn);
+ pI830->cursorOn = TRUE;
+ }
}
}
}