summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@neko.keithp.com>2007-01-03 21:54:05 -0800
committerKeith Packard <keithp@neko.keithp.com>2007-01-03 21:54:05 -0800
commit5a793b0dcf2d5de408b55073858fcfba6d99f994 (patch)
tree062de91ac31b128d29ec026090181b1d9b0de82f
parentf188525030a8fac59e41520449b1aec9b123e4ea (diff)
parent394124ceaadb46d976ad5c3bdeb1b77d351c57f6 (diff)
Merge branch 'modesetting-origin' into modesetting
-rw-r--r--src/i830.h4
-rw-r--r--src/i830_cursor.c8
-rw-r--r--src/i830_display.c63
-rw-r--r--src/i830_display.h1
-rw-r--r--src/i830_dri.c25
-rw-r--r--src/i830_driver.c152
-rw-r--r--src/i830_randr.c16
-rw-r--r--src/i830_sdvo.c7
-rw-r--r--src/i830_xf86Crtc.c410
-rw-r--r--src/i830_xf86Crtc.h25
10 files changed, 508 insertions, 203 deletions
diff --git a/src/i830.h b/src/i830.h
index c2670cda..d5ca5d4b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -194,7 +194,8 @@ extern const char *i830_output_type_names[];
typedef struct _I830CrtcPrivateRec {
int pipe;
- Bool gammaEnabled;
+ /* Lookup table values to be set when the CRTC is enabled */
+ CARD8 lut_r[256], lut_g[256], lut_b[256];
} I830CrtcPrivateRec, *I830CrtcPrivatePtr;
#define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
@@ -221,7 +222,6 @@ enum last_3d {
typedef struct _I830PipeRec {
Bool enabled;
- Bool gammaEnabled;
int x;
int y;
Bool cursorInRange;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index cb1585fb..81cb3bd8 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -130,9 +130,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force)
temp = INREG(cursor_control);
temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
if (pI830->CursorIsARGB) {
- temp |= CURSOR_MODE_64_ARGB_AX;
- if (intel_crtc->gammaEnabled)
- temp |= MCURSOR_GAMMA_ENABLE;
+ temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_MODE_64_4C_AX;
@@ -144,9 +142,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force)
temp &= ~(CURSOR_FORMAT_MASK);
temp |= CURSOR_ENABLE;
if (pI830->CursorIsARGB) {
- temp |= CURSOR_FORMAT_ARGB;
- if (intel_crtc->gammaEnabled)
- temp |= CURSOR_GAMMA_ENABLE;
+ temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_FORMAT_3C;
OUTREG(CURSOR_CONTROL, temp);
diff --git a/src/i830_display.c b/src/i830_display.c
index 9ec46a45..f47a9dbf 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -351,9 +351,12 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
if (IS_I965G(pI830)) {
OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp));
+ (void) INREG(dspbase);
OUTREG(dspsurf, Start);
+ (void) INREG(dspsurf);
} else {
OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+ (void) INREG(dspbase);
}
crtc->x = x;
@@ -533,6 +536,8 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
OUTREG(dspbase_reg, INREG(dspbase_reg));
}
+ i830_crtc_load_lut(crtc);
+
/* Give the overlay scaler a chance to enable if it's on this pipe */
i830_crtc_dpms_video(crtc, TRUE);
break;
@@ -715,10 +720,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
dpll |= PLL_REF_INPUT_DREFCLK;
/* Set up the display plane register */
- dspcntr = 0;
+ dspcntr = DISPPLANE_GAMMA_ENABLE;
switch (pScrn->bitsPerPixel) {
case 8:
- dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
+ dspcntr |= DISPPLANE_8BPP;
break;
case 16:
if (pScrn->depth == 15)
@@ -733,10 +738,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
FatalError("unknown display bpp\n");
}
- if (intel_crtc->gammaEnabled) {
- dspcntr |= DISPPLANE_GAMMA_ENABLE;
- }
-
if (pipe == 0)
dspcntr |= DISPPLANE_SEL_PIPE_A;
else
@@ -837,6 +838,48 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
i830WaitForVblank(pScrn);
}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void
+i830_crtc_load_lut(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
+ int i;
+
+ /* The clocks have to be on to load the palette. */
+ if (!crtc->enabled)
+ return;
+
+ for (i = 0; i < 256; i++) {
+ OUTREG(palreg + 4 * i,
+ (intel_crtc->lut_r[i] << 16) |
+ (intel_crtc->lut_g[i] << 8) |
+ intel_crtc->lut_b[i]);
+ }
+}
+
+/** Sets the color ramps on behalf of RandR */
+static void
+i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+ int size)
+{
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int i;
+
+ assert(size == 256);
+
+ for (i = 0; i < 256; i++) {
+ intel_crtc->lut_r[i] = red[i] >> 8;
+ intel_crtc->lut_g[i] = green[i] >> 8;
+ intel_crtc->lut_b[i] = blue[i] >> 8;
+ }
+
+ i830_crtc_load_lut(crtc);
+}
+
/**
* Sets the given video mode on the given pipe.
*
@@ -1144,6 +1187,7 @@ static const xf86CrtcFuncsRec i830_crtc_funcs = {
.restore = NULL, /* XXX */
.mode_fixup = i830_crtc_mode_fixup,
.mode_set = i830_crtc_mode_set,
+ .gamma_set = i830_crtc_gamma_set,
.destroy = NULL, /* XXX */
};
@@ -1152,6 +1196,7 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pipe)
{
xf86CrtcPtr crtc;
I830CrtcPrivatePtr intel_crtc;
+ int i;
crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
if (crtc == NULL)
@@ -1160,6 +1205,12 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pipe)
intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
intel_crtc->pipe = pipe;
+ /* Initialize the LUTs for when we turn on the CRTC. */
+ for (i = 0; i < 256; i++) {
+ intel_crtc->lut_r[i] = i;
+ intel_crtc->lut_g[i] = i;
+ intel_crtc->lut_b[i] = i;
+ }
crtc->driver_private = intel_crtc;
}
diff --git a/src/i830_display.h b/src/i830_display.h
index 5517d27c..66ab17e8 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -42,3 +42,4 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
Bool i830PipeInUse(xf86CrtcPtr crtc);
void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
+void i830_crtc_load_lut(xf86CrtcPtr crtc);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 5fdacc7d..eeef2895 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -216,9 +216,9 @@ I830InitVisualConfigs(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
int numConfigs = 0;
- __GLXvisualConfig *pConfigs = 0;
- I830ConfigPrivPtr pI830Configs = 0;
- I830ConfigPrivPtr *pI830ConfigPtrs = 0;
+ __GLXvisualConfig *pConfigs = NULL;
+ I830ConfigPrivPtr pI830Configs = NULL;
+ I830ConfigPrivPtr *pI830ConfigPtrs = NULL;
int accum, stencil, db, depth;
int i;
@@ -538,7 +538,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
if (!(pI830DRI = (I830DRIPtr) xcalloc(sizeof(I830DRIRec), 1))) {
DRIDestroyInfoRec(pI830->pDRIInfo);
- pI830->pDRIInfo = 0;
+ pI830->pDRIInfo = NULL;
return FALSE;
}
pDRIInfo->devPrivate = pI830DRI;
@@ -561,9 +561,9 @@ I830DRIScreenInit(ScreenPtr pScreen)
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] DRIScreenInit failed. Disabling DRI.\n");
xfree(pDRIInfo->devPrivate);
- pDRIInfo->devPrivate = 0;
+ pDRIInfo->devPrivate = NULL;
DRIDestroyInfoRec(pI830->pDRIInfo);
- pI830->pDRIInfo = 0;
+ pI830->pDRIInfo = NULL;
return FALSE;
}
@@ -951,10 +951,10 @@ I830DRICloseScreen(ScreenPtr pScreen)
if (pI830->pDRIInfo) {
if (pI830->pDRIInfo->devPrivate) {
xfree(pI830->pDRIInfo->devPrivate);
- pI830->pDRIInfo->devPrivate = 0;
+ pI830->pDRIInfo->devPrivate = NULL;
}
DRIDestroyInfoRec(pI830->pDRIInfo);
- pI830->pDRIInfo = 0;
+ pI830->pDRIInfo = NULL;
}
if (pI830->pVisualConfigs)
xfree(pI830->pVisualConfigs);
@@ -1025,7 +1025,7 @@ I830DRIFinishScreenInit(ScreenPtr pScreen)
}
}
-void
+static void
I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
DRIContextType oldContextType, void *oldContext,
DRIContextType newContextType, void *newContext)
@@ -1035,7 +1035,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
if (syncType == DRI_3D_SYNC &&
oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
ErrorF("i830DRISwapContext (in)\n");
@@ -1128,9 +1127,9 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
BoxPtr pbox = REGION_RECTS(prgnSrc);
int nbox = REGION_NUM_RECTS(prgnSrc);
- BoxPtr pboxNew1 = 0;
- BoxPtr pboxNew2 = 0;
- DDXPointPtr pptNew1 = 0;
+ BoxPtr pboxNew1 = NULL;
+ BoxPtr pboxNew2 = NULL;
+ DDXPointPtr pptNew1 = NULL;
DDXPointPtr pptSrc = &ptOldOrg;
int dx = pParent->drawable.x - ptOldOrg.x;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 52647676..94cba05d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -579,106 +579,67 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- I830Ptr pI830;
int i,j, index;
- unsigned char r, g, b;
- CARD32 val, temp;
- int palreg;
- int dspreg, dspbase, dspsurf;
int p;
+ CARD16 lut_r[256], lut_g[256], lut_b[256];
DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
- pI830 = I830PTR(pScrn);
- for(p=0; p < xf86_config->num_crtc; p++)
- {
+ for(p = 0; p < xf86_config->num_crtc; p++) {
xf86CrtcPtr crtc = xf86_config->crtc[p];
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
- if (p == 0) {
- palreg = PALETTE_A;
- dspreg = DSPACNTR;
- dspbase = DSPABASE;
- dspsurf = DSPASURF;
- } else {
- palreg = PALETTE_B;
- dspreg = DSPBCNTR;
- dspbase = DSPBBASE;
- dspsurf = DSPBSURF;
+ /* Initialize to the old lookup table values. */
+ for (i = 0; i < 256; i++) {
+ lut_r[i] = intel_crtc->lut_r[i] << 8;
+ lut_g[i] = intel_crtc->lut_g[i] << 8;
+ lut_b[i] = intel_crtc->lut_b[i] << 8;
}
- if (crtc->enabled == 0)
- continue;
-
- intel_crtc->gammaEnabled = 1;
-
- /* To ensure gamma is enabled we need to turn off and on the plane */
- temp = INREG(dspreg);
- OUTREG(dspreg, temp & ~(1<<31));
- OUTREG(dspbase, INREG(dspbase));
- OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE);
- OUTREG(dspbase, INREG(dspbase));
- if (IS_I965G(pI830))
- OUTREG(dspsurf, INREG(dspsurf));
-
- /* 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;
- for (j = 0; j < 8; j++) {
- OUTREG(palreg + index * 32 + (j * 4), val);
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ for (j = 0; j < 8; j++) {
+ lut_r[index * 8 + j] = colors[index].red << 8;
+ lut_g[index * 8 + j] = colors[index].green << 8;
+ lut_b[index * 8 + j] = colors[index].blue << 8;
+ }
}
- }
- break;
+ break;
case 16:
- for (i = 0; i < numColors; i++) {
- index = indices[i];
- r = colors[index / 2].red;
- g = colors[index].green;
- b = colors[index / 2].blue;
-
- 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);
-
- if (index <= 31) {
- r = colors[index].red;
- g = colors[(index * 2) + 1].green;
- b = colors[index].blue;
-
- val = (r << 16) | (g << 8) | b;
- OUTREG(palreg + index * 32, val);
- OUTREG(palreg + index * 32 + 4, val);
- OUTREG(palreg + index * 32 + 8, val);
- OUTREG(palreg + index * 32 + 12, val);
- }
- }
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+
+ if (i <= 31) {
+ for (j = 0; j < 8; j++) {
+ lut_r[index * 8 + j] = colors[index].red << 8;
+ lut_b[index * 8 + j] = colors[index].blue << 8;
+ }
+ }
+
+ for (j = 0; j < 4; j++) {
+ lut_g[index * 4 + j] = colors[index].green << 8;
+ }
+ }
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(palreg + index * 4, val);
- }
- break;
- }
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ lut_r[index] = colors[index].red << 8;
+ lut_g[index] = colors[index].green << 8;
+ lut_b[index] = colors[index].blue << 8;
+ }
+ break;
+ }
+
+ /* Make the change through RandR */
+#ifdef RANDR_12_INTERFACE
+ RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
+#else
+ crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
+#endif
}
-
- /* Enable gamma for Cursor if ARGB */
- if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
- pI830->CursorInfoRec->ShowCursor(pScrn);
}
int
@@ -912,7 +873,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
Bool enable;
const char *chipname;
int num_pipe;
- int max_width;
+ int max_width, max_height;
#ifdef XF86DRI
unsigned long savedMMSize;
#endif
@@ -1183,10 +1144,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
if (IS_I965G(pI830))
+ {
max_width = 16384;
+ max_height = 4096;
+ }
else
- max_width = 8192 / pI830->cpp;
- xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, 2048);
+ {
+ max_width = 2048;
+ max_height = 2048;
+ }
+ xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height);
/* Some of the probing needs MMIO access, so map it here. */
I830MapMMIO(pScrn);
@@ -1830,14 +1797,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
"VideoRam: %d KB\n", pScrn->videoRam);
- if (!IS_I965G(pI830) && pScrn->displayWidth * pI830->cpp > 8192) {
+ if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Cannot support DRI with frame buffer stride > 8K.\n");
+ "Cannot support DRI with frame buffer width > 2048.\n");
pI830->disableTiling = TRUE;
pI830->directRenderingDisabled = TRUE;
}
- if (pScrn->virtualY > 2048) {
+ if (!IS_I965G(pI830) && pScrn->virtualY > 2048) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
pI830->noAccel = TRUE;
}
@@ -3047,7 +3014,8 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags)
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
I830Ptr pI830 = I830PTR(pScrn);
- xf86CrtcPtr crtc = config->output[config->compat_output]->crtc;
+ xf86OutputPtr output = config->output[config->compat_output];
+ xf86CrtcPtr crtc = output->crtc;
DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
x, pI830->xoffset, y, pI830->yoffset);
@@ -3059,7 +3027,7 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags)
(*pI830->AccelInfoRec->Sync)(pScrn);
pI830->AccelInfoRec->NeedToSync = FALSE;
}
- i830PipeSetBase(crtc, x, y);
+ i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
}
}
@@ -3596,7 +3564,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg)
* is this.
*/
- xf86ProbeOutputModes (pScrn);
+ xf86ProbeOutputModes (pScrn, 0, 0);
xf86SetScrnInfoModes (pScrn);
I830DGAReInit (pScrn->pScreen);
xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d5ccce37..533322b2 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -95,7 +95,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
}
/* Re-probe the outputs for new monitors or modes */
- xf86ProbeOutputModes (scrp);
+ xf86ProbeOutputModes (scrp, 0, 0);
xf86SetScrnInfoModes (scrp);
I830DGAReInit (pScreen);
@@ -663,9 +663,17 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
static Bool
xf86RandR12CrtcSetGamma (ScreenPtr pScreen,
- RRCrtcPtr crtc)
+ RRCrtcPtr randr_crtc)
{
- return FALSE;
+ xf86CrtcPtr crtc = randr_crtc->devPrivate;
+
+ if (crtc->funcs->gamma_set == NULL)
+ return FALSE;
+
+ crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
+ randr_crtc->gammaBlue, randr_crtc->gammaSize);
+
+ return TRUE;
}
/**
@@ -818,7 +826,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- xf86ProbeOutputModes (pScrn);
+ xf86ProbeOutputModes (pScrn, 0, 0);
xf86SetScrnInfoModes (pScrn);
I830DGAReInit (pScreen);
return xf86RandR12SetInfo12 (pScreen);
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b5116be0..19b4b934 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1207,7 +1207,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
}
strcpy (name, name_prefix);
strcat (name, name_suffix);
- xf86OutputRename (output, name);
+ if (!xf86OutputRename (output, name))
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+
/* Set the input timing to the screen. Assume always input 0. */
i830_sdvo_set_target_input(output, TRUE, FALSE);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index a0f44df5..ceb8f2ef 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -127,6 +127,33 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
extern XF86ConfigPtr xf86configptr;
+typedef enum {
+ OPTION_PREFERRED_MODE,
+ OPTION_POSITION,
+ OPTION_BELOW,
+ OPTION_RIGHT_OF,
+ OPTION_ABOVE,
+ OPTION_LEFT_OF,
+ OPTION_ENABLE,
+ OPTION_DISABLE,
+ OPTION_MIN_CLOCK,
+ OPTION_MAX_CLOCK,
+} OutputOpts;
+
+static OptionInfoRec xf86OutputOptions[] = {
+ {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE },
+ {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE },
+ {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE },
+ {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE },
+ {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE },
+ {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE },
+};
+
static void
xf86OutputSetMonitor (xf86OutputPtr output)
{
@@ -134,6 +161,12 @@ xf86OutputSetMonitor (xf86OutputPtr output)
static const char monitor_prefix[] = "monitor-";
char *monitor;
+ if (output->options)
+ xfree (output->options);
+
+ output->options = xnfalloc (sizeof (xf86OutputOptions));
+ memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions));
+
option_name = xnfalloc (strlen (monitor_prefix) +
strlen (output->name) + 1);
strcpy (option_name, monitor_prefix);
@@ -144,7 +177,24 @@ xf86OutputSetMonitor (xf86OutputPtr output)
else
xf86MarkOptionUsedByName (output->scrn->options, option_name);
xfree (option_name);
- output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst);
+ output->conf_monitor = xf86findMonitor (monitor,
+ xf86configptr->conf_monitor_lst);
+ if (output->conf_monitor)
+ xf86ProcessOptions (output->scrn->scrnIndex,
+ output->conf_monitor->mon_option_lst,
+ output->options);
+}
+
+static Bool
+xf86OutputEnabled (xf86OutputPtr output)
+{
+ /* Check to see if this output was disabled in the config file */
+ if (xf86ReturnOptValBool (output->options, OPTION_ENABLE, TRUE) == FALSE ||
+ xf86ReturnOptValBool (output->options, OPTION_DISABLE, FALSE) == TRUE)
+ {
+ return FALSE;
+ }
+ return TRUE;
}
xf86OutputPtr
@@ -167,6 +217,8 @@ xf86OutputCreate (ScrnInfoPtr scrn,
#ifdef RANDR_12_INTERFACE
output->randr_output = NULL;
#endif
+ xf86OutputSetMonitor (output);
+
if (xf86_config->output)
outputs = xrealloc (xf86_config->output,
(xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
@@ -181,24 +233,24 @@ xf86OutputCreate (ScrnInfoPtr scrn,
xf86_config->output = outputs;
xf86_config->output[xf86_config->num_output++] = output;
- xf86OutputSetMonitor (output);
return output;
}
-void
+Bool
xf86OutputRename (xf86OutputPtr output, const char *name)
{
int len = strlen(name);
char *newname = xalloc (len + 1);
if (!newname)
- return; /* so sorry... */
+ return FALSE; /* so sorry... */
strcpy (newname, name);
if (output->name != (char *) (output + 1))
xfree (output->name);
output->name = newname;
xf86OutputSetMonitor (output);
+ return TRUE;
}
void
@@ -375,7 +427,9 @@ xf86PickCrtcs (ScrnInfoPtr pScrn,
* If the two outputs desire the same mode,
* see if they can be cloned
*/
- if (xf86ModesEqual (modes[o], modes[n]))
+ if (xf86ModesEqual (modes[o], modes[n]) &&
+ config->output[o]->initial_x == config->output[n]->initial_x &&
+ config->output[o]->initial_y == config->output[n]->initial_y)
{
for (l = 0; l < config->num_output; l++)
if (output->possible_clones & (1 << l))
@@ -403,7 +457,8 @@ xf86PickCrtcs (ScrnInfoPtr pScrn,
/*
* Compute the virtual size necessary to place all of the available
- * crtcs in a panorama configuration
+ * crtcs in the specified configuration and also large enough to
+ * resize any crtc to the largest available mode
*/
static void
@@ -418,7 +473,13 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp)
for (c = 0; c < config->num_crtc; c++)
{
int crtc_width = 0, crtc_height = 0;
+ xf86CrtcPtr crtc = config->crtc[c];
+ if (crtc->enabled)
+ {
+ crtc_width = crtc->x + crtc->desiredMode.HDisplay;
+ crtc_height = crtc->y + crtc->desiredMode.VDisplay;
+ }
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
@@ -436,7 +497,8 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp)
}
}
}
- width += crtc_width;
+ if (crtc_width > width)
+ width = crtc_width;
if (crtc_height > height)
height = crtc_height;
}
@@ -448,6 +510,186 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp)
*heightp = height;
}
+#define POSITION_UNSET -100000
+
+static Bool
+xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o;
+ int min_x, min_y;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x = output->initial_y = POSITION_UNSET;
+ }
+
+ /*
+ * Loop until all outputs are set
+ */
+ for (;;)
+ {
+ Bool any_set = FALSE;
+ Bool keep_going = FALSE;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ static const OutputOpts relations[] = {
+ OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
+ };
+ xf86OutputPtr output = config->output[o];
+ xf86OutputPtr relative;
+ char *relative_name;
+ char *position;
+ OutputOpts relation;
+ int r;
+
+ if (output->initial_x != POSITION_UNSET)
+ continue;
+ position = xf86GetOptValString (output->options,
+ OPTION_POSITION);
+ /*
+ * Absolute position wins
+ */
+ if (position)
+ {
+ int x, y;
+ if (sscanf (position, "%d %d", &x, &y) == 2)
+ {
+ output->initial_x = x;
+ output->initial_y = y;
+ }
+ else
+ {
+ xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+ "Output %s position not of form \"x y\"\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ }
+ any_set = TRUE;
+ continue;
+ }
+ /*
+ * Next comes relative positions
+ */
+ relation = 0;
+ relative_name = NULL;
+ for (r = 0; r < 4; r++)
+ {
+ relation = relations[r];
+ relative_name = xf86GetOptValString (output->options,
+ relation);
+ if (relative_name)
+ break;
+ }
+ if (relative_name)
+ {
+ int or;
+ relative = NULL;
+ for (or = 0; or < config->num_output; or++)
+ {
+ xf86OutputPtr out_rel = config->output[or];
+ XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor;
+ char *name;
+
+ if (rel_mon)
+ name = rel_mon->mon_identifier;
+ else
+ name = out_rel->name;
+ if (!strcmp (relative_name, name))
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (!relative)
+ {
+ xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+ "Cannot position output %s relative to unknown output %s\n",
+ output->name, relative_name);
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ continue;
+ }
+ if (relative->initial_x == POSITION_UNSET)
+ {
+ keep_going = TRUE;
+ continue;
+ }
+ output->initial_x = relative->initial_x;
+ output->initial_y = relative->initial_y;
+ switch (relation) {
+ case OPTION_BELOW:
+ output->initial_y += modes[or]->VDisplay;
+ break;
+ case OPTION_RIGHT_OF:
+ output->initial_x += modes[or]->HDisplay;
+ break;
+ case OPTION_ABOVE:
+ output->initial_y -= modes[o]->VDisplay;
+ break;
+ case OPTION_LEFT_OF:
+ output->initial_x -= modes[o]->HDisplay;
+ break;
+ default:
+ break;
+ }
+ any_set = TRUE;
+ continue;
+ }
+
+ /* Nothing set, just stick them at 0,0 */
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ }
+ if (!keep_going)
+ break;
+ if (!any_set)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ if (output->initial_x == POSITION_UNSET)
+ {
+ xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+ "Output position loop. Moving %s to 0,0\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * normalize positions
+ */
+ min_x = 1000000;
+ min_y = 1000000;
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ if (output->initial_x < min_x)
+ min_x = output->initial_x;
+ if (output->initial_y < min_y)
+ min_y = output->initial_y;
+ }
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x -= min_x;
+ output->initial_y -= min_y;
+ }
+ return TRUE;
+}
+
/*
* XXX walk the monitor mode list and prune out duplicates that
* are inserted by xf86DDCMonitorSet. In an ideal world, that
@@ -536,13 +778,13 @@ i830xf86SortModes (DisplayModePtr input)
#define DEBUG_REPROBE 1
void
-xf86ProbeOutputModes (ScrnInfoPtr pScrn)
+xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
int o;
- int virtualX, virtualY;
- xf86RandR12GetOriginalVirtualSize (pScrn, &virtualX, &virtualY);
+ if (maxX == 0 || maxY == 0)
+ xf86RandR12GetOriginalVirtualSize (pScrn, &maxX, &maxY);
/* Elide duplicate modes before defaulting code uses them */
xf86PruneDuplicateMonitorModes (pScrn->monitor);
@@ -553,11 +795,13 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
xf86OutputPtr output = config->output[o];
DisplayModePtr mode;
DisplayModePtr config_modes = NULL, output_modes, default_modes;
- XF86ConfMonitorPtr conf_monitor;
+ char *preferred_mode;
xf86MonPtr edid_monitor;
+ XF86ConfMonitorPtr conf_monitor;
MonRec mon_rec;
int min_clock = 0;
int max_clock = 0;
+ double clock;
enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
while (output->probed_modes != NULL)
@@ -632,6 +876,14 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
}
}
}
+
+ if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ min_clock = (int) clock;
+ if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ max_clock = (int) clock;
+
/*
* These limits will end up setting a 1024x768@60Hz mode by default,
* which seems like a fairly good mode to use when nothing else is
@@ -677,9 +929,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
/*
- * Check all modes against virtual size
+ * Check all modes against max size
*/
- i830xf86ValidateModesSize (pScrn, output->probed_modes, virtualX, virtualY, 0);
+ if (maxX && maxY)
+ i830xf86ValidateModesSize (pScrn, output->probed_modes,
+ maxX, maxY, 0);
/*
* Check all modes against output
@@ -693,27 +947,28 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
output->probed_modes = i830xf86SortModes (output->probed_modes);
/* Check for a configured preference for a particular mode */
- if (conf_monitor)
- {
- char *preferred_mode = xf86findOptionValue (conf_monitor->mon_option_lst,
- "Preferred Mode");
+ preferred_mode = xf86GetOptValString (output->options,
+ OPTION_PREFERRED_MODE);
- if (preferred_mode)
+ if (preferred_mode)
+ {
+ for (mode = output->probed_modes; mode; mode = mode->next)
{
- for (mode = output->probed_modes; mode; mode = mode->next)
- if (!strcmp (preferred_mode, mode->name))
- break;
- if (mode && mode != output->probed_modes)
+ if (!strcmp (preferred_mode, mode->name))
{
- if (mode->prev)
- mode->prev->next = mode->next;
- if (mode->next)
- mode->next->prev = mode->prev;
- mode->next = output->probed_modes;
- output->probed_modes->prev = mode;
- mode->prev = NULL;
- output->probed_modes = mode;
+ if (mode != output->probed_modes)
+ {
+ if (mode->prev)
+ mode->prev->next = mode->next;
+ if (mode->next)
+ mode->next->prev = mode->prev;
+ mode->next = output->probed_modes;
+ output->probed_modes->prev = mode;
+ mode->prev = NULL;
+ output->probed_modes = mode;
+ }
mode->type |= M_T_PREFERRED;
+ break;
}
}
}
@@ -760,7 +1015,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
xf86OutputPtr output;
xf86CrtcPtr crtc;
DisplayModePtr last, mode;
- int originalVirtualX, originalVirtualY;
output = config->output[config->compat_output];
if (!output->crtc)
@@ -788,18 +1042,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
/* Set pScrn->modes to the mode list for the 'compat' output */
pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
- xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
-
- /* Disable modes in the XFree86 DDX list that are larger than the current
- * virtual size.
- */
- i830xf86ValidateModesSize(pScrn, pScrn->modes,
- originalVirtualX, originalVirtualY,
- pScrn->displayWidth);
-
- /* Strip out anything that we threw out for virtualX/Y. */
- i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
-
for (mode = pScrn->modes; mode; mode = mode->next)
if (xf86ModesEqual (mode, &crtc->desiredMode))
break;
@@ -835,35 +1077,33 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn)
DisplayModePtr target_mode = NULL;
xf86CrtcPtr *crtcs;
DisplayModePtr *modes;
- int width, height;
-
- xf86ProbeOutputModes (pScrn);
+ Bool *enabled;
+ int width;
+ int height;
- if (pScrn->display->virtualX == 0)
- {
- /*
- * Expand virtual size to cover potential mode switches
- */
- xf86DefaultScreenLimits (pScrn, &width, &height);
-
- pScrn->display->virtualX = width;
- pScrn->display->virtualY = height;
- }
- else
- {
+ if (pScrn->display->virtualX)
width = pScrn->display->virtualX;
+ else
+ width = config->maxWidth;
+ if (pScrn->display->virtualY)
height = pScrn->display->virtualY;
- }
- if (width > pScrn->virtualX)
- pScrn->virtualX = width;
- if (height > pScrn->virtualY)
- pScrn->virtualY = height;
-
+ else
+ height = config->maxHeight;
+
+ xf86ProbeOutputModes (pScrn, width, height);
+
crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
+ enabled = xnfcalloc (config->num_output, sizeof (Bool));
for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
modes[o] = NULL;
+ enabled[o] = (xf86OutputEnabled (output) &&
+ output->status != XF86OutputStatusDisconnected);
+ }
/*
* Let outputs with preferred modes drive screen size
@@ -872,7 +1112,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn)
{
xf86OutputPtr output = config->output[o];
- if (output->status != XF86OutputStatusDisconnected &&
+ if (enabled[o] &&
xf86OutputHasPreferredMode (output, width, height))
{
target_mode = xf86DefaultMode (output, width, height);
@@ -889,7 +1129,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn)
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
- if (output->status != XF86OutputStatusDisconnected)
+ if (enabled[o])
{
target_mode = xf86DefaultMode (output, width, height);
if (target_mode)
@@ -905,10 +1145,23 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn)
{
xf86OutputPtr output = config->output[o];
- if (output->status != XF86OutputStatusDisconnected && !modes[o])
+ if (enabled[o] && !modes[o])
modes[o] = xf86ClosestMode (output, target_mode, width, height);
}
+ /*
+ * Set the position of each output
+ */
+ if (!xf86InitialOutputPositions (pScrn, modes))
+ {
+ xfree (crtcs);
+ xfree (modes);
+ return FALSE;
+ }
+
+ /*
+ * Assign CRTCs to fit output configuration
+ */
if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height))
{
xfree (crtcs);
@@ -928,7 +1181,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn)
crtc->enabled = FALSE;
memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
}
-
+
/*
* Set initial configuration
*/
@@ -942,13 +1195,28 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn)
{
crtc->desiredMode = *mode;
crtc->enabled = TRUE;
- crtc->x = 0;
- crtc->y = 0;
+ crtc->x = output->initial_x;
+ crtc->y = output->initial_y;
output->crtc = crtc;
- /* XXX set position; for now, we clone */
}
}
+ if (pScrn->display->virtualX == 0)
+ {
+ /*
+ * Expand virtual size to cover potential mode switches
+ */
+ xf86DefaultScreenLimits (pScrn, &width, &height);
+
+ pScrn->display->virtualX = width;
+ pScrn->display->virtualY = height;
+ }
+
+ if (width > pScrn->virtualX)
+ pScrn->virtualX = width;
+ if (height > pScrn->virtualY)
+ pScrn->virtualY = height;
+
/* Mirror output modes to pScrn mode list */
xf86SetScrnInfoModes (pScrn);
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index b30003e7..8fea162e 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -89,6 +89,11 @@ typedef struct _xf86CrtcFuncs {
DisplayModePtr mode,
DisplayModePtr adjusted_mode);
+ /* Set the color ramps for the CRTC to the given values. */
+ void
+ (*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+ int size);
+
/**
* Clean up driver-specific bits of the crtc
*/
@@ -289,6 +294,16 @@ struct _xf86Output {
DisplayModePtr probed_modes;
/**
+ * Options parsed from the related monitor section
+ */
+ OptionInfoPtr options;
+
+ /**
+ * Configured monitor section
+ */
+ XF86ConfMonitorPtr conf_monitor;
+
+ /**
* Desired initial position
*/
int initial_x, initial_y;
@@ -313,12 +328,6 @@ struct _xf86Output {
/** Output name */
char *name;
- /** Configured monitor name */
- char *monitor_name;
-
- /** Monitor information from config file */
- XF86ConfMonitorPtr conf_monitor;
-
/** output-specific functions */
const xf86OutputFuncsRec *funcs;
@@ -410,14 +419,14 @@ xf86OutputCreate (ScrnInfoPtr scrn,
const xf86OutputFuncsRec *funcs,
const char *name);
-void
+Bool
xf86OutputRename (xf86OutputPtr output, const char *name);
void
xf86OutputDestroy (xf86OutputPtr output);
void
-xf86ProbeOutputModes (ScrnInfoPtr pScrn);
+xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY);
void
xf86SetScrnInfoModes (ScrnInfoPtr pScrn);