diff options
author | Eric Anholt <eric@anholt.net> | 2007-01-02 16:57:33 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2007-01-03 09:56:19 -0800 |
commit | 394124ceaadb46d976ad5c3bdeb1b77d351c57f6 (patch) | |
tree | 645f082c8e924b7a451522e7bcc910ee5d8acf07 /src | |
parent | 69f250af60220a875f4a04c6d682bffa352281e4 (diff) |
Add per-CRTC gamma control support for RandR.
This makes the CRTCs now always run in gamma-enabled mode, rather than having
flaky logic for switching modes. Also, it should clear up issues with the LUTs
being uninitialized when outputs are first brought up.
Diffstat (limited to 'src')
-rw-r--r-- | src/i830.h | 4 | ||||
-rw-r--r-- | src/i830_cursor.c | 8 | ||||
-rw-r--r-- | src/i830_display.c | 60 | ||||
-rw-r--r-- | src/i830_display.h | 1 | ||||
-rw-r--r-- | src/i830_driver.c | 127 | ||||
-rw-r--r-- | src/i830_randr.c | 12 | ||||
-rw-r--r-- | src/i830_xf86Crtc.h | 5 |
7 files changed, 118 insertions, 99 deletions
@@ -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 d124ba0a..f47a9dbf 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -536,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; @@ -718,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) @@ -736,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 @@ -840,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. * @@ -1147,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 */ }; @@ -1155,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) @@ -1163,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_driver.c b/src/i830_driver.c index 694c96f3..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 diff --git a/src/i830_randr.c b/src/i830_randr.c index 83cf0238..533322b2 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -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; } /** diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 2555c55d..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 */ |