From f21230d3e1cc5470e8f88404b5d9f1702bec44bb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 1 Dec 2006 12:48:57 -0800 Subject: [PATCH 01/26] Add the [ax]4r4g4b4 source picture formats. --- src/i915_exa_render.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c index eae8171e..daffa0c6 100644 --- a/src/i915_exa_render.c +++ b/src/i915_exa_render.c @@ -116,6 +116,8 @@ static struct formatinfo I915TexFormats[] = { {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565 }, {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 }, {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 }, + {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 }, + {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 }, {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8 }, }; From a504e31f0fefdec802ae403573f52fac3d577b65 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 1 Dec 2006 12:49:43 -0800 Subject: [PATCH 02/26] Don't try to write the read-only PP_STATUS register. Also, don't bother reading the PP_CONTROL register to try to get LVDS status -- that's what PP_STATUS is for. --- src/i830_lvds.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/i830_lvds.c b/src/i830_lvds.c index bfb4e148..cf709569 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -50,12 +50,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) pI830->backlight_duty_cycle = backlight_duty_cycle; if (on) { - OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); do { pp_status = INREG(PP_STATUS); - pp_control = INREG(PP_CONTROL); - } while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON)); + } while ((pp_status & PP_ON) == 0); OUTREG(BLC_PWM_CTL, (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) | pI830->backlight_duty_cycle); @@ -63,12 +61,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) OUTREG(BLC_PWM_CTL, (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK)); - OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); do { pp_status = INREG(PP_STATUS); - pp_control = INREG(PP_CONTROL); - } while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON)); + } while (pp_status & PP_ON); } } From 81dde11d419c8f9198ab3502d9813d66d0bc6d6d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 1 Dec 2006 10:37:19 -0800 Subject: [PATCH 03/26] Fix copy'n'paste-o from restructure-outputs that resulted in crashes. Our driver private is stored in the bus that we set up, not the DDC device that xf86 code does. --- src/i830_sdvo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index aa061828..c75800d4 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -823,7 +823,7 @@ i830_sdvo_get_capabilities(xf86OutputPtr output, struct i830_sdvo_caps *caps) static Bool i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last) { - xf86OutputPtr output = d->DriverPrivate.ptr; + xf86OutputPtr output = d->pI2CBus->DriverPrivate.ptr; I830OutputPrivatePtr intel_output = output->driver_private; I2CBusPtr i2cbus = intel_output->pI2CBus, savebus; Bool ret; @@ -840,7 +840,7 @@ i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last) static Bool i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c) { - xf86OutputPtr output = d->DriverPrivate.ptr; + xf86OutputPtr output = d->pI2CBus->DriverPrivate.ptr; I830OutputPrivatePtr intel_output = output->driver_private; I2CBusPtr i2cbus = intel_output->pI2CBus, savebus; Bool ret; @@ -875,7 +875,7 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout) static void i830_sdvo_ddc_i2c_stop(I2CDevPtr d) { - xf86OutputPtr output = d->DriverPrivate.ptr; + xf86OutputPtr output = d->pI2CBus->DriverPrivate.ptr; I830OutputPrivatePtr intel_output = output->driver_private; I2CBusPtr i2cbus = intel_output->pI2CBus, savebus; From 8fcf9a81179ee8577ddab5e904c58fbfd14cf59c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Dec 2006 22:58:31 -0800 Subject: [PATCH 04/26] DOUBLE_WIDE mode for high pixel clock 8xx. Rewrite PLL search. High pixel clock modes on pipe A of an 8xx chip require DOUBLE_WIDE mode. It's supposed to be modes > 180MHz or so, but the board I have requires DOUBLE_WIDE mode for clocks > 108MHz or so. The limit is related to the core clock speed of the chip, which can be found indirectly through PCI config space. None of the possible values explain why this board needs this mode for these relatively low clock rates though. Also, create tables of data for the PLL computation and use them instead of code. I think it's cleaner looking. It is also untested on 9xx. It'll work. Really. --- src/i830_display.c | 417 ++++++++++++++++++++++++++++----------------- src/i830_randr.c | 2 +- 2 files changed, 265 insertions(+), 154 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 29b783bf..ac56528a 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -43,21 +43,179 @@ #include "i830_debug.h" #include "i830_xf86Modes.h" -/** Returns the pixel clock for the given refclk and divisors. */ -static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2) +typedef struct { + /* given values */ + int n; + int m1, m2; + int p1, p2; + /* derived values */ + int dot; + int vco; + int m; + int p; +} intel_clock_t; + +typedef struct { + int min, max; +} intel_range_t; + +typedef struct { + int dot_limit; + int p2_slow, p2_fast; +} intel_p2_t; + +#define INTEL_P2_NUM 2 + +typedef struct { + intel_range_t dot, vco, n, m, m1, m2, p, p1; + intel_p2_t p2; +} intel_limit_t; + +#define I8XX_DOT_MIN 25000 +#define I8XX_DOT_MAX 350000 +#define I8XX_VCO_MIN 930000 +#define I8XX_VCO_MAX 1400000 +#define I8XX_N_MIN 3 +#define I8XX_N_MAX 16 +#define I8XX_M_MIN 96 +#define I8XX_M_MAX 140 +#define I8XX_M1_MIN 18 +#define I8XX_M1_MAX 26 +#define I8XX_M2_MIN 6 +#define I8XX_M2_MAX 16 +#define I8XX_P_MIN 4 +#define I8XX_P_MAX 128 +#define I8XX_P1_MIN 0 +#define I8XX_P1_MAX 30 +#define I8XX_P2_SLOW 1 +#define I8XX_P2_FAST 0 +#define I8XX_P2_SLOW_LIMIT 165000 + +#define I9XX_DOT_MIN 20000 +#define I9XX_DOT_MAX 400000 +#define I9XX_VCO_MIN 1400000 +#define I9XX_VCO_MAX 2800000 +#define I9XX_N_MIN 3 +#define I9XX_N_MAX 8 +#define I9XX_M_MIN 70 +#define I9XX_M_MAX 120 +#define I9XX_M1_MIN 10 +#define I9XX_M1_MAX 20 +#define I9XX_M2_MIN 5 +#define I9XX_M2_MAX 9 +#define I9XX_P_SDVO_DAC_MIN 5 +#define I9XX_P_SDVO_DAC_MAX 80 +#define I9XX_P_LVDS_MIN 7 +#define I9XX_P_LVDS_MAX 98 +#define I9XX_P1_MIN 1 +#define I9XX_P1_MAX 8 +#define I9XX_P2_SDVO_DAC_SLOW 10 +#define I9XX_P2_SDVO_DAC_FAST 5 +#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 +#define I9XX_P2_LVDS_SLOW 14 +#define I9XX_P2_LVDS_FAST 7 +#define I9XX_P2_LVDS_SLOW_LIMIT 112000 + +#define INTEL_LIMIT_I8XX 0 +#define INTEL_LIMIT_I9XX_SDVO_DAC 1 +#define INTEL_LIMIT_I9XX_LVDS 2 + +static const intel_limit_t intel_limits[] = { + { + .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, + .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, + .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, + .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, + .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, + .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, + .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, + .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX }, + .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, + .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, + }, + { + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, + .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, + .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, + }, + { + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, + .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + /* The single-channel range is 25-112Mhz, and dual-channel + * is 80-224Mhz. Prefer single channel as much as possible. + */ + .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, + .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, + }, +}; + +static const intel_limit_t *intel_limit (xf86CrtcPtr crtc) { - return refclk * (5 * m1 + m2) / n / (p1 * p2); + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + const intel_limit_t *limit; + + if (IS_I9XX(pI830)) + { + if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) + limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; + else + limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; + } + else + limit = &intel_limits[INTEL_LIMIT_I8XX]; + return limit; +} + +/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ + +static void i8xx_clock(int refclk, intel_clock_t *clock) +{ + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); + clock->p = (clock->p1 + 2) << (clock->p2 + 1); + clock->vco = refclk * clock->m / (clock->n + 2); + clock->dot = clock->vco / clock->p; +} + +/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ + +static void i9xx_clock(int refclk, intel_clock_t *clock) +{ + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); + clock->p = clock->p1 * clock->p2; + clock->vco = refclk * clock->m / (clock->n + 2); + clock->dot = clock->vco / clock->p; +} + +static void intel_clock(I830Ptr pI830, int refclk, intel_clock_t *clock) +{ + if (IS_I9XX(pI830)) + return i9xx_clock (refclk, clock); + else + return i8xx_clock (refclk, clock); } static void -i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) +i830PrintPll(char *prefix, intel_clock_t *clock) { - int dotclock; - - dotclock = i830_clock(refclk, m1, m2, n, p1, p2); - - ErrorF("%s: dotclock %d ((%d, %d), %d, (%d, %d))\n", prefix, dotclock, - m1, m2, n, p1, p2); + ErrorF("%s: dotclock %d vco %d ((m %d, m1 %d, m2 %d), n %d, (p %d, p1 %d, p2 %d))\n", + prefix, clock->dot, clock->vco, + clock->m, clock->m1, clock->m2, + clock->n, + clock->p, clock->p1, clock->p2); } /** @@ -83,90 +241,38 @@ i830PipeHasType (xf86CrtcPtr crtc, int type) return FALSE; } +#define i830PllInvalid(s) { /* ErrorF (s) */; return FALSE; } /** * Returns whether the given set of divisors are valid for a given refclk with * the given outputs. - * - * The equation for these divisors would be: - * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ + static Bool -i830PllIsValid(xf86CrtcPtr crtc, int refclk, int m1, int m2, - int n, int p1, int p2) +i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock) { - ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); - int p, m, vco, dotclock; - int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n; - int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot; + const intel_limit_t *limit = intel_limit (crtc); - if (IS_I9XX(pI830)) { - min_m1 = 10; - max_m1 = 20; - min_m2 = 5; - max_m2 = 9; - min_m = 70; - max_m = 120; - min_n = 3; - max_n = 8; - min_p1 = 1; - max_p1 = 8; - if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) { - min_p = 7; - max_p = 98; - } else { - min_p = 5; - max_p = 80; - } - min_vco = 1400000; - max_vco = 2800000; - min_dot = 20000; - max_dot = 400000; - } else { - min_m1 = 18; - max_m1 = 26; - min_m2 = 6; - max_m2 = 16; - min_m = 96; - max_m = 140; - min_n = 3; - max_n = 16; - min_p1 = 2; - max_p1 = 18; - min_vco = 930000; - max_vco = 1400000; - min_dot = 20000; - max_dot = 350000; - min_p = 4; - max_p = 128; - } - - p = p1 * p2; - m = 5 * m1 + m2; - vco = refclk * m / n; - dotclock = i830_clock(refclk, m1, m2, n, p1, p2); - - if (p1 < min_p1 || p1 > max_p1) - return FALSE; - if (p < min_p || p > max_p) - return FALSE; - if (m2 < min_m2 || m2 > max_m2) - return FALSE; - if (m1 < min_m1 || m1 > max_m1) - return FALSE; - if (m1 <= m2) - return FALSE; - if (m < min_m || m > max_m) - return FALSE; - if (n < min_n || n > max_n) - return FALSE; - if (vco < min_vco || vco > max_vco) - return FALSE; + if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) + i830PllInvalid ("p1 out of range\n"); + if (clock->p < limit->p.min || limit->p.max < clock->p) + i830PllInvalid ("p out of range\n"); + if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) + i830PllInvalid ("m2 out of range\n"); + if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) + i830PllInvalid ("m1 out of range\n"); + if (clock->m1 <= clock->m2) + i830PllInvalid ("m1 <= m2\n"); + if (clock->m < limit->m.min || limit->m.max < clock->m) + i830PllInvalid ("m out of range\n"); + if (clock->n < limit->n.min || limit->n.max < clock->n) + i830PllInvalid ("n out of range\n"); + if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) + i830PllInvalid ("vco out of range\n"); /* XXX: We may need to be checking "Dot clock" depending on the multiplier, * output, etc., rather than just a single range. */ - if (dotclock < min_dot || dotclock > max_dot) - return FALSE; + if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) + i830PllInvalid ("dot out of range\n"); return TRUE; } @@ -174,83 +280,47 @@ i830PllIsValid(xf86CrtcPtr crtc, int refclk, int m1, int m2, /** * Returns a set of divisors for the desired target clock with the given refclk, * or FALSE. Divisor values are the actual divisors for - * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ static Bool -i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, - int *outm1, int *outm2, int *outn, int *outp1, int *outp2) +i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_clock) { ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - int m1, m2, n, p1, p2; + intel_clock_t clock; + const intel_limit_t *limit = intel_limit (crtc); int err = target; - int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1; - if (IS_I9XX(pI830)) { - min_m1 = 10; - max_m1 = 20; - min_m2 = 5; - max_m2 = 9; - min_n = 3; - max_n = 8; - min_p1 = 1; - max_p1 = 8; - if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) { - /* The single-channel range is 25-112Mhz, and dual-channel - * is 80-224Mhz. Prefer single channel as much as possible. - */ - if (target < 112000) - p2 = 14; - else - p2 = 7; - } else { - if (target < 200000) - p2 = 10; - else - p2 = 5; - } - } else { - min_m1 = 18; - max_m1 = 26; - min_m2 = 6; - max_m2 = 16; - min_n = 3; - max_n = 16; - min_p1 = 2; - max_p1 = 18; - if (target < 165000) - p2 = 4; - else - p2 = 2; - } + if (target < limit->p2.dot_limit) + clock.p2 = limit->p2.p2_slow; + else + clock.p2 = limit->p2.p2_fast; + memset (best_clock, 0, sizeof (*best_clock)); - for (m1 = min_m1; m1 <= max_m1; m1++) { - for (m2 = min_m2; m2 < max_m2; m2++) { - for (n = min_n; n <= max_n; n++) { - for (p1 = min_p1; p1 <= max_p1; p1++) { - int clock, this_err; + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) + { + for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && clock.m2 < limit->m2.max; clock.m2++) + { + for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) + { + for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++) + { + int this_err; - if (!i830PllIsValid(crtc, refclk, m1, m2, n, - p1, p2)) { + intel_clock (pI830, refclk, &clock); + + if (!i830PllIsValid(crtc, &clock)) continue; - } - clock = i830_clock(refclk, m1, m2, n, p1, p2); - this_err = abs(clock - target); + this_err = abs(clock.dot - target); if (this_err < err) { - *outm1 = m1; - *outm2 = m2; - *outn = n; - *outp1 = p1; - *outp2 = p2; + *best_clock = clock; err = this_err; } } } } } - return (err != target); } @@ -424,7 +494,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; - int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; + intel_clock_t clock; CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; CARD32 pipesrc, dspsize; @@ -446,6 +516,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; + int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT; Bool ret = FALSE; #ifdef XF86DRI Bool didLock = FALSE; @@ -572,8 +643,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, } else { refclk = 48000; } - ok = i830FindBestPLL(crtc, pixel_clock, refclk, &m1, &m2, &n, - &p1, &p2); + + ok = i830FindBestPLL(crtc, pixel_clock, refclk, &clock); if (!ok) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't find PLL settings for mode!\n"); @@ -586,8 +657,9 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, dpll |= DPLLB_MODE_LVDS; else dpll |= DPLLB_MODE_DAC_SERIAL; - dpll |= (1 << (p1 - 1)) << 16; - switch (p2) { + /* compute bitmask from p1 value */ + dpll |= (1 << (clock.p1 - 1)) << 16; + switch (clock.p2) { case 5: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; break; @@ -604,9 +676,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, if (IS_I965G(pI830)) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); } else { - dpll |= (p1 - 2) << 16; - if (p2 == 4) - dpll |= PLL_P2_DIVIDE_BY_4; + dpll |= clock.p1 << 16; + dpll |= clock.p2 << 23; } if (is_tv) @@ -622,7 +693,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, else dpll |= PLL_REF_INPUT_DREFCLK; - fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; #if 1 ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n", @@ -638,7 +709,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, (int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1); #endif - i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); + i830PrintPll("chosen", &clock); ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); dspcntr = DISPLAY_PLANE_ENABLE; @@ -714,13 +785,53 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, /* Then, turn the pipe on first */ temp = INREG(pipeconf_reg); - OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); + temp |= PIPEACONF_ENABLE; + if (!IS_I9XX(pI830) && pipe == 0) + { + /* + * The docs say this is needed when the dot clock is > 90% of the + * core speed. Core speeds are indicated by bits in the PCI + * config space and don't seem to ever be less than 200MHz, + * which is a bit confusing. + * + * However, For one little 855/852 card I have, 135000 requires + * double wide mode, but 108000 does not. That makes no sense + * but we're used to that. It may be affected by pixel size, + * but the BIOS mode setting code doesn't appear to use that. + * + * It doesn't seem to cause any harm, although it + * does restrict some output options. + */ + if (pixel_clock > 108000) + temp |= PIPEACONF_DOUBLE_WIDE; + else + temp &= ~PIPEACONF_DOUBLE_WIDE; + } + OUTREG(pipeconf_reg, temp); if (plane_enable) { /* And then turn the plane on */ OUTREG(dspcntr_reg, dspcntr); } +#if 0 + /* + * If the display isn't solid, it may be running out + * of memory bandwidth. This code will dump out the + * pipe status, if bit 31 is on, the fifo underran + */ + for (i = 0; i < 4; i++) { + i830WaitForVblank(pScrn); + + OUTREG(pipestat_reg, INREG(pipestat_reg) | 0x80000000); + + i830WaitForVblank(pScrn); + + temp = INREG(pipestat_reg); + ErrorF ("pipe status 0x%x\n", temp); + } +#endif + crtc->curMode = *pMode; ret = TRUE; diff --git a/src/i830_randr.c b/src/i830_randr.c index 373403f8..da8d7460 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -710,7 +710,7 @@ xf86RandR12SetInfo12 (ScrnInfoPtr pScrn) subpixel = SubPixelHorizontalRGB; break; case I830_OUTPUT_ANALOG: - crtc_types = ((1 << 0) | (1 << 1)); + crtc_types = ((1 << 0)); clone_types = ((1 << I830_OUTPUT_ANALOG) | (1 << I830_OUTPUT_DVO) | (1 << I830_OUTPUT_SDVO)); From 2e8c927f9308069a82f25b65bb0c62bc5a156832 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Dec 2006 14:02:30 -0800 Subject: [PATCH 05/26] Re-create RandR Crtc/output structures on server regen. RandR structures must be re-created when the server reinitializes, but the driver PreInit function is not re-invoked. Recreate them manually in this case during ScreenInit. --- src/i830_driver.c | 1 + src/i830_randr.c | 3 +++ src/i830_xf86Crtc.c | 58 +++++++++++++++++++++++++++++++++++++++++++-- src/i830_xf86Crtc.h | 6 +++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 3aafe3aa..c85fe4e6 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3805,6 +3805,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) DPRINTF(PFX, "\nUnmapping memory\n"); I830UnmapMem(pScrn); vgaHWUnmapMem(pScrn); + xf86CrtcCloseScreen (pScreen); if (pI830->ScanlineColorExpandBuffers) { xfree(pI830->ScanlineColorExpandBuffers); diff --git a/src/i830_randr.c b/src/i830_randr.c index da8d7460..00770201 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -900,6 +900,9 @@ xf86RandR12Init12 (ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; rrScrPrivPtr rp = rrGetScrPriv(pScreen); + if (xf86CrtcScreenInit (pScreen)) + return FALSE; + rp->rrGetInfo = xf86RandR12GetInfo12; rp->rrScreenSetSize = xf86RandR12ScreenSetSize; rp->rrCrtcSet = xf86RandR12CrtcSet; diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 2eb775bf..7eb581c9 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -68,7 +68,8 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) (*crtc->funcs->destroy) (crtc); #ifdef RANDR_12_INTERFACE - RRCrtcDestroy (crtc->randr_crtc); + if (crtc->randr_crtc) + RRCrtcDestroy (crtc->randr_crtc); #endif for (c = 0; c < xf86_config->num_crtc; c++) if (xf86_config->crtc[c] == crtc) @@ -122,7 +123,8 @@ xf86OutputDestroy (xf86OutputPtr output) (*output->funcs->destroy) (output); #ifdef RANDR_12_INTERFACE - RROutputDestroy (output->randr_output); + if (output->randr_output) + RROutputDestroy (output->randr_output); #endif while (output->probed_modes) xf86DeleteMode (&output->probed_modes, output->probed_modes); @@ -138,3 +140,55 @@ xf86OutputDestroy (xf86OutputPtr output) xfree (output); } +Bool +xf86CrtcScreenInit (ScreenPtr pScreen) +{ +#ifdef RANDR_12_INTERFACE + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for (i = 0; i < xf86_config->num_crtc; i++) + { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + if (!crtc->randr_crtc) + crtc->randr_crtc = RRCrtcCreate (crtc); + if (!crtc->randr_crtc) + return FALSE; + } + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + + if (!output->randr_output) + output->randr_output = RROutputCreate (output->name, + strlen (output->name), + output); + if (!output->randr_output) + return FALSE; + } +#endif + return TRUE; +} + +void +xf86CrtcCloseScreen (ScreenPtr pScreen) +{ +#ifdef RANDR_12_INTERFACE + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for (i = 0; i < xf86_config->num_crtc; i++) + { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + crtc->randr_crtc = NULL; + } + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + output->randr_output = NULL; + } +#endif +} diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 2952c8d5..21ba1fcf 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -307,4 +307,10 @@ xf86OutputCreate (ScrnInfoPtr scrn, void xf86OutputDestroy (xf86OutputPtr output); +Bool +xf86CrtcScreenInit (ScreenPtr pScreen); + +void +xf86CrtcCloseScreen (ScreenPtr pScreen); + #endif /* _XF86CRTC_H_ */ From e777d38ce98d7220621b049b09df1deca5a5df42 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 5 Dec 2006 10:01:31 -0800 Subject: [PATCH 06/26] WIP code to move mode set sequencing to XFree86 handlers. It compiles. It definitely doesn't run. --- src/i830_crt.c | 20 +- src/i830_display.c | 440 +++++++++++++++++++++++++------------------- src/i830_display.h | 1 + src/i830_driver.c | 67 +++---- src/i830_dvo.c | 49 +++-- src/i830_lvds.c | 105 ++++++++--- src/i830_sdvo.c | 53 +++--- src/i830_tv.c | 35 +++- src/i830_xf86Crtc.h | 56 ++++-- 9 files changed, 494 insertions(+), 332 deletions(-) diff --git a/src/i830_crt.c b/src/i830_crt.c index 7a706d14..ebd83bc4 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -93,13 +93,16 @@ i830_crt_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) return MODE_OK; } -static void -i830_crt_pre_set_mode (xf86OutputPtr output, DisplayModePtr pMode) +static Bool +i830_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { + return TRUE; } static void -i830_crt_post_set_mode (xf86OutputPtr output, DisplayModePtr pMode) +i830_crt_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); @@ -122,11 +125,10 @@ i830_crt_post_set_mode (xf86OutputPtr output, DisplayModePtr pMode) OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); } - adpa = ADPA_DAC_ENABLE; - - if (pMode->Flags & V_PHSYNC) + adpa = 0; + if (adjusted_mode->Flags & V_PHSYNC) adpa |= ADPA_HSYNC_ACTIVE_HIGH; - if (pMode->Flags & V_PVSYNC) + if (adjusted_mode->Flags & V_PVSYNC) adpa |= ADPA_VSYNC_ACTIVE_HIGH; if (i830_crtc->pipe == 0) @@ -372,8 +374,8 @@ static const xf86OutputFuncsRec i830_crt_output_funcs = { .save = i830_crt_save, .restore = i830_crt_restore, .mode_valid = i830_crt_mode_valid, - .pre_set_mode = i830_crt_pre_set_mode, - .post_set_mode = i830_crt_post_set_mode, + .mode_fixup = i830_crt_mode_fixup, + .mode_set = i830_crt_mode_set, .detect = i830_crt_detect, .get_modes = i830_crt_get_modes, .destroy = i830_crt_destroy diff --git a/src/i830_display.c b/src/i830_display.c index 29b783bf..eab82f6e 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -408,34 +408,94 @@ i830PipeInUse (xf86CrtcPtr crtc) return FALSE; } -/** - * Sets the given video mode on the given pipe. - * - * Plane A is always output to pipe A, and plane B to pipe B. The plane - * will not be enabled if plane_enable is FALSE, which is used for - * load detection, when something else will be output to the pipe other than - * display data. - */ -Bool -i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, - Bool plane_enable) +static void +i830_crtc_dpms(xf86CrtcPtr crtc, int mode) { ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; - int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; - CARD32 dpll = 0, fp = 0, temp; - CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; - CARD32 pipesrc, dspsize; - Bool ok, is_sdvo = FALSE, is_dvo = FALSE; - Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE; - int refclk, pixel_clock; - int i; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + CARD32 temp; + + /* XXX: When our outputs are all unaware of DPMS modes other than off and + * on, we should map those modes to DPMSModeOff in the CRTC. + */ + switch (mode) { + case DPMSModeOn: + case DPMSModeStandby: + case DPMSModeSuspend: + /* Enable the DPLL */ + temp = INREG(dpll_reg); + OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); + + /* Wait for the clocks to stabilize. */ + usleep(150); + + /* Enable the pipe */ + temp = INREG(pipeconf_reg); + OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); + + /* Enable the plane */ + temp = INREG(dspcntr_reg); + OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); + break; + case DPMSModeOff: + /* Disable display plane */ + temp = INREG(dspcntr_reg); + OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); + + /* Disable the VGA plane that we never use */ + OUTREG(VGACNTRL, VGA_DISP_DISABLE); + + if (!IS_I9XX(pI830)) { + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + } + + /* Next, disable display pipes */ + temp = INREG(pipeconf_reg); + OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + + /* Wait for vblank for the disable to take effect. */ + i830WaitForVblank(pScrn); + + temp = INREG(dpll_reg); + OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE); + break; + } +} + +static Bool +i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +/** + * Sets up registers for the given mode/adjusted_mode pair. + * + * The clocks, CRTCs and outputs attached to this CRTC must be off. + * + * This shouldn't enable any clocks, CRTCs, or outputs, but they should + * be easily turned on/off after this. + */ +static void +i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; int fp_reg = (pipe == 0) ? FPA0 : FPB0; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; @@ -446,38 +506,23 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; - Bool ret = FALSE; -#ifdef XF86DRI - Bool didLock = FALSE; -#endif + int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; + int i; + int refclk; + CARD32 dpll = 0, fp = 0, temp, dspcntr; + Bool ok, is_sdvo = FALSE, is_dvo = FALSE; + Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE; - if (xf86ModesEqual(&crtc->curMode, pMode)) - return TRUE; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n", - pMode->Clock); - - crtc->enabled = i830PipeInUse (crtc); - - if (!crtc->enabled) - { - /* XXX disable crtc? */ - return TRUE; - } - -#ifdef XF86DRI - didLock = I830DRILock(pScrn); -#endif - - for (i = 0; i < pI830->xf86_config.num_output; i++) - { + /* Set up some convenient bools for what outputs are connected to + * our pipe, used in DPLL setup. + */ + for (i = 0; i < pI830->xf86_config.num_output; i++) { xf86OutputPtr output = pI830->xf86_config.output[i]; - I830OutputPrivatePtr intel_output = output->driver_private; + I830OutputPrivatePtr intel_output = output->driver_private; + if (output->crtc != crtc) continue; - (*output->funcs->pre_set_mode)(output, pMode); - switch (intel_output->type) { case I830_OUTPUT_LVDS: is_lvds = TRUE; @@ -497,90 +542,23 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, } } - if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't enable LVDS and non-LVDS on the same pipe\n"); - goto done; - } - if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't enable a TV and any other output on the same " - "pipe\n"); - goto done; - } - if (pipe == 0 && is_lvds) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't support LVDS on pipe A\n"); - goto done; - } - - htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); - hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); - hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16); - vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16); - vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16); - vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); - pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); - dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); - pixel_clock = pMode->Clock; - - if (is_lvds && pI830->panel_fixed_hactive != 0) { - /* To enable panel fitting, we need to set the pipe timings to that of - * the screen at its full resolution. So, drop the timings from the - * BIOS VBT tables here. - */ - htot = (pI830->panel_fixed_hactive - 1) | - ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) - << 16); - hblank = (pI830->panel_fixed_hactive - 1) | - ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) - << 16); - hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) | - ((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff + - pI830->panel_fixed_hsyncwidth - 1) << 16); - - vtot = (pI830->panel_fixed_vactive - 1) | - ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) - << 16); - vblank = (pI830->panel_fixed_vactive - 1) | - ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) - << 16); - vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) | - ((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff + - pI830->panel_fixed_vsyncwidth - 1) << 16); - pixel_clock = pI830->panel_fixed_clock; - - if (pMode->HDisplay <= pI830->panel_fixed_hactive && - pMode->HDisplay <= pI830->panel_fixed_vactive) - { - pipesrc = ((pMode->HDisplay - 1) << 16) | - (pMode->VDisplay - 1); - dspsize = ((pMode->VDisplay - 1) << 16) | - (pMode->HDisplay - 1); - } - } - - /* Adjust the clock for pixel multiplication. - * See DPLL_MD_UDI_MULTIPLIER_MASK. - */ - if (is_sdvo) { - pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode); - } - if (IS_I9XX(pI830)) { refclk = 96000; } else { refclk = 48000; } - ok = i830FindBestPLL(crtc, pixel_clock, refclk, &m1, &m2, &n, - &p1, &p2); - if (!ok) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't find PLL settings for mode!\n"); - goto done; - } - dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; + ok = i830FindBestPLL(crtc, adjusted_mode->Clock, refclk, &m1, &m2, &n, + &p1, &p2); + if (!ok) + FatalError("Couldn't find PLL settings for mode!\n"); + + fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); + + i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); + ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); + + dpll = DPLL_VGA_MODE_DIS; if (IS_I9XX(pI830)) { if (is_lvds) dpll |= DPLLB_MODE_LVDS; @@ -615,33 +593,15 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ dpll |= 3; } -#if 0 +#if 0 else if (is_lvds) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; #endif - else + else dpll |= PLL_REF_INPUT_DREFCLK; - fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); - -#if 1 - ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n", - (int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1, - (int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1, - (int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1); - ErrorF("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n", - (int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1, - (int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1, - (int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1); - ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n", - (int)(pipesrc >> 16) + 1, (int)(pipesrc & 0xffff) + 1, - (int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1); -#endif - - i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); - ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); - - dspcntr = DISPLAY_PLANE_ENABLE; + /* Set up the display plane register */ + dspcntr = 0; switch (pScrn->bitsPerPixel) { case 8: dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE; @@ -668,61 +628,139 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, else dspcntr |= DISPPLANE_SEL_PIPE_B; - OUTREG(VGACNTRL, VGA_DISP_DISABLE); - - /* Finally, set the mode. */ - /* First, disable display planes */ - temp = INREG(dspcntr_reg); - OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); - - /* Wait for vblank for the disable to take effect */ - i830WaitForVblank(pScrn); - - /* Next, disable display pipes */ - temp = INREG(pipeconf_reg); - OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); - OUTREG(fp_reg, fp); OUTREG(dpll_reg, dpll); - - /* - * If the panel fitter is stuck on our pipe, turn it off. - * The LVDS output will set it as necessary in post_set_mode. - */ - if (!IS_I830(pI830)) { - if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) - OUTREG(PFIT_CONTROL, 0); + if (IS_I965G(pI830)) { + /* Set the SDVO multiplier/divider to 1x for the sake of analog output. + * It will be updated by the SDVO code if SDVO had fixed up the clock + * for a higher multiplier. + */ + OUTREG(dpll_md_reg, 0); } - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - if (output->crtc == crtc) - (*output->funcs->post_set_mode)(output, pMode); - } - - OUTREG(htot_reg, htot); - OUTREG(hblank_reg, hblank); - OUTREG(hsync_reg, hsync); - OUTREG(vtot_reg, vtot); - OUTREG(vblank_reg, vblank); - OUTREG(vsync_reg, vsync); + OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) | + ((adjusted_mode->CrtcHTotal - 1) << 16)); + OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) | + ((adjusted_mode->CrtcHBlankEnd - 1) << 16)); + OUTREG(hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) | + ((adjusted_mode->CrtcHSyncEnd - 1) << 16)); + OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) | + ((adjusted_mode->CrtcVTotal - 1) << 16)); + OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) | + ((adjusted_mode->CrtcVBlankEnd - 1) << 16)); + OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) | + ((adjusted_mode->CrtcVSyncEnd - 1) << 16)); OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp); - OUTREG(dspsize_reg, dspsize); + /* pipesrc and dspsize control the size that is scaled from, which should + * always be the user's requested size. + */ + OUTREG(dspsize_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1)); OUTREG(dsppos_reg, 0); i830PipeSetBase(crtc, crtc->x, crtc->y); - OUTREG(pipesrc_reg, pipesrc); - - /* Then, turn the pipe on first */ + OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1)); temp = INREG(pipeconf_reg); - OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); + OUTREG(pipeconf_reg, temp); + OUTREG(dspcntr_reg, dspcntr); - if (plane_enable) { - /* And then turn the plane on */ - OUTREG(dspcntr_reg, dspcntr); + /* Disable the panel fitter if it was on our pipe */ + if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) + OUTREG(PFIT_CONTROL, 0); +} + +/** + * Sets the given video mode on the given pipe. + * + * Plane A is always output to pipe A, and plane B to pipe B. The plane + * will not be enabled if plane_enable is FALSE, which is used for + * load detection, when something else will be output to the pipe other than + * display data. + */ +Bool +i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, + Bool plane_enable) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + int i; + Bool ret = FALSE; +#ifdef XF86DRI + Bool didLock = FALSE; +#endif + DisplayModePtr adjusted_mode; + + /* XXX: curMode */ + + adjusted_mode = xf86DuplicateMode(pMode); + + crtc->enabled = i830PipeInUse (crtc); + + if (!crtc->enabled) + { + /* XXX disable crtc? */ + return TRUE; + } + +#ifdef XF86DRI + didLock = I830DRILock(pScrn); +#endif + + /* Pass our mode to the outputs and the CRTC to give them a chance to + * adjust it according to limitations or output properties, and also + * a chance to reject the mode entirely. + */ + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr output = pI830->xf86_config.output[i]; + + if (output->crtc != crtc) + continue; + + if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) { + ret = FALSE; + goto done; + } + } + + if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) { + ret = FALSE; + goto done; + } + + /* Disable the outputs and CRTCs before setting the mode. */ + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr output = pI830->xf86_config.output[i]; + + if (output->crtc != crtc) + continue; + + /* Disable the output as the first thing we do. */ + output->funcs->dpms(output, DPMSModeOff); + } + + crtc->funcs->dpms(crtc, DPMSModeOff); + + /* Set up the DPLL and any output state that needs to adjust or depend + * on the DPLL. + */ + crtc->funcs->mode_set(crtc, pMode, adjusted_mode); + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr output = pI830->xf86_config.output[i]; + if (output->crtc == crtc) + output->funcs->mode_set(output, pMode, adjusted_mode); + } + + /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ + crtc->funcs->dpms(crtc, DPMSModeOn); + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr output = pI830->xf86_config.output[i]; + if (output->crtc == crtc) + output->funcs->dpms(output, DPMSModeOn); } crtc->curMode = *pMode; + i830DumpRegs(pScrn); + + /* XXX free adjustedmode */ ret = TRUE; done: #ifdef XF86DRI @@ -962,3 +1000,29 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr output) i830DisableUnusedFunctions(pScrn); } } + +static const xf86CrtcFuncsRec i830_crtc_funcs = { + .dpms = i830_crtc_dpms, + .save = NULL, /* XXX */ + .restore = NULL, /* XXX */ + .mode_fixup = i830_crtc_mode_fixup, + .mode_set = i830_crtc_mode_set, + .destroy = NULL, /* XXX */ +}; + +void +i830_crtc_init(ScrnInfoPtr pScrn, int pipe) +{ + xf86CrtcPtr crtc; + I830CrtcPrivatePtr intel_crtc; + + crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs); + if (crtc == NULL) + return; + + intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1); + intel_crtc->pipe = pipe; + + crtc->driver_private = intel_crtc; +} + diff --git a/src/i830_display.h b/src/i830_display.h index c80c3f72..c1725ab1 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -41,6 +41,7 @@ void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output); void i830ReleaseLoadDetectPipe(xf86OutputPtr output); Bool i830PipeInUse(xf86CrtcPtr crtc); +void i830_crtc_init(ScrnInfoPtr pScrn, int pipe); /** @{ */ diff --git a/src/i830_driver.c b/src/i830_driver.c index 3aafe3aa..8f017ab2 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -715,28 +715,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn) * Setup the CRTCs */ -static const xf86CrtcFuncsRec i830_crtc_funcs = { -}; -static void -I830SetupCrtcs(ScrnInfoPtr pScrn, int num_pipe) -{ - int p; - - for (p = 0; p < num_pipe; p++) - { - xf86CrtcPtr crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs); - I830CrtcPrivatePtr intel_crtc; - - if (!crtc) - break; - intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1); - intel_crtc->pipe = p; - - crtc->driver_private = intel_crtc; - } -} - static void I830PreInitDDC(ScrnInfoPtr pScrn) { @@ -1340,7 +1319,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) I830PreInitDDC(pScrn); I830SetupOutputs(pScrn); - I830SetupCrtcs(pScrn, num_pipe); + for (i = 0; i < num_pipe; i++) { + i830_crtc_init(pScrn, i); + } if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { if (num_pipe == 1) { @@ -2286,7 +2267,13 @@ RestoreHWState(ScrnInfoPtr pScrn) vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); - /* First, disable display planes */ + /* Disable outputs */ + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr output = pI830->xf86_config.output[i]; + output->funcs->dpms(output, DPMSModeOff); + } + + /* Disable display planes */ temp = INREG(DSPACNTR); OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); temp = INREG(DSPBCNTR); @@ -2298,12 +2285,6 @@ RestoreHWState(ScrnInfoPtr pScrn) temp = INREG(PIPEBCONF); OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); - /* Disable outputs if necessary */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - (*output->funcs->pre_set_mode) (output, NULL); - } - i830WaitForVblank(pScrn); OUTREG(FPA0, pI830->saveFPA0); @@ -2311,6 +2292,16 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DPLL_A, pI830->saveDPLL_A); if (IS_I965G(pI830)) OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD); + if(pI830->xf86_config.num_crtc == 2) { + OUTREG(FPB0, pI830->saveFPB0); + OUTREG(FPB1, pI830->saveFPB1); + OUTREG(DPLL_B, pI830->saveDPLL_B); + if (IS_I965G(pI830)) + OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); + } + /* Wait for clocks to stabilize */ + usleep(150); + OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); OUTREG(HBLANK_A, pI830->saveHBLANK_A); OUTREG(HSYNC_A, pI830->saveHSYNC_A); @@ -2327,11 +2318,6 @@ RestoreHWState(ScrnInfoPtr pScrn) } if(pI830->xf86_config.num_crtc == 2) { - OUTREG(FPB0, pI830->saveFPB0); - OUTREG(FPB1, pI830->saveFPB1); - OUTREG(DPLL_B, pI830->saveDPLL_B); - if (IS_I965G(pI830)) - OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); OUTREG(HBLANK_B, pI830->saveHBLANK_B); OUTREG(HSYNC_B, pI830->saveHSYNC_B); @@ -2348,12 +2334,8 @@ RestoreHWState(ScrnInfoPtr pScrn) } } - OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); - - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - (*output->funcs->restore) (output); - } + if (!IS_I830(pI830) && !IS_845G(pI830)) + OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); if (IS_I965G(pI830)) { OUTREG(DSPASURF, pI830->saveDSPASURF); @@ -2371,6 +2353,11 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPACNTR, pI830->saveDSPACNTR); OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr output = pI830->xf86_config.output[i]; + (*output->funcs->restore) (output); + } + for(i = 0; i < 7; i++) { OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 6fe31575..04d20387 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -59,11 +59,17 @@ struct _I830DVODriver i830_dvo_drivers[] = static void i830_dvo_dpms(xf86OutputPtr output, int mode) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - if (mode == DPMSModeOn) + + if (mode == DPMSModeOn) { + OUTREG(DVOC, INREG(DVOC) | DVO_ENABLE); (*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, TRUE); - else + } else { (*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, FALSE); + OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE); + } } static void @@ -113,48 +119,51 @@ i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) return MODE_BAD; } -static void -i830_dvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode) +static Bool +i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { - ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); - I830OutputPrivatePtr intel_output = output->driver_private; + /* XXX: Hook this up to a DVO driver function */ - (*intel_output->i2c_drv->vid_rec->Mode)(intel_output->i2c_drv->dev_priv, pMode); - - OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE); + return TRUE; } static void -i830_dvo_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) +i830_dvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); xf86CrtcPtr crtc = output->crtc; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + I830OutputPrivatePtr intel_output = output->driver_private; int pipe = intel_crtc->pipe; CARD32 dvo; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + intel_output->i2c_drv->vid_rec->Mode(intel_output->i2c_drv->dev_priv, + mode); + /* Save the data order, since I don't know what it should be set to. */ dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); - dvo |= DVO_ENABLE; dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; if (pipe == 1) dvo |= DVO_PIPE_B_SELECT; - if (pMode->Flags & V_PHSYNC) + if (adjusted_mode->Flags & V_PHSYNC) dvo |= DVO_HSYNC_ACTIVE_HIGH; - if (pMode->Flags & V_PVSYNC) + if (adjusted_mode->Flags & V_PVSYNC) dvo |= DVO_VSYNC_ACTIVE_HIGH; OUTREG(dpll_reg, INREG(dpll_reg) | DPLL_DVO_HIGH_SPEED); - /*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | - (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ - OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | - (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); + /*OUTREG(DVOB_SRCDIM, + (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ + OUTREG(DVOC_SRCDIM, + (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); /*OUTREG(DVOB, dvo);*/ OUTREG(DVOC, dvo); } @@ -222,8 +231,8 @@ static const xf86OutputFuncsRec i830_dvo_output_funcs = { .save = i830_dvo_save, .restore = i830_dvo_restore, .mode_valid = i830_dvo_mode_valid, - .pre_set_mode = i830_dvo_pre_set_mode, - .post_set_mode = i830_dvo_post_set_mode, + .mode_fixup = i830_dvo_mode_fixup, + .mode_set = i830_dvo_mode_set, .detect = i830_dvo_detect, .get_modes = i830_ddc_get_modes, .destroy = i830_dvo_destroy diff --git a/src/i830_lvds.c b/src/i830_lvds.c index cf709569..a9c0e204 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -40,7 +40,7 @@ static void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 pp_status, pp_control; + CARD32 pp_status; CARD32 blc_pwm_ctl; int backlight_duty_cycle; @@ -77,6 +77,8 @@ i830_lvds_dpms (xf86OutputPtr output, int mode) i830SetLVDSPanelPower(pScrn, TRUE); else i830SetLVDSPanelPower(pScrn, FALSE); + + /* XXX: We never power down the LVDS pair. */ } static void @@ -128,28 +130,86 @@ i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) return MODE_OK; } -static void -i830_lvds_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode) +static Bool +i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { - ScrnInfoPtr pScrn = output->scrn; - /* Always make sure the LVDS is off before we play with DPLLs and pipe - * configuration. We can skip this in some cases (for example, going - * between hi-res modes with automatic panel scaling are fine), but be - * conservative for now. + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private; + int i; + + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr other_output = pI830->xf86_config.output[i]; + + if (other_output != output && other_output->crtc == output->crtc) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't enable LVDS and another output on the same " + "pipe\n"); + return FALSE; + } + } + + if (intel_crtc->pipe == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't support LVDS on pipe A\n"); + return FALSE; + } + + /* If we have timings from the BIOS for the panel, put them in + * to the adjusted mode. The CRTC will be set up for this mode, + * with the panel scaling set up to source from the H/VDisplay + * of the original mode. */ - i830SetLVDSPanelPower(pScrn, FALSE); + if (pI830->panel_fixed_hactive != 0) { + adjusted_mode->HDisplay = pI830->panel_fixed_hactive; + adjusted_mode->HTotal = adjusted_mode->HDisplay + + pI830->panel_fixed_hblank; + adjusted_mode->HSyncStart = adjusted_mode->HDisplay + + pI830->panel_fixed_hsyncoff; + adjusted_mode->HSyncStart = adjusted_mode->HSyncStart + + pI830->panel_fixed_hsyncwidth; + adjusted_mode->VDisplay = pI830->panel_fixed_vactive; + adjusted_mode->VTotal = adjusted_mode->VDisplay + + pI830->panel_fixed_hblank; + adjusted_mode->VSyncStart = adjusted_mode->VDisplay + + pI830->panel_fixed_hsyncoff; + adjusted_mode->VSyncStart = adjusted_mode->VSyncStart + + pI830->panel_fixed_hsyncwidth; + adjusted_mode->Clock = pI830->panel_fixed_clock; + xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); + } + + /* XXX: if we don't have BIOS fixed timings (or we have + * a preferred mode from DDC, probably), we should use the + * DDC mode as the fixed timing. + */ + + /* XXX: It would be nice to support lower refresh rates on the + * panels to reduce power consumption, and perhaps match the + * user's requested refresh rate. + */ + + return TRUE; } static void -i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) +i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { - ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); - CARD32 pfit_control; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 pfit_control; + + /* The LVDS pin pair needs to be on before the DPLLs are enabled. + * This is an exception to the general rule that mode_set doesn't turn + * things on. + */ + OUTREG(LVDS, LVDS_PORT_EN | LVDS_PIPEB_SELECT); /* Enable automatic panel scaling so that non-native modes fill the * screen. Should be enabled before the pipe is enabled, according to - * register description. + * register description and PRM. */ pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | @@ -159,19 +219,6 @@ i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) pfit_control |= PANEL_8TO6_DITHER_ENABLE; OUTREG(PFIT_CONTROL, pfit_control); - - /* Disable the PLL before messing with LVDS enable */ - OUTREG(FPB0, INREG(FPB0) & ~DPLL_VCO_ENABLE); - - /* LVDS must be powered on before PLL is enabled and before power - * sequencing the panel. - */ - OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT); - - /* Re-enable the PLL */ - OUTREG(FPB0, INREG(FPB0) | DPLL_VCO_ENABLE); - - i830SetLVDSPanelPower(pScrn, TRUE); } /** @@ -234,8 +281,8 @@ static const xf86OutputFuncsRec i830_lvds_output_funcs = { .save = i830_lvds_save, .restore = i830_lvds_restore, .mode_valid = i830_lvds_mode_valid, - .pre_set_mode = i830_lvds_pre_set_mode, - .post_set_mode = i830_lvds_post_set_mode, + .mode_fixup = i830_lvds_mode_fixup, + .mode_set = i830_lvds_mode_set, .detect = i830_lvds_detect, .get_modes = i830_lvds_get_modes, .destroy = i830_lvds_destroy diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index c75800d4..7755252a 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -534,15 +534,36 @@ i830_sdvo_set_clock_rate_mult(xf86OutputPtr output, CARD8 val) return TRUE; } +static Bool +i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO + * device will be told of the multiplier during mode_set. + */ + adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode); + + return TRUE; +} + static void -i830_sdvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr mode) +i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; - CARD16 width; - CARD16 height; + xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + Bool input1, input2; + CARD32 dpll, sdvox; + int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B; + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; + int sdvo_pixel_multiply; + int i; + CARD8 status; + CARD16 width, height; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; CARD16 h_sync_offset, v_sync_offset; struct i830_sdvo_dtd output_dtd; @@ -633,26 +654,6 @@ i830_sdvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr mode) break; } - OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE); -} - -static void -i830_sdvo_post_set_mode(xf86OutputPtr output, DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = output->scrn; - I830OutputPrivatePtr intel_output = output->driver_private; - struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; - xf86CrtcPtr crtc = output->crtc; - I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - I830Ptr pI830 = I830PTR(pScrn); - Bool input1, input2; - CARD32 dpll, sdvox; - int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B; - int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; - int sdvo_pixel_multiply; - int i; - CARD8 status; - /* Set the SDVO control regs. */ sdvox = INREG(dev_priv->output_device); switch (dev_priv->output_device) { @@ -663,7 +664,7 @@ i830_sdvo_post_set_mode(xf86OutputPtr output, DisplayModePtr mode) sdvox &= SDVOC_PRESERVE_MASK; break; } - sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE; + sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; if (intel_crtc->pipe == 1) sdvox |= SDVO_PIPE_B_SELECT; @@ -1014,8 +1015,8 @@ static const xf86OutputFuncsRec i830_sdvo_output_funcs = { .save = i830_sdvo_save, .restore = i830_sdvo_restore, .mode_valid = i830_sdvo_mode_valid, - .pre_set_mode = i830_sdvo_pre_set_mode, - .post_set_mode = i830_sdvo_post_set_mode, + .mode_fixup = i830_sdvo_mode_fixup, + .mode_set = i830_sdvo_mode_set, .detect = i830_sdvo_detect, .get_modes = i830_ddc_get_modes, .destroy = i830_sdvo_destroy diff --git a/src/i830_tv.c b/src/i830_tv.c index f5716f8b..87aecda6 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -295,8 +295,33 @@ static const CARD32 v_chroma[43] = { 0x28003100, 0x28002F00, 0x00003100, }; +static Bool +i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < pI830->xf86_config.num_output; i++) { + xf86OutputPtr other_output = pI830->xf86_config.output[i]; + + if (other_output != output && other_output->crtc == output->crtc) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't enable TV and another output on the same " + "pipe\n"); + return FALSE; + } + } + + /* XXX: fill me in */ + + return TRUE; +} + static void -i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) +i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); @@ -359,7 +384,7 @@ i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) | (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT); - tv_ctl = TV_ENC_ENABLE; + tv_ctl = 0; if (intel_crtc->pipe == 1) tv_ctl |= TV_ENC_PIPEB_SELECT; @@ -403,7 +428,7 @@ i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; tv_filter_ctl = TV_AUTO_SCALE; - if (pMode->HDisplay > 1024) + if (mode->HDisplay > 1024) tv_ctl |= TV_V_FILTER_BYPASS; OUTREG(TV_H_CTL_1, hctl1); @@ -635,8 +660,8 @@ static const xf86OutputFuncsRec i830_tv_output_funcs = { .save = i830_tv_save, .restore = i830_tv_restore, .mode_valid = i830_tv_mode_valid, - .pre_set_mode = i830_tv_pre_set_mode, - .post_set_mode = i830_tv_post_set_mode, + .mode_fixup = i830_tv_mode_fixup, + .mode_set = i830_tv_mode_set, .detect = i830_tv_detect, .get_modes = i830_tv_get_modes, .destroy = i830_tv_destroy diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 2952c8d5..b5dbe511 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -27,14 +27,15 @@ #include "i830_xf86Modes.h" typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr; +typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr; typedef struct _xf86CrtcFuncs { /** * Turns the crtc on/off, or sets intermediate power levels if available. * * Unsupported intermediate modes drop to the lower power setting. If the - * mode is DPMSModeOff, the crtc must be disabled, as the DPLL may be - * disabled afterwards. + * mode is DPMSModeOff, the crtc must be disabled sufficiently for it to + * be safe to call mode_set. */ void (*dpms)(xf86CrtcPtr crtc, @@ -52,6 +53,27 @@ typedef struct _xf86CrtcFuncs { void (*restore)(xf86CrtcPtr crtc); + + /** + * Callback to adjust the mode to be set in the CRTC. + * + * This allows a CRTC to adjust the clock or even the entire set of + * timings, which is used for panels with fixed timings or for + * buses with clock limitations. + */ + Bool + (*mode_fixup)(xf86CrtcPtr crtc, + DisplayModePtr mode, + DisplayModePtr adjusted_mode); + + /** + * Callback for setting up a video mode after fixups have been made. + */ + void + (*mode_set)(xf86CrtcPtr crtc, + DisplayModePtr mode, + DisplayModePtr adjusted_mode); + /** * Clean up driver-specific bits of the crtc */ @@ -127,8 +149,6 @@ struct _xf86Crtc { #endif }; -typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr; - typedef struct _xf86OutputFuncs { /** * Turns the output on/off, or sets intermediate power levels if available. @@ -157,7 +177,7 @@ typedef struct _xf86OutputFuncs { * Callback for testing a video mode for a given output. * * This function should only check for cases where a mode can't be supported - * on the pipe specifically, and not represent generic CRTC limitations. + * on the output specifically, and not represent generic CRTC limitations. * * \return MODE_OK if the mode is valid, or another MODE_* otherwise. */ @@ -166,22 +186,28 @@ typedef struct _xf86OutputFuncs { DisplayModePtr pMode); /** - * Callback for setting up a video mode before any crtc/dpll changes. + * Callback to adjust the mode to be set in the CRTC. * - * \param pMode the mode that will be set, or NULL if the mode to be set is - * unknown (such as the restore path of VT switching). + * This allows an output to adjust the clock or even the entire set of + * timings, which is used for panels with fixed timings or for + * buses with clock limitations. */ - void - (*pre_set_mode)(xf86OutputPtr output, - DisplayModePtr pMode); + Bool + (*mode_fixup)(xf86OutputPtr output, + DisplayModePtr mode, + DisplayModePtr adjusted_mode); /** - * Callback for setting up a video mode after the DPLL update but before - * the plane is enabled. + * Callback for setting up a video mode after fixups have been made. + * + * This is only called while the output is disabled. The dpms callback + * must be all that's necessary for the output, to turn the output on + * after this function is called. */ void - (*post_set_mode)(xf86OutputPtr output, - DisplayModePtr pMode); + (*mode_set)(xf86OutputPtr output, + DisplayModePtr mode, + DisplayModePtr adjusted_mode); /** * Probe for a connected output, and return detect_status. From 7844e576e71c004ed495bbc31f7bbe890d18b8d9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 5 Dec 2006 14:39:09 -0800 Subject: [PATCH 07/26] Move reg dump from i830PipeSetMode to after we set up the modes with RandR. --- src/i830_display.c | 2 -- src/i830_randr.c | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index eab82f6e..d7d74179 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -758,8 +758,6 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, crtc->curMode = *pMode; - i830DumpRegs(pScrn); - /* XXX free adjustedmode */ ret = TRUE; done: diff --git a/src/i830_randr.c b/src/i830_randr.c index 373403f8..dd70bba3 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -41,6 +41,7 @@ #include "i830_xf86Crtc.h" #include "i830_randr.h" +#include "i830_debug.h" #include "i830_display.h" #include "i830.h" @@ -604,6 +605,8 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, i830PipeSetBase(crtc, x, y); } i830DisableUnusedFunctions (pScrn); + + i830DumpRegs(pScrn); } return xf86RandR12CrtcNotify (randr_crtc); } From 0b4c3e7bff790e1e99ace5036a41e96046335b04 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 5 Dec 2006 14:39:47 -0800 Subject: [PATCH 08/26] Add a bunch of per-register debug code to i830DumpRegs(). --- src/i810_reg.h | 19 ++++ src/i830_debug.c | 258 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 234 insertions(+), 43 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 7312f8a4..d5250245 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -762,6 +762,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PP_STATUS 0x61200 # define PP_ON (1 << 31) +/** + * Indicates that all dependencies of the panel are on: + * + * - PLL enabled + * - pipe enabled + * - LVDS/DVOB/DVOC on + */ +# define PP_READY (1 << 30) +# define PP_SEQUENCE_NONE (0 << 28) +# define PP_SEQUENCE_ON (1 << 28) +# define PP_SEQUENCE_OFF (2 << 28) +# define PP_SEQUENCE_MASK 0x30000000 #define PP_CONTROL 0x61204 # define POWER_TARGET_ON (1 << 0) @@ -796,12 +808,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define DPLL_VGA_MODE_DIS (1 << 28) # define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ # define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +# define DPLL_MODE_MASK (3 << 26) # define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ # define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ # define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ # define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ # define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ # define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +# define DPLL_FPA01_P1_POST_DIV_SHIFT 16 # define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */ # define DPLL_FPA01_P1_POS_DIV_MASK_I830 0x001f0000 /* i830 */ # define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ @@ -809,6 +823,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ # define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */ # define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +# define PLL_REF_INPUT_MASK (3 << 13) # define PLL_LOAD_PULSE_PHASE_SHIFT 9 /* * Parallel to Serial Load Pulse phase selection. @@ -818,6 +833,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ # define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) # define DISPLAY_RATE_SELECT_FPA1 (1 << 8) + /** * SDVO multiplier for 945G/GM. Not used on 965. * @@ -906,8 +922,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FPB0 0x06048 #define FPB1 0x0604c # define FP_N_DIV_MASK 0x003f0000 +# define FP_N_DIV_SHIFT 16 # define FP_M1_DIV_MASK 0x00003f00 +# define FP_M1_DIV_SHIFT 8 # define FP_M2_DIV_MASK 0x0000003f +# define FP_M2_DIV_SHIFT 0 #define PORT_HOTPLUG_EN 0x61110 # define SDVOB_HOTPLUG_INT_EN (1 << 26) diff --git a/src/i830_debug.c b/src/i830_debug.c index d74d0920..97b09830 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -33,13 +33,157 @@ #include "i830.h" #include "i830_debug.h" +#define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val) + +DEBUGSTRING(i830_debug_xyminus1) +{ + return XNFprintf("%d, %d", (val & 0xffff) + 1, + ((val & 0xffff0000) >> 16) + 1); +} + +DEBUGSTRING(i830_debug_xy) +{ + return XNFprintf("%d, %d", (val & 0xffff), + ((val & 0xffff0000) >> 16)); +} + +DEBUGSTRING(i830_debug_dspstride) +{ + return XNFprintf("%d bytes", val); +} + +DEBUGSTRING(i830_debug_dspcntr) +{ + char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled"; + char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A'; + return XNFprintf("%s, pipe %c", enabled, plane); +} + +DEBUGSTRING(i830_debug_pipeconf) +{ + char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled"; + char *wide = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide"; + return XNFprintf("%s, %s", enabled, wide); +} + +DEBUGSTRING(i830_debug_hvtotal) +{ + return XNFprintf("%d active, %d total", (val & 0xffff) + 1, + ((val & 0xffff0000) >> 16) + 1); +} + +DEBUGSTRING(i830_debug_hvsyncblank) +{ + return XNFprintf("%d start, %d end", (val & 0xffff) + 1, + ((val & 0xffff0000) >> 16) + 1); +} + +DEBUGSTRING(i830_debug_vgacntrl) +{ + return XNFprintf("%s", val & VGA_DISP_DISABLE ? "disabled" : "enabled"); +} + +DEBUGSTRING(i830_debug_fp) +{ + return XNFprintf("n = %d, m1 = %d, m2 = %d", + ((val & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT), + ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT), + ((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT)); +} + +DEBUGSTRING(i830_debug_pp_status) +{ + char *status = val & PP_ON ? "on" : "off"; + char *ready = val & PP_READY ? "ready" : "not ready"; + char *seq = "unknown"; + + switch (val & PP_SEQUENCE_MASK) { + case PP_SEQUENCE_NONE: + seq = "idle"; + break; + case PP_SEQUENCE_ON: + seq = "on"; + break; + case PP_SEQUENCE_OFF: + seq = "off"; + break; + } + + return XNFprintf("%s, %s, sequencing %s", status, ready, seq); +} + +DEBUGSTRING(i830_debug_pp_control) +{ + return XNFprintf("power target: %s", + val & POWER_TARGET_ON ? "on" : "off"); +} + +DEBUGSTRING(i830_debug_dpll) +{ + char *enabled = val & DPLL_VCO_ENABLE ? "enabled" : "disabled"; + char *dvomode = val & DPLL_DVO_HIGH_SPEED ? "dvo" : "non-dvo"; + char *vgamode = val & DPLL_VGA_MODE_DIS ? "" : ", VGA"; + char *mode = "unknown"; + char *clock = "unknown"; + char *fpextra = val & DISPLAY_RATE_SELECT_FPA1 ? ", using FPx1!" : ""; + char sdvoextra[3]; + int p1, p2 = 0; + + p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >> + DPLL_FPA01_P1_POST_DIV_SHIFT); + switch (val & DPLL_MODE_MASK) { + case DPLLB_MODE_DAC_SERIAL: + mode = "dac/serial"; + p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10; + break; + case DPLLB_MODE_LVDS: + mode = "LVDS"; + p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14; + break; + } + switch (val & PLL_REF_INPUT_MASK) { + case PLL_REF_INPUT_DREFCLK: + clock = "default"; + break; + case PLL_REF_INPUT_TVCLKINA: + clock = "TV A"; + break; + case PLL_REF_INPUT_TVCLKINBC: + clock = "TV B/C"; + break; + } + if (IS_I945G(pI830) || IS_I945GM(pI830)) { + sprintf(sdvoextra, "SDVO mult %d", + (int)(val & SDVO_MULTIPLIER_MASK) >> + SDVO_MULTIPLIER_SHIFT_HIRES); + } else { + sdvoextra[0] = '\0'; + } + + return XNFprintf("%s, %s%s, %s mode, %s clock, p1 = %d, " + "p2 = %d%s%s", + enabled, dvomode, vgamode, mode, clock, p1, p2, + fpextra, sdvoextra); +} + +DEBUGSTRING(i830_debug_lvds) +{ + char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A'; + char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled"; + + return XNFprintf("%s, pipe %c", enable, pipe); +} + #define DEFINEREG(reg) \ - { reg, #reg, 0 } + { reg, #reg, NULL, 0 } +#define DEFINEREG2(reg, func) \ + { reg, #reg, func, 0 } static struct i830SnapshotRec { int reg; char *name; - CARD32 regval; + char *(*debug_output)(I830Ptr pI830, int reg, CARD32 val); + CARD32 val; } i830_snapshot[] = { DEFINEREG(VCLK_DIVISOR_VGA0), DEFINEREG(VCLK_DIVISOR_VGA1), @@ -61,7 +205,7 @@ static struct i830SnapshotRec { DEFINEREG(DSPFW3), DEFINEREG(ADPA), - DEFINEREG(LVDS), + DEFINEREG2(LVDS, i830_debug_lvds), DEFINEREG(DVOA), DEFINEREG(DVOB), DEFINEREG(DVOC), @@ -69,63 +213,63 @@ static struct i830SnapshotRec { DEFINEREG(DVOB_SRCDIM), DEFINEREG(DVOC_SRCDIM), - DEFINEREG(PP_CONTROL), - DEFINEREG(PP_STATUS), + DEFINEREG2(PP_CONTROL, i830_debug_pp_control), + DEFINEREG2(PP_STATUS, i830_debug_pp_status), DEFINEREG(PFIT_CONTROL), DEFINEREG(PFIT_PGM_RATIOS), DEFINEREG(PORT_HOTPLUG_EN), DEFINEREG(PORT_HOTPLUG_STAT), - DEFINEREG(DSPACNTR), - DEFINEREG(DSPASTRIDE), - DEFINEREG(DSPAPOS), - DEFINEREG(DSPASIZE), + DEFINEREG2(DSPACNTR, i830_debug_dspcntr), + DEFINEREG2(DSPASTRIDE, i830_debug_dspstride), + DEFINEREG2(DSPAPOS, i830_debug_xy), + DEFINEREG2(DSPASIZE, i830_debug_xyminus1), DEFINEREG(DSPABASE), DEFINEREG(DSPASURF), DEFINEREG(DSPATILEOFF), - DEFINEREG(PIPEACONF), - DEFINEREG(PIPEASRC), + DEFINEREG2(PIPEACONF, i830_debug_pipeconf), + DEFINEREG2(PIPEASRC, i830_debug_xyminus1), - DEFINEREG(FPA0), - DEFINEREG(FPA1), - DEFINEREG(DPLL_A), + DEFINEREG2(FPA0, i830_debug_fp), + DEFINEREG2(FPA1, i830_debug_fp), + DEFINEREG2(DPLL_A, i830_debug_dpll), DEFINEREG(DPLL_A_MD), - DEFINEREG(HTOTAL_A), - DEFINEREG(HBLANK_A), - DEFINEREG(HSYNC_A), - DEFINEREG(VTOTAL_A), - DEFINEREG(VBLANK_A), - DEFINEREG(VSYNC_A), + DEFINEREG2(HTOTAL_A, i830_debug_hvtotal), + DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank), + DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank), + DEFINEREG2(VTOTAL_A, i830_debug_hvtotal), + DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank), + DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank), DEFINEREG(BCLRPAT_A), DEFINEREG(VSYNCSHIFT_A), - DEFINEREG(DSPBCNTR), - DEFINEREG(DSPBSTRIDE), - DEFINEREG(DSPBPOS), - DEFINEREG(DSPBSIZE), + DEFINEREG2(DSPBCNTR, i830_debug_dspcntr), + DEFINEREG2(DSPBSTRIDE, i830_debug_dspstride), + DEFINEREG2(DSPBPOS, i830_debug_xy), + DEFINEREG2(DSPBSIZE, i830_debug_xyminus1), DEFINEREG(DSPBBASE), DEFINEREG(DSPBSURF), DEFINEREG(DSPBTILEOFF), - DEFINEREG(PIPEBCONF), - DEFINEREG(PIPEBSRC), + DEFINEREG2(PIPEBCONF, i830_debug_pipeconf), + DEFINEREG2(PIPEBSRC, i830_debug_xyminus1), - DEFINEREG(FPB0), - DEFINEREG(FPB1), - DEFINEREG(DPLL_B), + DEFINEREG2(FPB0, i830_debug_fp), + DEFINEREG2(FPB1, i830_debug_fp), + DEFINEREG2(DPLL_B, i830_debug_dpll), DEFINEREG(DPLL_B_MD), - DEFINEREG(HTOTAL_B), - DEFINEREG(HBLANK_B), - DEFINEREG(HSYNC_B), - DEFINEREG(VTOTAL_B), - DEFINEREG(VBLANK_B), - DEFINEREG(VSYNC_B), + DEFINEREG2(HTOTAL_B, i830_debug_hvtotal), + DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank), + DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank), + DEFINEREG2(VTOTAL_B, i830_debug_hvtotal), + DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank), + DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank), DEFINEREG(BCLRPAT_B), DEFINEREG(VSYNCSHIFT_B), DEFINEREG(VCLK_DIVISOR_VGA0), DEFINEREG(VCLK_DIVISOR_VGA1), DEFINEREG(VCLK_POST_DIV), - DEFINEREG(VGACNTRL), + DEFINEREG2(VGACNTRL, i830_debug_vgacntrl), DEFINEREG(TV_CTL), DEFINEREG(TV_DAC), @@ -171,7 +315,7 @@ void i830TakeRegSnapshot(ScrnInfoPtr pScrn) int i; for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { - i830_snapshot[i].regval = INREG(i830_snapshot[i].reg); + i830_snapshot[i].val = INREG(i830_snapshot[i].reg); } } @@ -184,11 +328,28 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn) "Comparing regs before/after X's VT usage\n"); for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { CARD32 val = INREG(i830_snapshot[i].reg); - if (i830_snapshot[i].regval != val) { + if (i830_snapshot[i].val == val) + continue; + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n", + i830_snapshot[i].reg, i830_snapshot[i].name, + (int)i830_snapshot[i].val, (int)val); + + if (i830_snapshot[i].debug_output != NULL) { + char *before, *after; + + before = i830_snapshot[i].debug_output(pI830, + i830_snapshot[i].reg, + i830_snapshot[i].val); + after = i830_snapshot[i].debug_output(pI830, + i830_snapshot[i].reg, + val); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n", - i830_snapshot[i].reg, i830_snapshot[i].name, - (int)i830_snapshot[i].regval, (int)val); + "%s before: %s", i830_snapshot[i].name, before); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s after: %s", i830_snapshot[i].name, after); + } } } @@ -220,8 +381,19 @@ void i830DumpRegs (ScrnInfoPtr pScrn) xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n"); for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { - xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n", - i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg)); + CARD32 val = INREG(i830_snapshot[i].reg); + + if (i830_snapshot[i].debug_output != NULL) { + char *debug = i830_snapshot[i].debug_output(pI830, + i830_snapshot[i].reg, + val); + xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x (%s)\n", + i830_snapshot[i].name, (unsigned int)val, debug); + xfree(debug); + } else { + xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n", + i830_snapshot[i].name, (unsigned int)val); + } } i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7); msr = INREG8(0x3cc); From eee23fdd0dadd38a2b80525ec886120150f91077 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 5 Dec 2006 18:19:49 -0800 Subject: [PATCH 09/26] Fix copy'n'paste-o of the ordering of h/v fields in DSP[AB]SIZE. --- src/i830_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_display.c b/src/i830_display.c index 03a77650..d8220837 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -745,7 +745,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, /* pipesrc and dspsize control the size that is scaled from, which should * always be the user's requested size. */ - OUTREG(dspsize_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1)); + OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1)); OUTREG(dsppos_reg, 0); i830PipeSetBase(crtc, crtc->x, crtc->y); OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1)); From 1d94ec7de3387b70815679977cfc5d88200efa99 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 5 Dec 2006 18:22:59 -0800 Subject: [PATCH 10/26] Fix ordering of PIPE[AB]SRC debug output to be (x, y). --- src/i830_debug.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/i830_debug.c b/src/i830_debug.c index 97b09830..68c4b5d2 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -41,6 +41,12 @@ DEBUGSTRING(i830_debug_xyminus1) ((val & 0xffff0000) >> 16) + 1); } +DEBUGSTRING(i830_debug_yxminus1) +{ + return XNFprintf("%d, %d", ((val & 0xffff0000) >> 16) + 1, + (val & 0xffff) + 1); +} + DEBUGSTRING(i830_debug_xy) { return XNFprintf("%d, %d", (val & 0xffff), @@ -228,7 +234,7 @@ static struct i830SnapshotRec { DEFINEREG(DSPASURF), DEFINEREG(DSPATILEOFF), DEFINEREG2(PIPEACONF, i830_debug_pipeconf), - DEFINEREG2(PIPEASRC, i830_debug_xyminus1), + DEFINEREG2(PIPEASRC, i830_debug_yxminus1), DEFINEREG2(FPA0, i830_debug_fp), DEFINEREG2(FPA1, i830_debug_fp), @@ -251,7 +257,7 @@ static struct i830SnapshotRec { DEFINEREG(DSPBSURF), DEFINEREG(DSPBTILEOFF), DEFINEREG2(PIPEBCONF, i830_debug_pipeconf), - DEFINEREG2(PIPEBSRC, i830_debug_xyminus1), + DEFINEREG2(PIPEBSRC, i830_debug_yxminus1), DEFINEREG2(FPB0, i830_debug_fp), DEFINEREG2(FPB1, i830_debug_fp), From 62fba80d3ea9c185ec8ae1e06c099c02bf844d8b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Dec 2006 19:43:41 -0800 Subject: [PATCH 11/26] fix up misleading comment in i830_crt.c about border register --- src/i830_crt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/i830_crt.c b/src/i830_crt.c index 7a706d14..bf23f9eb 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -221,9 +221,7 @@ i830_crt_detect_load (xf86CrtcPtr crtc, adpa |= ADPA_VSYNC_CNTL_ENABLE | ADPA_HSYNC_CNTL_ENABLE; OUTREG(ADPA, adpa); - /* Set the border color to purple. Maybe we should save/restore this - * reg. - */ + /* Set the border color to purple. */ bclrpat = INREG(bclrpat_reg); OUTREG(bclrpat_reg, 0x00500050); From a73649611414cb92697575efa90addfc3cf91cf9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Dec 2006 19:47:04 -0800 Subject: [PATCH 12/26] Capture VGA registers sooner so checks are more informative --- src/i830_debug.c | 4 ++-- src/i830_debug.h | 2 +- src/i830_driver.c | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/i830_debug.c b/src/i830_debug.c index d74d0920..f7323891 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -175,13 +175,13 @@ void i830TakeRegSnapshot(ScrnInfoPtr pScrn) } } -void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn) +void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where) { I830Ptr pI830 = I830PTR(pScrn); int i; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Comparing regs before/after X's VT usage\n"); + "Comparing regs from server start up to %s\n", where); for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { CARD32 val = INREG(i830_snapshot[i].reg); if (i830_snapshot[i].regval != val) { diff --git a/src/i830_debug.h b/src/i830_debug.h index a8e38398..a365085c 100644 --- a/src/i830_debug.h +++ b/src/i830_debug.h @@ -26,5 +26,5 @@ */ void i830TakeRegSnapshot(ScrnInfoPtr pScrn); -void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn); +void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where); void i830DumpRegs (ScrnInfoPtr pScrn); diff --git a/src/i830_driver.c b/src/i830_driver.c index c85fe4e6..73af1471 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -325,6 +325,9 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool I830SaveScreen(ScreenPtr pScreen, int unblack); static Bool I830EnterVT(int scrnIndex, int flags); static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg); +static Bool SaveHWState(ScrnInfoPtr pScrn); +static Bool RestoreHWState(ScrnInfoPtr pScrn); + extern int I830EntityIndex; @@ -1146,6 +1149,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Some of the probing needs MMIO access, so map it here. */ I830MapMMIO(pScrn); + i830TakeRegSnapshot(pScrn); + #if 1 pI830->saveSWF0 = INREG(SWF0); pI830->saveSWF4 = INREG(SWF4); @@ -1360,18 +1365,22 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } +#if 0 + SaveHWState (pScrn); +#endif /* Perform the pipe assignment of outputs. This is a kludge until * we have better configuration support in the generic RandR code */ for (i = 0; i < pI830->xf86_config.num_output; i++) { xf86OutputPtr output = pI830->xf86_config.output[i]; - I830OutputPrivatePtr intel_output = output->driver_private; - xf86CrtcPtr crtc; - int p; output_status[i] = (*output->funcs->detect) (output); } +#if 0 + RestoreHWState (pScrn); +#endif + for (i = 0; i < pI830->xf86_config.num_output; i++) { @@ -1911,6 +1920,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86LoaderReqSymLists(I810ramdacSymbols, NULL); } + i830CompareRegsToSnapshot(pScrn, "After PreInit"); + I830UnmapMMIO(pScrn); /* We won't be using the VGA access after the probe. */ @@ -2187,8 +2198,6 @@ SaveHWState(ScrnInfoPtr pScrn) (unsigned long) temp); } - i830TakeRegSnapshot(pScrn); - /* Save video mode information for native mode-setting. */ pI830->saveDSPACNTR = INREG(DSPACNTR); pI830->savePIPEACONF = INREG(PIPEACONF); @@ -2380,7 +2389,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(SWF31, pI830->saveSWF[15]); OUTREG(SWF32, pI830->saveSWF[16]); - i830CompareRegsToSnapshot(pScrn); + i830CompareRegsToSnapshot(pScrn, "After RestoreHWState"); + i830DumpRegs (pScrn); return TRUE; } From ffd8aacbe7c72b696ff7257609e3c1d45c057609 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Dec 2006 19:48:39 -0800 Subject: [PATCH 13/26] new server APIs are not in server-1.2 (version 7.1.99.2) --- src/i830_display.h | 4 ++-- src/i830_edid_modes.c | 4 ++-- src/i830_xf86Modes.c | 4 ++-- src/i830_xf86Modes.h | 4 ++-- src/i830_xf86cvt.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/i830_display.h b/src/i830_display.h index c80c3f72..d140e093 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -44,11 +44,11 @@ Bool i830PipeInUse(xf86CrtcPtr crtc); /** @{ */ -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, Bool Interlaced); #define xf86DDCGetModes i830_xf86DDCGetModes #define xf86CVTMode i830_xf86CVTMode -#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2) */ +#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2) */ /** @} */ diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c index fcb71d23..3becbb50 100644 --- a/src/i830_edid_modes.c +++ b/src/i830_edid_modes.c @@ -38,7 +38,7 @@ #include "i830.h" #include "i830_display.h" -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) /* * TODO: @@ -208,4 +208,4 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) return Modes; } -#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) */ +#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */ diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index c091aef7..1afda951 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -45,7 +45,7 @@ * there but we still want to use. We need to come up with better API here. */ -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) /** * Calculates the horizontal sync rate of a mode. * @@ -321,7 +321,7 @@ xf86PrintModeline(int scrnIndex,DisplayModePtr mode) mode->VTotal, flags, xf86ModeHSync(mode)); xfree(flags); } -#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */ +#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */ /** * Marks as bad any modes with unsupported flags. diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 3bd8557d..98300039 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -29,7 +29,7 @@ #define _I830_XF86MODES_H_ #include "xorgVersion.h" -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) double i830_xf86ModeHSync(DisplayModePtr mode); double i830_xf86ModeVRefresh(DisplayModePtr mode); DisplayModePtr i830_xf86DuplicateMode(DisplayModePtr pMode); @@ -50,7 +50,7 @@ DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); #define xf86ModesEqual i830_xf86ModesEqual #define xf86PrintModeline i830_xf86PrintModeline #define xf86ModesAdd i830_xf86ModesAdd -#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */ +#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */ void i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c index 00140561..dba57c82 100644 --- a/src/i830_xf86cvt.c +++ b/src/i830_xf86cvt.c @@ -40,7 +40,7 @@ #include "i830.h" #include "i830_display.h" -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) /* * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh. * @@ -303,4 +303,4 @@ xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, return Mode; } -#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) */ +#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */ From 56f71194157ef929b62fe34a89c840bd59e56301 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Dec 2006 00:13:57 -0800 Subject: [PATCH 14/26] Use xf86 structures for default config instead of RandR. To avoid requiring RandR 1.2 in the X server, use the xf86 Crtc and Output structures as the basis for the default configuration computation (and, eventually, the config-file based configuration as well). --- src/i830.h | 13 +- src/i830_crt.c | 17 +- src/i830_display.c | 6 +- src/i830_driver.c | 145 ++++++------ src/i830_dvo.c | 5 +- src/i830_lvds.c | 5 +- src/i830_modes.c | 239 ------------------- src/i830_randr.c | 554 ++++++++------------------------------------ src/i830_sdvo.c | 14 +- src/i830_tv.c | 8 +- src/i830_xf86Crtc.c | 510 +++++++++++++++++++++++++++++++++++----- src/i830_xf86Crtc.h | 47 +++- 12 files changed, 708 insertions(+), 855 deletions(-) diff --git a/src/i830.h b/src/i830.h index 4cfed4b4..64d693af 100644 --- a/src/i830.h +++ b/src/i830.h @@ -192,12 +192,6 @@ struct _I830DVODriver { extern const char *i830_output_type_names[]; -enum detect_status { - OUTPUT_STATUS_CONNECTED, - OUTPUT_STATUS_DISCONNECTED, - OUTPUT_STATUS_UNKNOWN -}; - typedef struct _I830CrtcPrivateRec { int pipe; Bool gammaEnabled; @@ -606,6 +600,9 @@ extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +/* return a mask of output indices matching outputs against type_mask */ +int i830_output_clones (ScrnInfoPtr pScrn, int type_mask); + /* i830_display.c */ Bool i830PipeHasType (xf86CrtcPtr crtc, int type); @@ -627,10 +624,6 @@ Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); /* i830_modes.c */ -int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); -void i830_reprobe_output_modes(ScrnInfoPtr pScrn); -void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn); -void i830_set_default_screen_size(ScrnInfoPtr pScrn); DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output); /* i830_tv.c */ diff --git a/src/i830_crt.c b/src/i830_crt.c index bf23f9eb..1bb52d41 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -272,7 +272,7 @@ i830_crt_detect_ddc(xf86OutputPtr output) * @param allow_disturb enables detection methods that may cause flickering * on active displays. */ -static enum detect_status +static xf86OutputStatus i830_crt_detect(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; @@ -281,13 +281,13 @@ i830_crt_detect(xf86OutputPtr output) if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) { if (i830_crt_detect_hotplug(output)) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; else - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; } if (i830_crt_detect_ddc(output)) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; /* Use the load-detect method if we have no other way of telling. */ crtc = i830GetLoadDetectPipe (output); @@ -318,12 +318,12 @@ i830_crt_detect(xf86OutputPtr output) i830ReleaseLoadDetectPipe (output); if (connected) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; else - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; } - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; } static DisplayModePtr @@ -337,7 +337,7 @@ i830_crt_get_modes(xf86OutputPtr output) if (modes != NULL) return modes; - if ((*output->funcs->detect)(output) == OUTPUT_STATUS_DISCONNECTED) + if ((*output->funcs->detect)(output) == XF86OutputStatusDisconnected) return NULL; /* We've got a potentially-connected monitor that we can't DDC. Return a @@ -393,6 +393,7 @@ i830_crt_init(ScrnInfoPtr pScrn) return; } i830_output->type = I830_OUTPUT_ANALOG; + output->driver_private = i830_output; /* Set up the DDC bus. */ diff --git a/src/i830_display.c b/src/i830_display.c index ac56528a..1f41cc31 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -912,15 +912,15 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); Bool ok = TRUE; - int i; + xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; DPRINTF(PFX, "i830SetMode\n"); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + if (crtc && crtc->enabled) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; ok = i830PipeSetMode(crtc, i830PipeFindClosestMode(crtc, pMode), TRUE); diff --git a/src/i830_driver.c b/src/i830_driver.c index 73af1471..ad25a77e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -686,6 +686,23 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, pI830->CursorInfoRec->ShowCursor(pScrn); } +int +i830_output_clones (ScrnInfoPtr pScrn, int type_mask) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); + int o; + int index_mask = 0; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + I830OutputPrivatePtr intel_output = output->driver_private; + if (type_mask & (1 << intel_output->type)) + index_mask |= (1 << o); + } + return index_mask; +} + /** * Set up the outputs according to what type of chip we are. * @@ -695,7 +712,9 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, static void I830SetupOutputs(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); + I830Ptr pI830 = I830PTR(pScrn); + int o; /* everyone has at least a single analog output */ i830_crt_init(pScrn); @@ -712,6 +731,44 @@ I830SetupOutputs(ScrnInfoPtr pScrn) } if (IS_I915GM(pI830) || IS_I945GM(pI830)) i830_tv_init(pScrn); + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + I830OutputPrivatePtr intel_output = output->driver_private; + int crtc_mask = 0, clone_mask = 0; + + /* + * Valid crtcs + */ + switch (intel_output->type) { + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + break; + case I830_OUTPUT_ANALOG: + crtc_mask = ((1 << 0)); + clone_mask = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + break; + case I830_OUTPUT_LVDS: + crtc_mask = (1 << 1); + clone_mask = (1 << I830_OUTPUT_LVDS); + break; + case I830_OUTPUT_TVOUT: + crtc_mask = ((1 << 0) | + (1 << 1)); + clone_mask = (1 << I830_OUTPUT_TVOUT); + break; + } + output->possible_crtcs = crtc_mask; + output->possible_clones = i830_output_clones (pScrn, clone_mask); + } } /** @@ -883,7 +940,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) #ifdef XF86DRI unsigned long savedMMSize; #endif - enum detect_status output_status[MAX_OUTPUTS]; if (pScrn->numEntities != 1) return FALSE; @@ -1375,64 +1431,20 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) { xf86OutputPtr output = pI830->xf86_config.output[i]; - output_status[i] = (*output->funcs->detect) (output); + output->status = (*output->funcs->detect) (output); } #if 0 RestoreHWState (pScrn); #endif - - for (i = 0; i < pI830->xf86_config.num_output; i++) + if (!xf86InitialConfiguration (pScrn)) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - I830OutputPrivatePtr intel_output = output->driver_private; - xf86CrtcPtr crtc; - int p; - - output->crtc = NULL; - - if (output_status[i] == OUTPUT_STATUS_DISCONNECTED) - continue; - - switch (intel_output->type) { - case I830_OUTPUT_LVDS: - /* LVDS must live on pipe B for two-pipe devices */ - crtc = pI830->xf86_config.crtc[pI830->xf86_config.num_crtc - 1]; - if (!i830PipeInUse (crtc)) - output->crtc = crtc; - break; - case I830_OUTPUT_ANALOG: - case I830_OUTPUT_DVO: - case I830_OUTPUT_SDVO: - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - { - crtc = pI830->xf86_config.crtc[p]; - if (!i830PipeInUse(crtc)) - { - output->crtc = crtc; - break; - } - } - break; - case I830_OUTPUT_TVOUT: - crtc = pI830->xf86_config.crtc[0]; - if (!i830PipeInUse(crtc)) - { - output->crtc = crtc; - } - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); - break; - } + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + PreInitCleanup(pScrn); + return FALSE; } - - for (i = 0; i < pI830->xf86_config.num_crtc; i++) - { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; - crtc->enabled = i830PipeInUse(crtc); - } - + pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; + pI830->rotation = RR_Rotate_0; if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) { pI830->InitialRotation = 0; @@ -1677,7 +1689,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (!xf86RandR12PreInit (pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); PreInitCleanup(pScrn); return FALSE; } @@ -3398,23 +3410,21 @@ static void i830AdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); - int i; + xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); - /* Sync the engine before adjust frame */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } - - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + if (crtc && crtc->enabled) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; - if (crtc->enabled) - i830PipeSetBase(crtc, x, y); + /* Sync the engine before adjust frame */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + i830PipeSetBase(crtc, x, y); } } @@ -3815,7 +3825,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) DPRINTF(PFX, "\nUnmapping memory\n"); I830UnmapMem(pScrn); vgaHWUnmapMem(pScrn); - xf86CrtcCloseScreen (pScreen); if (pI830->ScanlineColorExpandBuffers) { xfree(pI830->ScanlineColorExpandBuffers); @@ -4017,7 +4026,9 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) * implements a sensible policy using RandR-1.2. For now, all we get * is this. */ - I830ValidateXF86ModeList(pScrn, FALSE); + + xf86ProbeOutputModes (pScrn); + xf86SetScrnInfoModes (pScrn); xf86SwitchMode(pScrn->pScreen, pScrn->currentMode); /* Clear the BIOS's hotkey press flags */ diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 6fe31575..ccd08468 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -164,10 +164,10 @@ i830_dvo_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) * * Unimplemented. */ -static enum detect_status +static xf86OutputStatus i830_dvo_detect(xf86OutputPtr output) { - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; } static Bool @@ -248,6 +248,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) } intel_output->type = I830_OUTPUT_DVO; output->driver_private = intel_output; + output->subpixel_order = SubPixelHorizontalRGB; /* Set up the I2C and DDC buses */ ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E"); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index cf709569..5f0c01bb 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -180,10 +180,10 @@ i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) * This always returns OUTPUT_STATUS_CONNECTED. This output should only have * been set up if the LVDS was actually connected anyway. */ -static enum detect_status +static xf86OutputStatus i830_lvds_detect(xf86OutputPtr output) { - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; } /** @@ -293,6 +293,7 @@ i830_lvds_init(ScrnInfoPtr pScrn) } intel_output->type = I830_OUTPUT_LVDS; output->driver_private = intel_output; + output->subpixel_order = SubPixelHorizontalRGB; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_modes.c b/src/i830_modes.c index a0d79db9..34f6cd52 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -57,245 +57,6 @@ #define DEBUG_REPROBE 1 -static DisplayModePtr -i830GetModeListTail(DisplayModePtr pModeList) -{ - DisplayModePtr last; - - if (pModeList == NULL) - return NULL; - - for (last = pModeList; last->next != NULL; last = last->next) - ; - - return last; -} - -/** - * This function removes a mode from a list of modes. It should probably be - * moved to xf86Mode.c. - * - * There are different types of mode lists: - * - * - singly linked linear lists, ending in NULL - * - doubly linked linear lists, starting and ending in NULL - * - doubly linked circular lists - * - */ - -static void -I830xf86DeleteModeFromList(DisplayModePtr *modeList, DisplayModePtr mode) -{ - /* Catch the easy/insane cases */ - if (modeList == NULL || *modeList == NULL || mode == NULL) - return; - - /* If the mode is at the start of the list, move the start of the list */ - if (*modeList == mode) - *modeList = mode->next; - - /* If mode is the only one on the list, set the list to NULL */ - if ((mode == mode->prev) && (mode == mode->next)) { - *modeList = NULL; - } else { - if ((mode->prev != NULL) && (mode->prev->next == mode)) - mode->prev->next = mode->next; - if ((mode->next != NULL) && (mode->next->prev == mode)) - mode->next->prev = mode->prev; - } -} - -void -i830_reprobe_output_modes(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - Bool properties_set = FALSE; - int i; - - /* Re-probe the list of modes for each output. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) - { - xf86OutputPtr output = pI830->xf86_config.output[i]; - DisplayModePtr mode; - - while (output->probed_modes != NULL) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - output->probed_modes = (*output->funcs->get_modes) (output); - - /* Set the DDC properties to whatever first output has DDC information. - */ - if (output->MonInfo != NULL && !properties_set) { - xf86SetDDCproperties(pScrn, output->MonInfo); - properties_set = TRUE; - } - - if (output->probed_modes != NULL) - { - /* silently prune modes down to ones matching the user's - * configuration. - */ - i830xf86ValidateModesUserConfig(pScrn, output->probed_modes); - i830xf86PruneInvalidModes(pScrn, &output->probed_modes, FALSE); - } - -#ifdef DEBUG_REPROBE - if (output->probed_modes != NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Printing probed modes for output %s\n", - output->name); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No remaining probed modes for output %s\n", - output->name); - } -#endif - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - /* The code to choose the best mode per pipe later on will require - * VRefresh to be set. - */ - mode->VRefresh = xf86ModeVRefresh(mode); - xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - -#ifdef DEBUG_REPROBE - xf86PrintModeline(pScrn->scrnIndex, mode); -#endif - } - } -} - -/** - * Constructs pScrn->modes from the output mode lists. - * - * Currently it only takes one output's mode list and stuffs it into the - * XFree86 DDX mode list while trimming it for root window size. - * - * This should be obsoleted by RandR 1.2 hopefully. - */ -void -i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr saved_mode, last; - int originalVirtualX, originalVirtualY; - int i; - - /* Remove the current mode from the modelist if we're re-validating, so we - * can find a new mode to map ourselves to afterwards. - */ - saved_mode = pI830->currentMode; - if (saved_mode != NULL) { - I830xf86DeleteModeFromList(&pScrn->modes, saved_mode); - } - - /* Clear any existing modes from pScrn->modes */ - while (pScrn->modes != NULL) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - - /* Set pScrn->modes to the mode list for an arbitrary output. - * pScrn->modes should only be used for XF86VidMode now, which we don't - * care about enough to make some sort of unioned list. - */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - if (output->probed_modes != NULL) { - pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes); - break; - } - } - - 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); - - if (pScrn->modes == NULL) { - FatalError("No modes left for XFree86 DDX\n"); - } - - /* For some reason, pScrn->modes is circular, unlike the other mode lists. - * How great is that? - */ - last = i830GetModeListTail(pScrn->modes); - last->next = pScrn->modes; - pScrn->modes->prev = last; - - /* Save a pointer to the previous current mode. We can't reset - * pScrn->currentmode, because we rely on xf86SwitchMode's shortcut not - * happening so we can hot-enable devices at SwitchMode. We'll notice this - * case at SwitchMode and free the saved mode. - */ - pI830->savedCurrentMode = saved_mode; -} - -/** - * Takes the output mode lists and decides the default root window size - * and framebuffer pitch. - */ -void -i830_set_default_screen_size(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int maxX = -1, maxY = -1; - int i; - - /* Set up a virtual size that will cover any clone mode we'd want to - * set for the currently-connected outputs. - */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - DisplayModePtr mode; - - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - if (mode->HDisplay > maxX) - maxX = mode->HDisplay; - if (mode->VDisplay > maxY) - maxY = mode->VDisplay; - } - } - /* let the user specify a bigger virtual size if they like */ - if (pScrn->display->virtualX > maxX) - maxX = pScrn->display->virtualX; - if (pScrn->display->virtualY > maxY) - maxY = pScrn->display->virtualY; - pScrn->virtualX = maxX; - pScrn->virtualY = maxY; - pScrn->displayWidth = (maxX + 63) & ~63; -} - -/** - * Probes for video modes on attached otuputs, and assembles a list to insert - * into pScrn. - * - * \param first_time indicates that the memory layout has already been set up, - * so displayWidth, virtualX, and virtualY shouldn't be touched. - * - * A SetMode must follow this call in order for operatingDevices to match the - * hardware's state, in case we detect a new output device. - */ -int -I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) -{ - i830_reprobe_output_modes(pScrn); - - if (first_time) { - i830_set_default_screen_size(pScrn); - } - - i830_set_xf86_modes_from_outputs(pScrn); - - return 1; /* XXX */ -} - #ifdef RANDR_12_INTERFACE #define EDID_ATOM_NAME "EDID_DATA" diff --git a/src/i830_randr.c b/src/i830_randr.c index 00770201..94d2221b 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -94,7 +94,8 @@ xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) } /* Re-probe the outputs for new monitors or modes */ - I830ValidateXF86ModeList(scrp, FALSE); + xf86ProbeOutputModes (scrp); + xf86SetScrnInfoModes (scrp); for (mode = scrp->modes; ; mode = mode->next) { @@ -246,13 +247,13 @@ xf86RandR12SetConfig (ScreenPtr pScreen, int rate, RRScreenSizePtr pSize) { - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int px, py; - Bool useVirtual = FALSE; - int maxX = 0, maxY = 0; - Rotation oldRotation = randrp->rotation; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int px, py; + Bool useVirtual = FALSE; + int maxX = 0, maxY = 0; + Rotation oldRotation = randrp->rotation; randrp->rotation = rotation; @@ -487,15 +488,15 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) { ScreenPtr pScreen = randr_crtc->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); RRModePtr randr_mode = NULL; int x; int y; Rotation rotation; int numOutputs; - RROutputPtr randr_outputs[MAX_OUTPUTS]; + RROutputPtr randr_outputs[XF86_MAX_OUTPUT]; RROutputPtr randr_output; - xf86CrtcPtr crtc = randr_crtc->devPrivate; + xf86CrtcPtr crtc = randr_crtc->devPrivate; xf86OutputPtr output; int i, j; DisplayModePtr curMode = &crtc->curMode; @@ -505,9 +506,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) rotation = RR_Rotate_0; numOutputs = 0; randr_mode = NULL; - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < config->num_output; i++) { - output = pI830->xf86_config.output[i]; + output = config->output[i]; if (output->crtc == crtc) { randr_output = output->randr_output; @@ -542,12 +543,13 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, RROutputPtr *randr_outputs) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - xf86CrtcPtr crtc = randr_crtc->devPrivate; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc = randr_crtc->devPrivate; DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL; Bool changed = FALSE; + Bool pos_changed; int o, ro; - xf86CrtcPtr save_crtcs[MAX_OUTPUTS]; + xf86CrtcPtr save_crtcs[XF86_MAX_OUTPUT]; Bool save_enabled = crtc->enabled; if ((mode != NULL) != crtc->enabled) @@ -555,9 +557,12 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, else if (mode && !xf86ModesEqual (&crtc->curMode, mode)) changed = TRUE; - for (o = 0; o < pI830->xf86_config.num_output; o++) + pos_changed = changed; + if (x != crtc->x || y != crtc->y) + pos_changed = TRUE; + for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; + xf86OutputPtr output = config->output[o]; xf86CrtcPtr new_crtc; save_crtcs[o] = output->crtc; @@ -578,10 +583,12 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, output->crtc = new_crtc; } } + /* XXX need device-independent mode setting code through an API */ if (changed) { + I830Ptr pI830 = I830PTR(pScrn); crtc->enabled = mode != NULL; - + /* Sync the engine before adjust mode */ if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { (*pI830->AccelInfoRec->Sync)(pScrn); @@ -593,18 +600,19 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, if (!i830PipeSetMode (crtc, mode, TRUE)) { crtc->enabled = save_enabled; - for (o = 0; o < pI830->xf86_config.num_output; o++) + for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; + xf86OutputPtr output = config->output[o]; output->crtc = save_crtcs[o]; } return FALSE; } crtc->desiredMode = *mode; - i830PipeSetBase(crtc, x, y); } i830DisableUnusedFunctions (pScrn); } + if (pos_changed && mode) + i830PipeSetBase(crtc, x, y); return xf86RandR12CrtcNotify (randr_crtc); } @@ -620,7 +628,7 @@ xf86RandR12CrtcSetGamma (ScreenPtr pScreen, * RandR modes and assign them to the output */ static Bool -I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) +xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) { DisplayModePtr mode; RRModePtr *rrmodes = NULL; @@ -660,8 +668,8 @@ I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) modeInfo.modeFlags = mode->Flags; rrmode = RRModeGet (&modeInfo, mode->name); - rrmode->devPrivate = mode; if (rrmode) { + rrmode->devPrivate = mode; rrmodes[nmode++] = rrmode; npreferred += pref; } @@ -679,64 +687,25 @@ I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) * Mirror the current mode configuration to RandR */ static Bool -xf86RandR12SetInfo12 (ScrnInfoPtr pScrn) +xf86RandR12SetInfo12 (ScreenPtr pScreen) { - I830Ptr pI830 = I830PTR(pScrn); - RROutputPtr clones[MAX_OUTPUTS]; - RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; - int ncrtc; - int o, c, p; - int clone_types; - int crtc_types; - int subpixel; - RRCrtcPtr randr_crtc; - int nclone; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RROutputPtr clones[XF86_MAX_OUTPUT]; + RRCrtcPtr crtcs[XF86_MAX_CRTC]; + int ncrtc; + int o, c, l; + RRCrtcPtr randr_crtc; + int nclone; - for (o = 0; o < pI830->xf86_config.num_output; o++) + for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; - I830OutputPrivatePtr intel_output = output->driver_private; - /* - * Valid crtcs - */ - switch (intel_output->type) { - case I830_OUTPUT_DVO: - case I830_OUTPUT_SDVO: - crtc_types = ((1 << 0)| - (1 << 1)); - clone_types = ((1 << I830_OUTPUT_ANALOG) | - (1 << I830_OUTPUT_DVO) | - (1 << I830_OUTPUT_SDVO)); - subpixel = SubPixelHorizontalRGB; - break; - case I830_OUTPUT_ANALOG: - crtc_types = ((1 << 0)); - clone_types = ((1 << I830_OUTPUT_ANALOG) | - (1 << I830_OUTPUT_DVO) | - (1 << I830_OUTPUT_SDVO)); - subpixel = SubPixelNone; - break; - case I830_OUTPUT_LVDS: - crtc_types = (1 << 1); - clone_types = (1 << I830_OUTPUT_LVDS); - subpixel = SubPixelHorizontalRGB; - break; - case I830_OUTPUT_TVOUT: - crtc_types = ((1 << 0) | - (1 << 1)); - clone_types = (1 << I830_OUTPUT_TVOUT); - subpixel = SubPixelNone; - break; - default: - crtc_types = 0; - clone_types = 0; - subpixel = SubPixelUnknown; - break; - } + xf86OutputPtr output = config->output[o]; + ncrtc = 0; - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - if (crtc_types & (1 << p)) - crtcs[ncrtc++] = pI830->xf86_config.crtc[p]->randr_crtc; + for (c = 0; c < config->num_crtc; c++) + if (output->possible_crtcs & (1 << c)) + crtcs[ncrtc++] = config->crtc[c]->randr_crtc; if (output->crtc) randr_crtc = output->crtc->randr_crtc; @@ -750,32 +719,31 @@ xf86RandR12SetInfo12 (ScrnInfoPtr pScrn) RROutputSetPhysicalSize(output->randr_output, output->mm_width, output->mm_height); - I830xf86RROutputSetModes (output->randr_output, output->probed_modes); + xf86RROutputSetModes (output->randr_output, output->probed_modes); - switch ((*output->funcs->detect)(output)) { - case OUTPUT_STATUS_CONNECTED: + switch (output->status = (*output->funcs->detect)(output)) { + case XF86OutputStatusConnected: RROutputSetConnection (output->randr_output, RR_Connected); break; - case OUTPUT_STATUS_DISCONNECTED: + case XF86OutputStatusDisconnected: RROutputSetConnection (output->randr_output, RR_Disconnected); break; - case OUTPUT_STATUS_UNKNOWN: + case XF86OutputStatusUnknown: RROutputSetConnection (output->randr_output, RR_UnknownConnection); break; } - RROutputSetSubpixelOrder (output->randr_output, subpixel); + RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order); /* * Valid clones */ nclone = 0; - for (c = 0; c < pI830->xf86_config.num_output; c++) + for (l = 0; l < config->num_output; l++) { - xf86OutputPtr clone = pI830->xf86_config.output[c]; - I830OutputPrivatePtr intel_clone = clone->driver_private; + xf86OutputPtr clone = config->output[l]; - if (o != c && ((1 << intel_clone->type) & clone_types)) + if (l != o && (output->possible_clones & (1 << l))) clones[nclone++] = clone->randr_output; } if (!RROutputSetClones (output->randr_output, clones, nclone)) @@ -793,15 +761,18 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - i830_reprobe_output_modes(pScrn); - return xf86RandR12SetInfo12 (pScrn); + xf86ProbeOutputModes (pScrn); + xf86SetScrnInfoModes (pScrn); + return xf86RandR12SetInfo12 (pScreen); } static Bool -xf86RandR12CreateObjects12 (ScrnInfoPtr pScrn) +xf86RandR12CreateObjects12 (ScreenPtr pScreen) { - I830Ptr pI830 = I830PTR(pScrn); - int p; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + int o; if (!RRInit ()) return FALSE; @@ -809,45 +780,47 @@ xf86RandR12CreateObjects12 (ScrnInfoPtr pScrn) /* * Configure crtcs */ - for (p = 0; p < pI830->xf86_config.num_crtc; p++) + for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[p]; + xf86CrtcPtr crtc = config->crtc[c]; + crtc->randr_crtc = RRCrtcCreate (crtc); + RRCrtcAttachScreen (crtc->randr_crtc, pScreen); RRCrtcGammaSetSize (crtc->randr_crtc, 256); } + /* + * Configure outputs + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + output->randr_output = RROutputCreate (output->name, + strlen (output->name), + output); + RROutputAttachScreen (output->randr_output, pScreen); + } return TRUE; } static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) { - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - int p, o; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int c; int width, height; - /* - * Attach RandR objects to screen - */ - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - if (!RRCrtcAttachScreen (pI830->xf86_config.crtc[p]->randr_crtc, pScreen)) - return FALSE; - - for (o = 0; o < pI830->xf86_config.num_output; o++) - if (!RROutputAttachScreen (pI830->xf86_config.output[o]->randr_output, pScreen)) - return FALSE; - /* * Compute width of screen */ width = 0; height = 0; - for (p = 0; p < pI830->xf86_config.num_crtc; p++) + for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[p]; - int crtc_width = crtc->x + crtc->curMode.HDisplay; - int crtc_height = crtc->y + crtc->curMode.VDisplay; + xf86CrtcPtr crtc = config->crtc[c]; + int crtc_width = crtc->x + crtc->curMode.HDisplay; + int crtc_height = crtc->y + crtc->curMode.VDisplay; if (crtc->enabled && crtc_width > width) width = crtc_width; @@ -869,14 +842,14 @@ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) "Setting screen physical size to %d x %d\n", mmWidth, mmHeight); xf86RandR12ScreenSetSize (pScreen, - width, - height, - mmWidth, - mmHeight); + width, + height, + mmWidth, + mmHeight); } - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - xf86RandR12CrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc); + for (c = 0; c < config->num_crtc; c++) + xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); if (randrp->virtualX == -1 || randrp->virtualY == -1) { @@ -900,356 +873,27 @@ xf86RandR12Init12 (ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; rrScrPrivPtr rp = rrGetScrPriv(pScreen); - if (xf86CrtcScreenInit (pScreen)) - return FALSE; - rp->rrGetInfo = xf86RandR12GetInfo12; rp->rrScreenSetSize = xf86RandR12ScreenSetSize; rp->rrCrtcSet = xf86RandR12CrtcSet; rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; rp->rrSetConfig = NULL; pScrn->PointerMoved = xf86RandR12PointerMoved; - return TRUE; -} - -static RRModePtr -I830RRDefaultMode (RROutputPtr output) -{ - RRModePtr target_mode = NULL; - int target_diff = 0; - int mmHeight; - int num_modes; - int m; - - num_modes = output->numPreferred ? output->numPreferred : output->numModes; - mmHeight = output->mmHeight; - if (!mmHeight) - mmHeight = 203; /* 768 pixels at 96dpi */ - /* - * Pick a mode closest to 96dpi - */ - for (m = 0; m < num_modes; m++) - { - RRModePtr mode = output->modes[m]; - int dpi; - int diff; - - dpi = (mode->mode.height * 254) / (mmHeight * 10); - diff = dpi - 96; - diff = diff < 0 ? -diff : diff; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static RRModePtr -I830ClosestMode (RROutputPtr output, RRModePtr match) -{ - RRModePtr target_mode = NULL; - int target_diff = 0; - int m; - - /* - * Pick a mode closest to the specified mode - */ - for (m = 0; m < output->numModes; m++) - { - RRModePtr mode = output->modes[m]; - int dx, dy; - int diff; - - /* exact matches are preferred */ - if (mode == match) - return mode; - - dx = match->mode.width - mode->mode.width; - dy = match->mode.height - mode->mode.height; - diff = dx * dx + dy * dy; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static int -I830RRPickCrtcs (RROutputPtr *outputs, - RRCrtcPtr *best_crtcs, - RRModePtr *modes, - int num_output, - int n) -{ - int c, o, l; - RROutputPtr output; - RRCrtcPtr crtc; - RRCrtcPtr *crtcs; - RRCrtcPtr best_crtc; - int best_score; - int score; - int my_score; - - if (n == num_output) - return 0; - output = outputs[n]; - - /* - * Compute score with this output disabled - */ - best_crtcs[n] = NULL; - best_crtc = NULL; - best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_output, n+1); - if (modes[n] == NULL) - return best_score; - - crtcs = xalloc (num_output * sizeof (RRCrtcPtr)); - if (!crtcs) - return best_score; - - my_score = 1; - /* Score outputs that are known to be connected higher */ - if (output->connection == RR_Connected) - my_score++; - /* Score outputs with preferred modes higher */ - if (output->numPreferred) - my_score++; - /* - * Select a crtc for this output and - * then attempt to configure the remaining - * outputs - */ - for (c = 0; c < output->numCrtcs; c++) - { - crtc = output->crtcs[c]; - /* - * Check to see if some other output is - * using this crtc - */ - for (o = 0; o < n; o++) - if (best_crtcs[o] == crtc) - break; - if (o < n) - { - /* - * If the two outputs desire the same mode, - * see if they can be cloned - */ - if (modes[o] == modes[n]) - { - for (l = 0; l < output->numClones; l++) - if (output->clones[l] == outputs[o]) - break; - if (l == output->numClones) - continue; /* nope, try next CRTC */ - } - else - continue; /* different modes, can't clone */ - } - crtcs[n] = crtc; - memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr)); - score = my_score + I830RRPickCrtcs (outputs, crtcs, modes, - num_output, n+1); - if (score >= best_score) - { - best_crtc = crtc; - best_score = score; - memcpy (best_crtcs, crtcs, num_output * sizeof (RRCrtcPtr)); - } - } - xfree (crtcs); - return best_score; -} - -static Bool -I830RRInitialConfiguration (RROutputPtr *outputs, - RRCrtcPtr *crtcs, - RRModePtr *modes, - int num_output) -{ - int o; - RRModePtr target_mode = NULL; - - for (o = 0; o < num_output; o++) - modes[o] = NULL; - - /* - * Let outputs with preferred modes drive screen size - */ - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - - if (output->connection != RR_Disconnected && output->numPreferred) - { - target_mode = I830RRDefaultMode (output); - if (target_mode) - { - modes[o] = target_mode; - break; - } - } - } - if (!target_mode) - { - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - if (output->connection != RR_Disconnected) - { - target_mode = I830RRDefaultMode (output); - if (target_mode) - { - modes[o] = target_mode; - break; - } - } - } - } - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - - if (output->connection != RR_Disconnected && !modes[o]) - modes[o] = I830ClosestMode (output, target_mode); - } - - if (!I830RRPickCrtcs (outputs, crtcs, modes, num_output, 0)) + if (!xf86RandR12CreateObjects12 (pScreen)) + return FALSE; + + /* + * Configure output modes + */ + if (!xf86RandR12SetInfo12 (pScreen)) return FALSE; - return TRUE; } -/* - * Compute the virtual size necessary to place all of the available - * crtcs in a panorama configuration - */ - -static void -I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_output, - RRCrtcPtr *crtcs, int num_crtc, - int *widthp, int *heightp) -{ - int width = 0, height = 0; - int o; - int c; - int m; - int s; - - for (c = 0; c < num_crtc; c++) - { - RRCrtcPtr crtc = crtcs[c]; - int crtc_width = 1600, crtc_height = 1200; - - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - - for (s = 0; s < output->numCrtcs; s++) - if (output->crtcs[s] == crtc) - { - for (m = 0; m < output->numModes; m++) - { - RRModePtr mode = output->modes[m]; - if (mode->mode.width > crtc_width) - crtc_width = mode->mode.width; - if (mode->mode.height > crtc_width) - crtc_height = mode->mode.height; - } - } - } - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - } - *widthp = width; - *heightp = height; -} - #endif Bool xf86RandR12PreInit (ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); -#if RANDR_12_INTERFACE - RROutputPtr outputs[MAX_OUTPUTS]; - RRCrtcPtr output_crtcs[MAX_OUTPUTS]; - RRModePtr output_modes[MAX_OUTPUTS]; - RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; - int width, height; - int o; - int c; -#endif - - if (pI830->xf86_config.num_output <= 0) - return FALSE; - - i830_reprobe_output_modes(pScrn); - -#if RANDR_12_INTERFACE - if (!xf86RandR12CreateObjects12 (pScrn)) - return FALSE; - - /* - * Configure output modes - */ - if (!xf86RandR12SetInfo12 (pScrn)) - return FALSE; - /* - * With RandR info set up, let RandR choose - * the initial configuration - */ - for (o = 0; o < pI830->xf86_config.num_output; o++) - outputs[o] = pI830->xf86_config.output[o]->randr_output; - for (c = 0; c < pI830->xf86_config.num_crtc; c++) - crtcs[c] = pI830->xf86_config.crtc[c]->randr_crtc; - - if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes, - pI830->xf86_config.num_output)) - return FALSE; - - I830RRDefaultScreenLimits (outputs, pI830->xf86_config.num_output, - crtcs, pI830->xf86_config.num_crtc, - &width, &height); - - if (width > pScrn->virtualX) - pScrn->virtualX = width; - if (width > pScrn->display->virtualX) - pScrn->display->virtualX = width; - if (height > pScrn->virtualY) - pScrn->virtualY = height; - if (height > pScrn->display->virtualY) - pScrn->display->virtualY = height; - - /* XXX override xf86 common frame computation code */ - pScrn->display->frameX0 = 0; - pScrn->display->frameY0 = 0; - for (o = 0; o < pI830->xf86_config.num_output; o++) - { - xf86OutputPtr output = pI830->xf86_config.output[o]; - RRModePtr randr_mode = output_modes[o]; - RRCrtcPtr randr_crtc = output_crtcs[o]; - DisplayModePtr mode; - - if (randr_mode && randr_crtc) - { - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - mode = (DisplayModePtr) randr_mode->devPrivate; - crtc->desiredMode = *mode; - output->crtc = crtc; - } - } -#endif - i830_set_xf86_modes_from_outputs (pScrn); - - i830_set_default_screen_size(pScrn); - return TRUE; } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index c75800d4..a2030b72 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -975,7 +975,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn) * * Takes 14ms on average on my i945G. */ -static enum detect_status +static xf86OutputStatus i830_sdvo_detect(xf86OutputPtr output) { CARD8 response[2]; @@ -985,12 +985,12 @@ i830_sdvo_detect(xf86OutputPtr output) status = i830_sdvo_read_response(output, &response, 2); if (status != SDVO_CMD_STATUS_SUCCESS) - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; if (response[0] != 0 || response[1] != 0) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; else - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; } static void @@ -1132,9 +1132,15 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs)); if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) + { dev_priv->active_outputs = SDVO_OUTPUT_TMDS0; + output->subpixel_order = SubPixelHorizontalRGB; + } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) + { dev_priv->active_outputs = SDVO_OUTPUT_TMDS1; + output->subpixel_order = SubPixelHorizontalRGB; + } else { unsigned char bytes[2]; diff --git a/src/i830_tv.c b/src/i830_tv.c index f5716f8b..e05bc4cb 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -544,7 +544,7 @@ i830_tv_detect_type (xf86CrtcPtr crtc, * Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure * we have a pipe programmed in order to probe the TV. */ -static enum detect_status +static xf86OutputStatus i830_tv_detect(xf86OutputPtr output) { xf86CrtcPtr crtc; @@ -567,11 +567,11 @@ i830_tv_detect(xf86OutputPtr output) switch (dev_priv->type) { case TV_TYPE_NONE: - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; case TV_TYPE_UNKNOWN: - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; default: - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; } } diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 7eb581c9..5378b34f 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -31,6 +31,7 @@ #include #include "xf86.h" +#include "xf86DDC.h" #include "i830_xf86Crtc.h" /* @@ -49,12 +50,7 @@ xf86CrtcCreate (ScrnInfoPtr scrn, crtc->scrn = scrn; crtc->funcs = funcs; #ifdef RANDR_12_INTERFACE - crtc->randr_crtc = RRCrtcCreate (crtc); - if (!crtc->randr_crtc) - { - xfree (crtc); - return NULL; - } + crtc->randr_crtc = NULL; #endif xf86_config->crtc[xf86_config->num_crtc++] = crtc; return crtc; @@ -67,10 +63,6 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) int c; (*crtc->funcs->destroy) (crtc); -#ifdef RANDR_12_INTERFACE - if (crtc->randr_crtc) - RRCrtcDestroy (crtc->randr_crtc); -#endif for (c = 0; c < xf86_config->num_crtc; c++) if (xf86_config->crtc[c] == crtc) { @@ -101,14 +93,10 @@ xf86OutputCreate (ScrnInfoPtr scrn, output->scrn = scrn; output->funcs = funcs; output->name = (char *) (output + 1); + output->subpixel_order = SubPixelUnknown; strcpy (output->name, name); #ifdef RANDR_12_INTERFACE - output->randr_output = RROutputCreate (name, strlen (name), output); - if (!output->randr_output) - { - xfree (output); - return NULL; - } + output->randr_output = NULL; #endif xf86_config->output[xf86_config->num_output++] = output; return output; @@ -122,10 +110,6 @@ xf86OutputDestroy (xf86OutputPtr output) int o; (*output->funcs->destroy) (output); -#ifdef RANDR_12_INTERFACE - if (output->randr_output) - RROutputDestroy (output->randr_output); -#endif while (output->probed_modes) xf86DeleteMode (&output->probed_modes, output->probed_modes); for (o = 0; o < xf86_config->num_output; o++) @@ -140,55 +124,467 @@ xf86OutputDestroy (xf86OutputPtr output) xfree (output); } -Bool -xf86CrtcScreenInit (ScreenPtr pScreen) +static DisplayModePtr +xf86DefaultMode (xf86OutputPtr output) { -#ifdef RANDR_12_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; - - for (i = 0; i < xf86_config->num_crtc; i++) + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + int target_preferred = 0; + int mm_height; + + mm_height = output->mm_height; + if (!mm_height) + mm_height = 203; /* 768 pixels at 96dpi */ + /* + * Pick a mode closest to 96dpi + */ + for (mode = output->probed_modes; mode; mode = mode->next) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; + int dpi; + int preferred = (mode->type & M_T_PREFERRED) != 0; + int diff; - if (!crtc->randr_crtc) - crtc->randr_crtc = RRCrtcCreate (crtc); - if (!crtc->randr_crtc) - return FALSE; + dpi = (mode->HDisplay * 254) / (mm_height * 10); + diff = dpi - 96; + diff = diff < 0 ? -diff : diff; + if (target_mode == NULL || (preferred > target_preferred) || + (preferred == target_preferred && diff < target_diff)) + { + target_mode = mode; + target_diff = diff; + target_preferred = preferred; + } } - for (i = 0; i < xf86_config->num_output; i++) + return target_mode; +} + +static DisplayModePtr +xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + + /* + * Pick a mode closest to the specified mode + */ + for (mode = output->probed_modes; mode; mode = mode->next) { - xf86OutputPtr output = xf86_config->output[i]; + int dx, dy; + int diff; + + /* exact matches are preferred */ + if (xf86ModesEqual (mode, match)) + return mode; - if (!output->randr_output) - output->randr_output = RROutputCreate (output->name, - strlen (output->name), - output); - if (!output->randr_output) - return FALSE; + dx = match->HDisplay - mode->HDisplay; + dy = match->VDisplay - mode->VDisplay; + diff = dx * dx + dy * dy; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } } -#endif - return TRUE; + return target_mode; +} + +static Bool +xf86OutputHasPreferredMode (xf86OutputPtr output) +{ + DisplayModePtr mode; + + for (mode = output->probed_modes; mode; mode = mode->next) + if (mode->type & M_T_PREFERRED) + return TRUE; + return FALSE; +} + +static int +xf86PickCrtcs (ScrnInfoPtr pScrn, + xf86CrtcPtr *best_crtcs, + DisplayModePtr *modes, + int n) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c, o, l; + xf86OutputPtr output; + xf86CrtcPtr crtc; + xf86CrtcPtr *crtcs; + xf86CrtcPtr best_crtc; + int best_score; + int score; + int my_score; + + if (n == config->num_output) + return 0; + output = config->output[n]; + + /* + * Compute score with this output disabled + */ + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1); + if (modes[n] == NULL) + return best_score; + + crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr)); + if (!crtcs) + return best_score; + + my_score = 1; + /* Score outputs that are known to be connected higher */ + if (output->status == XF86OutputStatusConnected) + my_score++; + /* Score outputs with preferred modes higher */ + if (xf86OutputHasPreferredMode (output)) + my_score++; + /* + * Select a crtc for this output and + * then attempt to configure the remaining + * outputs + */ + for (c = 0; c < config->num_crtc; c++) + { + if ((output->possible_crtcs & (1 << c)) == 0) + continue; + + crtc = config->crtc[c]; + /* + * Check to see if some other output is + * using this crtc + */ + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + if (o < n) + { + /* + * If the two outputs desire the same mode, + * see if they can be cloned + */ + if (xf86ModesEqual (modes[o], modes[n])) + { + for (l = 0; l < config->num_output; l++) + if (output->possible_clones & (1 << l)) + break; + if (l == config->num_output) + continue; /* nope, try next CRTC */ + } + else + continue; /* different modes, can't clone */ + } + crtcs[n] = crtc; + memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); + score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1); + if (score >= best_score) + { + best_crtc = crtc; + best_score = score; + memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); + } + } + xfree (crtcs); + return best_score; +} + + +/* + * Compute the virtual size necessary to place all of the available + * crtcs in a panorama configuration + */ + +static void +xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int width = 0, height = 0; + int o; + int c; + int s; + + for (c = 0; c < config->num_crtc; c++) + { + int crtc_width = 1600, crtc_height = 1200; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + for (s = 0; s < config->num_crtc; s++) + if (output->possible_crtcs & (1 << s)) + { + DisplayModePtr mode; + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (mode->HDisplay > crtc_width) + crtc_width = mode->HDisplay; + if (mode->VDisplay > crtc_width) + crtc_height = mode->VDisplay; + } + } + } + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + } + *widthp = width; + *heightp = height; } void -xf86CrtcCloseScreen (ScreenPtr pScreen) +xf86ProbeOutputModes (ScrnInfoPtr pScrn) { -#ifdef RANDR_12_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + Bool properties_set = FALSE; + int o; - for (i = 0; i < xf86_config->num_crtc; i++) + /* Probe the list of modes for each output. */ + for (o = 0; o < config->num_output; o++) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; - crtc->randr_crtc = NULL; - } - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - output->randr_output = NULL; - } + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode; + + while (output->probed_modes != NULL) + xf86DeleteMode(&output->probed_modes, output->probed_modes); + + output->probed_modes = (*output->funcs->get_modes) (output); + + /* Set the DDC properties to whatever first output has DDC information. + */ + if (output->MonInfo != NULL && !properties_set) { + xf86SetDDCproperties(pScrn, output->MonInfo); + properties_set = TRUE; + } + +#ifdef DEBUG_REPROBE + if (output->probed_modes != NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Printing probed modes for output %s\n", + output->name); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No remaining probed modes for output %s\n", + output->name); + } #endif + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + mode->VRefresh = xf86ModeVRefresh(mode); + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + +#ifdef DEBUG_REPROBE + xf86PrintModeline(pScrn->scrnIndex, mode); +#endif + } + } +} + + +/** + * Copy one of the output mode lists to the ScrnInfo record + */ + +/* XXX where does this function belong? Here? */ +void +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y); + +void +xf86SetScrnInfoModes (ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + DisplayModePtr last, mode; + int originalVirtualX, originalVirtualY; + + output = config->output[config->compat_output]; + if (!output->crtc) + { + int o; + + output = NULL; + for (o = 0; o < config->num_output; o++) + if (config->output[o]->crtc) + { + config->compat_output = o; + output = config->output[o]; + break; + } + /* no outputs are active, punt and leave things as they are */ + if (!output) + return; + } + crtc = output->crtc; + + /* Clear any existing modes from pScrn->modes */ + while (pScrn->modes != NULL) + xf86DeleteMode(&pScrn->modes, pScrn->modes); + + /* 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; + + /* For some reason, pScrn->modes is circular, unlike the other mode lists. + * How great is that? + */ + for (last = pScrn->modes; last && last->next; last = last->next); + last->next = pScrn->modes; + pScrn->modes->prev = last; + if (mode) + while (pScrn->modes != mode) + pScrn->modes = pScrn->modes->next; + pScrn->currentMode = pScrn->modes; +} + +/** + * Construct default screen configuration + * + * Given auto-detected (and, eventually, configured) values, + * construct a usable configuration for the system + */ + +Bool +xf86InitialConfiguration (ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, c; + DisplayModePtr target_mode = NULL; + xf86CrtcPtr *crtcs; + DisplayModePtr *modes; + int width, height; + + xf86ProbeOutputModes (pScrn); + + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); + modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); + + for (o = 0; o < config->num_output; o++) + modes[o] = NULL; + + /* + * Let outputs with preferred modes drive screen size + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->status != XF86OutputStatusDisconnected && + xf86OutputHasPreferredMode (output)) + { + target_mode = xf86DefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + config->compat_output = o; + break; + } + } + } + if (!target_mode) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (output->status != XF86OutputStatusDisconnected) + { + target_mode = xf86DefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + config->compat_output = o; + break; + } + } + } + } + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->status != XF86OutputStatusDisconnected && !modes[o]) + modes[o] = xf86ClosestMode (output, target_mode); + } + + if (!xf86PickCrtcs (pScrn, crtcs, modes, 0)) + { + xfree (crtcs); + xfree (modes); + return FALSE; + } + + xf86DefaultScreenLimits (pScrn, &width, &height); + + /* + * Expand virtual size to cover potential mode switches + */ + if (width > pScrn->virtualX) + pScrn->virtualX = width; + if (width > pScrn->display->virtualX) + pScrn->display->virtualX = width; + if (height > pScrn->virtualY) + pScrn->virtualY = height; + if (height > pScrn->display->virtualY) + pScrn->display->virtualY = height; + + /* XXX override xf86 common frame computation code */ + + pScrn->display->frameX0 = 0; + pScrn->display->frameY0 = 0; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->enabled = FALSE; + memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); + } + + /* + * Set initial configuration + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode = modes[o]; + xf86CrtcPtr crtc = crtcs[o]; + + if (mode && crtc) + { + crtc->desiredMode = *mode; + crtc->enabled = TRUE; + crtc->x = 0; + crtc->y = 0; + output->crtc = crtc; + /* XXX set position; for now, we clone */ + } + } + + /* Mirror output modes to pScrn mode list */ + xf86SetScrnInfoModes (pScrn); + + xfree (crtcs); + xfree (modes); + return TRUE; } diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 21ba1fcf..9b7f788c 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -28,6 +28,12 @@ typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr; +typedef enum _xf86OutputStatus { + XF86OutputStatusConnected, + XF86OutputStatusDisconnected, + XF86OutputStatusUnknown, +} xf86OutputStatus; + typedef struct _xf86CrtcFuncs { /** * Turns the crtc on/off, or sets intermediate power levels if available. @@ -186,7 +192,7 @@ typedef struct _xf86OutputFuncs { /** * Probe for a connected output, and return detect_status. */ - enum detect_status + xf86OutputStatus (*detect)(xf86OutputPtr output); /** @@ -211,12 +217,23 @@ struct _xf86Output { * Associated ScrnInfo */ ScrnInfoPtr scrn; + /** * Currently connected crtc (if any) * * If this output is not in use, this field will be NULL. */ xf86CrtcPtr crtc; + + /** + * Possible CRTCs for this output as a mask of crtc indices + */ + CARD32 possible_crtcs; + + /** + * Possible outputs to share the same CRTC as a mask of output indices + */ + CARD32 possible_clones; /** * List of available modes on this output. * @@ -225,9 +242,20 @@ struct _xf86Output { */ DisplayModePtr probed_modes; + /** + * Current connection status + * + * This indicates whether a monitor is known to be connected + * to this output or not, or whether there is no way to tell + */ + xf86OutputStatus status; + /** EDID monitor information */ xf86MonPtr MonInfo; + /** subpixel order */ + int subpixel_order; + /** Physical size of the currently attached output device. */ int mm_width, mm_height; @@ -253,12 +281,20 @@ struct _xf86Output { #endif }; +/* XXX yes, static allocation is a kludge */ #define XF86_MAX_CRTC 4 #define XF86_MAX_OUTPUT 16 typedef struct _xf86CrtcConfig { int num_output; xf86OutputPtr output[XF86_MAX_OUTPUT]; + /** + * compat_output is used whenever we deal + * with legacy code that only understands a single + * output. pScrn->modes will be loaded from this output, + * adjust frame will whack this output, etc. + */ + int compat_output; int num_crtc; xf86CrtcPtr crtc[XF86_MAX_CRTC]; @@ -307,10 +343,13 @@ xf86OutputCreate (ScrnInfoPtr scrn, void xf86OutputDestroy (xf86OutputPtr output); -Bool -xf86CrtcScreenInit (ScreenPtr pScreen); +void +xf86ProbeOutputModes (ScrnInfoPtr pScrn); void -xf86CrtcCloseScreen (ScreenPtr pScreen); +xf86SetScrnInfoModes (ScrnInfoPtr pScrn); + +Bool +xf86InitialConfiguration (ScrnInfoPtr pScrn); #endif /* _XF86CRTC_H_ */ From 1cb6311c1182fe98d2b8d237cef42509c3178f9a Mon Sep 17 00:00:00 2001 From: Wang Zhenyu Date: Wed, 6 Dec 2006 16:31:00 +0800 Subject: [PATCH 15/26] fix typo in checking xf86CrtcScreenInit return --- src/i830_randr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 00770201..a6d71f2d 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -900,7 +900,7 @@ xf86RandR12Init12 (ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; rrScrPrivPtr rp = rrGetScrPriv(pScreen); - if (xf86CrtcScreenInit (pScreen)) + if (!xf86CrtcScreenInit (pScreen)) return FALSE; rp->rrGetInfo = xf86RandR12GetInfo12; From 236c53be5d94798d55219651a6885fee32ce175b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 10:10:27 -0800 Subject: [PATCH 16/26] Fix LVDS fixed mode code after generic-mode-set. --- src/i830.h | 13 +------------ src/i830_bios.c | 45 +++++++++++++++++++++++------------------- src/i830_lvds.c | 52 ++++++++++++++++--------------------------------- 3 files changed, 43 insertions(+), 67 deletions(-) diff --git a/src/i830.h b/src/i830.h index 4cfed4b4..ae6b536d 100644 --- a/src/i830.h +++ b/src/i830.h @@ -438,19 +438,8 @@ typedef struct _I830Rec { int ddc2; - /* Panel size pulled from the BIOS */ - int PanelXRes, PanelYRes; - /* The BIOS's fixed timings for the LVDS */ - int panel_fixed_clock; - int panel_fixed_hactive; - int panel_fixed_hblank; - int panel_fixed_hsyncoff; - int panel_fixed_hsyncwidth; - int panel_fixed_vactive; - int panel_fixed_vblank; - int panel_fixed_vsyncoff; - int panel_fixed_vsyncwidth; + DisplayModePtr panel_fixed_mode; int backlight_duty_cycle; /* restore backlight to this value */ diff --git a/src/i830_bios.c b/src/i830_bios.c index 0821845a..4a1bdb17 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -158,6 +158,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) struct lvds_bdb_2 *lvds2; struct lvds_bdb_2_fp_params *fpparam; struct lvds_bdb_2_fp_edid_dtd *fptiming; + DisplayModePtr fixed_mode; CARD8 *timing_ptr; id = INTEL_BIOS_8(start); @@ -197,32 +198,36 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) continue; } - pI830->PanelXRes = fpparam->x_res; - pI830->PanelYRes = fpparam->y_res; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Found panel of size %dx%d in BIOS VBT tables\n", - pI830->PanelXRes, pI830->PanelYRes); + fixed_mode = xnfalloc(sizeof(DisplayModeRec)); + memset(fixed_mode, 0, sizeof(*fixed_mode)); /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing * block, pull the contents out using EDID macros. */ - pI830->panel_fixed_clock = _PIXEL_CLOCK(timing_ptr) / 1000; - pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr); - pI830->panel_fixed_hblank = _H_BLANK(timing_ptr); - pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr); - pI830->panel_fixed_hsyncwidth = _H_SYNC_WIDTH(timing_ptr); + fixed_mode->HDisplay = _H_ACTIVE(timing_ptr); + fixed_mode->VDisplay = _V_ACTIVE(timing_ptr); + fixed_mode->HSyncStart = fixed_mode->HDisplay + + _H_SYNC_OFF(timing_ptr); + fixed_mode->HSyncEnd = fixed_mode->HSyncStart + + _H_SYNC_WIDTH(timing_ptr); + fixed_mode->HTotal = fixed_mode->HSyncEnd + + 1; + fixed_mode->VSyncStart = fixed_mode->VDisplay + + _V_SYNC_OFF(timing_ptr); + fixed_mode->VSyncEnd = fixed_mode->VSyncStart + + _V_SYNC_WIDTH(timing_ptr); + fixed_mode->VTotal = fixed_mode->VSyncEnd + 1; + fixed_mode->Clock = _PIXEL_CLOCK(timing_ptr) / 1000; + fixed_mode->type = M_T_PREFERRED; + + xf86SetModeDefaultName(fixed_mode); - pI830->panel_fixed_vactive = _V_ACTIVE(timing_ptr); - pI830->panel_fixed_vblank = _V_BLANK(timing_ptr); - pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr); - pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Panel mode h active %d blank %d rate %f v active %d blank %d rate %f\n", - pI830->panel_fixed_hactive, pI830->panel_fixed_hblank, - (double) pI830->panel_fixed_clock / (pI830->panel_fixed_hactive + pI830->panel_fixed_hblank), - pI830->panel_fixed_vactive, pI830->panel_fixed_vblank, - (double) pI830->panel_fixed_clock / - ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank) * (pI830->panel_fixed_vactive + pI830->panel_fixed_vblank))); + "Found panel mode in BIOS VBT tables:\n"); + xf86PrintModeline(pScrn->scrnIndex, fixed_mode); + + pI830->panel_fixed_mode = fixed_mode; + found_panel_info = TRUE; break; } diff --git a/src/i830_lvds.c b/src/i830_lvds.c index a9c0e204..2c044e92 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -161,22 +161,16 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, * with the panel scaling set up to source from the H/VDisplay * of the original mode. */ - if (pI830->panel_fixed_hactive != 0) { - adjusted_mode->HDisplay = pI830->panel_fixed_hactive; - adjusted_mode->HTotal = adjusted_mode->HDisplay + - pI830->panel_fixed_hblank; - adjusted_mode->HSyncStart = adjusted_mode->HDisplay + - pI830->panel_fixed_hsyncoff; - adjusted_mode->HSyncStart = adjusted_mode->HSyncStart + - pI830->panel_fixed_hsyncwidth; - adjusted_mode->VDisplay = pI830->panel_fixed_vactive; - adjusted_mode->VTotal = adjusted_mode->VDisplay + - pI830->panel_fixed_hblank; - adjusted_mode->VSyncStart = adjusted_mode->VDisplay + - pI830->panel_fixed_hsyncoff; - adjusted_mode->VSyncStart = adjusted_mode->VSyncStart + - pI830->panel_fixed_hsyncwidth; - adjusted_mode->Clock = pI830->panel_fixed_clock; + if (pI830->panel_fixed_mode != NULL) { + adjusted_mode->HDisplay = pI830->panel_fixed_mode->HDisplay; + adjusted_mode->HSyncStart = pI830->panel_fixed_mode->HSyncStart; + adjusted_mode->HSyncEnd = pI830->panel_fixed_mode->HSyncEnd; + adjusted_mode->HTotal = pI830->panel_fixed_mode->HTotal; + adjusted_mode->VDisplay = pI830->panel_fixed_mode->VDisplay; + adjusted_mode->VSyncStart = pI830->panel_fixed_mode->VSyncStart; + adjusted_mode->VSyncEnd = pI830->panel_fixed_mode->VSyncEnd; + adjusted_mode->VTotal = pI830->panel_fixed_mode->VTotal; + adjusted_mode->Clock = pI830->panel_fixed_mode->Clock; xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); } @@ -241,30 +235,16 @@ i830_lvds_get_modes(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr modes, new; - char stmp[32]; + DisplayModePtr modes; modes = i830_ddc_get_modes(output); if (modes != NULL) return modes; - new = xnfcalloc(1, sizeof (DisplayModeRec)); - sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes); - new->name = xnfalloc(strlen(stmp) + 1); - strcpy(new->name, stmp); - new->HDisplay = pI830->PanelXRes; - new->VDisplay = pI830->PanelYRes; - new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; - new->HSyncEnd = new->HSyncStart + pI830->panel_fixed_hsyncwidth; - new->HTotal = new->HSyncEnd + 1; - new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; - new->VSyncEnd = new->VSyncStart + pI830->panel_fixed_vsyncwidth; - new->VTotal = new->VSyncEnd + 1; - new->Clock = pI830->panel_fixed_clock; + if (pI830->panel_fixed_mode != NULL) + return xf86DuplicateMode(pI830->panel_fixed_mode); - new->type = M_T_PREFERRED; - - return new; + return NULL; } static void @@ -321,7 +301,9 @@ i830_lvds_init(ScrnInfoPtr pScrn) * display. */ - if (pI830->PanelXRes == 800 && pI830->PanelYRes == 600) { + if (pI830->panel_fixed_mode != NULL && + pI830->panel_fixed_mode->HDisplay == 800 && + pI830->panel_fixed_mode->VDisplay == 600) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Suspected Mac Mini, ignoring the LVDS\n"); return; From 727bf1cbf72362edcbdd68001a3558fd2b2b4eca Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 10:12:49 -0800 Subject: [PATCH 17/26] Add missing newlines to new debug output. --- src/i830_debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_debug.c b/src/i830_debug.c index 68c4b5d2..b14f9818 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -352,9 +352,9 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn) i830_snapshot[i].reg, val); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "%s before: %s", i830_snapshot[i].name, before); + "%s before: %s\n", i830_snapshot[i].name, before); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "%s after: %s", i830_snapshot[i].name, after); + "%s after: %s\n", i830_snapshot[i].name, after); } } From 47d07b1073c162ec00a8b173b8b6389dc4adbe88 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 10:56:38 -0800 Subject: [PATCH 18/26] More LVDS fixed mode fixing: use the EDID DTD's blank length. --- src/i830_bios.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/i830_bios.c b/src/i830_bios.c index 4a1bdb17..a9ef474d 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -210,13 +210,14 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) _H_SYNC_OFF(timing_ptr); fixed_mode->HSyncEnd = fixed_mode->HSyncStart + _H_SYNC_WIDTH(timing_ptr); - fixed_mode->HTotal = fixed_mode->HSyncEnd + - 1; + fixed_mode->HTotal = fixed_mode->HDisplay + + _H_BLANK(timing_ptr); fixed_mode->VSyncStart = fixed_mode->VDisplay + _V_SYNC_OFF(timing_ptr); fixed_mode->VSyncEnd = fixed_mode->VSyncStart + _V_SYNC_WIDTH(timing_ptr); - fixed_mode->VTotal = fixed_mode->VSyncEnd + 1; + fixed_mode->VTotal = fixed_mode->VDisplay + + _V_BLANK(timing_ptr); fixed_mode->Clock = _PIXEL_CLOCK(timing_ptr) / 1000; fixed_mode->type = M_T_PREFERRED; From b3bb10e33e44c78f132d239e30931f97065a9fd6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 11:53:40 -0800 Subject: [PATCH 19/26] Fix LVDS: Don't change bits in LVDS other than port enable/pipe select. This behavior matches what we did before when LVDS worked. --- src/i830_lvds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 2c044e92..97f38528 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -199,7 +199,7 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode, * This is an exception to the general rule that mode_set doesn't turn * things on. */ - OUTREG(LVDS, LVDS_PORT_EN | LVDS_PIPEB_SELECT); + OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT); /* Enable automatic panel scaling so that non-native modes fill the * screen. Should be enabled before the pipe is enabled, according to From 5d345c13a949caef384a63769d7185885de6d26d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Dec 2006 13:19:58 -0800 Subject: [PATCH 20/26] Clean up SDVO multiplier debug output --- src/i830_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_debug.c b/src/i830_debug.c index 9f4dd29d..8c8b95ee 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -159,7 +159,7 @@ DEBUGSTRING(i830_debug_dpll) break; } if (IS_I945G(pI830) || IS_I945GM(pI830)) { - sprintf(sdvoextra, "SDVO mult %d", + sprintf(sdvoextra, ", SDVO mult %d", (int)(val & SDVO_MULTIPLIER_MASK) >> SDVO_MULTIPLIER_SHIFT_HIRES); } else { From d5ec9d2160f47f21a6015c1cc05b57274cbb0471 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Dec 2006 14:44:40 -0800 Subject: [PATCH 21/26] Cannot modify DPLL register in output mode_set function. DPLL register contains clock setup, so it cannot be written from the output mode_set function or 'bad things' happen. --- src/i830_display.c | 16 +++++++++++++--- src/i830_sdvo.c | 15 ++------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 3d0c3af9..0e5a09ac 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -624,15 +624,22 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, fp = clock.n << 16 | clock.m1 << 8 | clock.m2; - i830PrintPll("chosen", &clock); - ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); - dpll = DPLL_VGA_MODE_DIS; if (IS_I9XX(pI830)) { if (is_lvds) dpll |= DPLLB_MODE_LVDS; else dpll |= DPLLB_MODE_DAC_SERIAL; + if (is_sdvo) + { + dpll |= DPLL_DVO_HIGH_SPEED; + if (IS_I945G(pI830) || IS_I945GM(pI830)) + { + int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock; + dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + } + } + /* compute bitmask from p1 value */ dpll |= (1 << (clock.p1 - 1)) << 16; switch (clock.p2) { @@ -719,6 +726,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, pipeconf &= ~PIPEACONF_DOUBLE_WIDE; } + i830PrintPll("chosen", &clock); + ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); + OUTREG(fp_reg, fp); OUTREG(dpll_reg, dpll); if (IS_I965G(pI830)) { diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 331a519a..87dc9d9e 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -557,8 +557,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, xf86CrtcPtr crtc = output->crtc; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; Bool input1, input2; - CARD32 dpll, sdvox; - int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B; + CARD32 sdvox; int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int sdvo_pixel_multiply; int i; @@ -614,9 +613,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; output_dtd.part2.reserved = 0; - /* Turn off the screens before adjusting timings */ - i830_sdvo_set_active_outputs(output, 0); - /* Set the output timing to the screen */ i830_sdvo_set_target_output(output, dev_priv->active_outputs); i830_sdvo_set_output_timing(output, &output_dtd); @@ -668,20 +664,16 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, if (intel_crtc->pipe == 1) sdvox |= SDVO_PIPE_B_SELECT; - dpll = INREG(dpll_reg); - sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); if (IS_I965G(pI830)) { OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); } else if (IS_I945G(pI830) || IS_I945GM(pI830)) { - dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + /* done in crtc_mode_set as it lives inside the dpll register */ } else { sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; } - OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED); - OUTREG(dev_priv->output_device, sdvox); for (i = 0; i < 2; i++) @@ -695,9 +687,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, "First %s output reported failure to sync\n", SDVO_NAME(dev_priv)); } - - i830_sdvo_set_active_outputs(output, dev_priv->active_outputs); - i830_sdvo_set_target_input(output, TRUE, FALSE); } static void From 9c3e733aaa2068fcb0164577237ed70d177e9b5a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 16:36:42 -0800 Subject: [PATCH 22/26] Save/restore more TV registers. --- src/i830_tv.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/i830_tv.c b/src/i830_tv.c index d44d58eb..9f92ce00 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -59,6 +59,26 @@ struct i830_tv_priv { CARD32 save_TV_V_CTL_6; CARD32 save_TV_V_CTL_7; CARD32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3; + + CARD32 save_TV_CSC_Y; + CARD32 save_TV_CSC_Y2; + CARD32 save_TV_CSC_U; + CARD32 save_TV_CSC_U2; + CARD32 save_TV_CSC_V; + CARD32 save_TV_CSC_V2; + CARD32 save_TV_CLR_KNOBS; + CARD32 save_TV_CLR_LEVEL; + CARD32 save_TV_WIN_POS; + CARD32 save_TV_WIN_SIZE; + CARD32 save_TV_FILTER_CTL_1; + CARD32 save_TV_FILTER_CTL_2; + CARD32 save_TV_FILTER_CTL_3; + + CARD32 save_TV_H_LUMA[60]; + CARD32 save_TV_H_CHROMA[60]; + CARD32 save_TV_V_LUMA[43]; + CARD32 save_TV_V_CHROMA[43]; + CARD32 save_TV_DAC; CARD32 save_TV_CTL; }; @@ -168,6 +188,7 @@ i830_tv_save(xf86OutputPtr output) I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; struct i830_tv_priv *dev_priv = intel_output->dev_priv; + int i; dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1); dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2); @@ -183,6 +204,29 @@ i830_tv_save(xf86OutputPtr output) dev_priv->save_TV_SC_CTL_2 = INREG(TV_SC_CTL_2); dev_priv->save_TV_SC_CTL_3 = INREG(TV_SC_CTL_3); + dev_priv->save_TV_CSC_Y = INREG(TV_CSC_Y); + dev_priv->save_TV_CSC_Y2 = INREG(TV_CSC_Y2); + dev_priv->save_TV_CSC_U = INREG(TV_CSC_U); + dev_priv->save_TV_CSC_U2 = INREG(TV_CSC_U2); + dev_priv->save_TV_CSC_V = INREG(TV_CSC_V); + dev_priv->save_TV_CSC_V2 = INREG(TV_CSC_V2); + dev_priv->save_TV_CLR_KNOBS = INREG(TV_CLR_KNOBS); + dev_priv->save_TV_CLR_LEVEL = INREG(TV_CLR_LEVEL); + dev_priv->save_TV_WIN_POS = INREG(TV_WIN_POS); + dev_priv->save_TV_WIN_SIZE = INREG(TV_WIN_SIZE); + dev_priv->save_TV_FILTER_CTL_1 = INREG(TV_FILTER_CTL_1); + dev_priv->save_TV_FILTER_CTL_2 = INREG(TV_FILTER_CTL_2); + dev_priv->save_TV_FILTER_CTL_3 = INREG(TV_FILTER_CTL_3); + + for (i = 0; i < 60; i++) + dev_priv->save_TV_H_LUMA[i] = INREG(TV_H_LUMA_0 + (i <<2)); + for (i = 0; i < 60; i++) + dev_priv->save_TV_H_CHROMA[i] = INREG(TV_H_CHROMA_0 + (i <<2)); + for (i = 0; i < 43; i++) + dev_priv->save_TV_V_LUMA[i] = INREG(TV_V_LUMA_0 + (i <<2)); + for (i = 0; i < 43; i++) + dev_priv->save_TV_V_CHROMA[i] = INREG(TV_V_CHROMA_0 + (i <<2)); + dev_priv->save_TV_DAC = INREG(TV_DAC); dev_priv->save_TV_CTL = INREG(TV_CTL); } @@ -194,6 +238,7 @@ i830_tv_restore(xf86OutputPtr output) I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; struct i830_tv_priv *dev_priv = intel_output->dev_priv; + int i; OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1); OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2); @@ -209,6 +254,29 @@ i830_tv_restore(xf86OutputPtr output) OUTREG(TV_SC_CTL_2, dev_priv->save_TV_SC_CTL_2); OUTREG(TV_SC_CTL_3, dev_priv->save_TV_SC_CTL_3); + OUTREG(TV_CSC_Y, dev_priv->save_TV_CSC_Y); + OUTREG(TV_CSC_Y2, dev_priv->save_TV_CSC_Y2); + OUTREG(TV_CSC_U, dev_priv->save_TV_CSC_U); + OUTREG(TV_CSC_U2, dev_priv->save_TV_CSC_U2); + OUTREG(TV_CSC_V, dev_priv->save_TV_CSC_V); + OUTREG(TV_CSC_V2, dev_priv->save_TV_CSC_V2); + OUTREG(TV_CLR_KNOBS, dev_priv->save_TV_CLR_KNOBS); + OUTREG(TV_CLR_LEVEL, dev_priv->save_TV_CLR_LEVEL); + OUTREG(TV_WIN_POS, dev_priv->save_TV_WIN_POS); + OUTREG(TV_WIN_SIZE, dev_priv->save_TV_WIN_SIZE); + OUTREG(TV_FILTER_CTL_1, dev_priv->save_TV_FILTER_CTL_1); + OUTREG(TV_FILTER_CTL_2, dev_priv->save_TV_FILTER_CTL_2); + OUTREG(TV_FILTER_CTL_3, dev_priv->save_TV_FILTER_CTL_3); + + for (i = 0; i < 60; i++) + OUTREG(TV_H_LUMA_0 + (i <<2), dev_priv->save_TV_H_LUMA[i]); + for (i = 0; i < 60; i++) + OUTREG(TV_H_CHROMA_0 + (i <<2), dev_priv->save_TV_H_CHROMA[i]); + for (i = 0; i < 43; i++) + OUTREG(TV_V_LUMA_0 + (i <<2), dev_priv->save_TV_V_LUMA[i]); + for (i = 0; i < 43; i++) + OUTREG(TV_V_CHROMA_0 + (i <<2), dev_priv->save_TV_V_CHROMA[i]); + OUTREG(TV_DAC, dev_priv->save_TV_DAC); OUTREG(TV_CTL, dev_priv->save_TV_CTL); } From d3c21c09e3904b3d32aca7563044194b061ac2fa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 16:50:52 -0800 Subject: [PATCH 23/26] Remove stale i830_tv_pre_set_mode. Replaced by generic dpms hook call. Also replaced by not spamming unrelated ADPA register. At least, it had sure better not be related. --- src/i830_tv.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/i830_tv.c b/src/i830_tv.c index 9f92ce00..b6cc2c9b 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -287,18 +287,6 @@ i830_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) return MODE_OK; } -static void -i830_tv_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode) -{ - ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); - - /* Disable the encoder while we set up the pipe. */ - OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE); - /* XXX match BIOS for now */ - OUTREG(ADPA, 0x40008C18); -} - static const CARD32 h_luma[60] = { 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140, 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000, From b23dec37b28a76433ad5d537ab508294e843cabe Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 16:58:24 -0800 Subject: [PATCH 24/26] Save/restore registers around calls in PreInit with register side-effects. --- src/i830_driver.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index ec41a56a..9428476e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1401,12 +1401,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->Clone = TRUE; } - -#if 0 - SaveHWState (pScrn); -#endif - /* Perform the pipe assignment of outputs. This is a kludge until - * we have better configuration support in the generic RandR code + SaveHWState(pScrn); + /* Do an initial detection of the outputs while none are configured on yet. + * This will give us some likely legitimate response for later if both + * pipes are already allocated and we're asked to do a detect. */ for (i = 0; i < pI830->xf86_config.num_output; i++) { @@ -1414,16 +1412,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) output->status = (*output->funcs->detect) (output); } -#if 0 - RestoreHWState (pScrn); -#endif - + if (!xf86InitialConfiguration (pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + RestoreHWState(pScrn); PreInitCleanup(pScrn); return FALSE; } + RestoreHWState(pScrn); + pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; pI830->rotation = RR_Rotate_0; From c6ce8a3c3355e8a56e86856caa56baf1cd3c0231 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 17:07:48 -0800 Subject: [PATCH 25/26] Reduce dumpregs to X startup, after a mode set, and LeaveVT. While here, remove some other register dumping that is better done by i830DumpRegs(). --- src/i830_driver.c | 215 ++-------------------------------------------- 1 file changed, 7 insertions(+), 208 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 9428476e..53c0ab85 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1184,6 +1184,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Some of the probing needs MMIO access, so map it here. */ I830MapMMIO(pScrn); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state on X startup:\n"); + i830DumpRegs (pScrn); + i830TakeRegSnapshot(pScrn); #if 1 @@ -2177,18 +2180,6 @@ SaveHWState(ScrnInfoPtr pScrn) CARD32 temp; int i; - /* - * Print out the PIPEACONF and PIPEBCONF registers. - */ - temp = INREG(PIPEACONF); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", - (unsigned long) temp); - if (pI830->xf86_config.num_crtc == 2) { - temp = INREG(PIPEBCONF); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", - (unsigned long) temp); - } - /* Save video mode information for native mode-setting. */ pI830->saveDSPACNTR = INREG(DSPACNTR); pI830->savePIPEACONF = INREG(PIPEACONF); @@ -2386,9 +2377,6 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(SWF31, pI830->saveSWF[15]); OUTREG(SWF32, pI830->saveSWF[16]); - i830CompareRegsToSnapshot(pScrn, "After RestoreHWState"); - i830DumpRegs (pScrn); - return TRUE; } @@ -2502,195 +2490,6 @@ I965PrintErrorState(ScrnInfoPtr pScrn) } -#ifdef I830DEBUG -static void -dump_DSPACNTR(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned int tmp; - - /* Display A Control */ - tmp = INREG(0x70180); - ErrorF("Display A Plane Control Register (0x%.8x)\n", tmp); - - if (tmp & BIT(31)) - ErrorF(" Display Plane A (Primary) Enable\n"); - else - ErrorF(" Display Plane A (Primary) Disabled\n"); - - if (tmp & BIT(30)) - ErrorF(" Display A pixel data is gamma corrected\n"); - else - ErrorF(" Display A pixel data bypasses gamma correction logic (default)\n"); - - switch ((tmp & 0x3c000000) >> 26) { /* bit 29:26 */ - case 0x00: - case 0x01: - case 0x03: - ErrorF(" Reserved\n"); - break; - case 0x02: - ErrorF(" 8-bpp Indexed\n"); - break; - case 0x04: - ErrorF(" 15-bit (5-5-5) pixel format (Targa compatible)\n"); - break; - case 0x05: - ErrorF(" 16-bit (5-6-5) pixel format (XGA compatible)\n"); - break; - case 0x06: - ErrorF(" 32-bit format (X:8:8:8)\n"); - break; - case 0x07: - ErrorF(" 32-bit format (8:8:8:8)\n"); - break; - default: - ErrorF(" Unknown - Invalid register value maybe?\n"); - } - - if (tmp & BIT(25)) - ErrorF(" Stereo Enable\n"); - else - ErrorF(" Stereo Disable\n"); - - if (tmp & BIT(24)) - ErrorF(" Display A, Pipe B Select\n"); - else - ErrorF(" Display A, Pipe A Select\n"); - - if (tmp & BIT(22)) - ErrorF(" Source key is enabled\n"); - else - ErrorF(" Source key is disabled\n"); - - switch ((tmp & 0x00300000) >> 20) { /* bit 21:20 */ - case 0x00: - ErrorF(" No line duplication\n"); - break; - case 0x01: - ErrorF(" Line/pixel Doubling\n"); - break; - case 0x02: - case 0x03: - ErrorF(" Reserved\n"); - break; - } - - if (tmp & BIT(18)) - ErrorF(" Stereo output is high during second image\n"); - else - ErrorF(" Stereo output is high during first image\n"); -} - -static void -dump_DSPBCNTR(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned int tmp; - - /* Display B/Sprite Control */ - tmp = INREG(0x71180); - ErrorF("Display B/Sprite Plane Control Register (0x%.8x)\n", tmp); - - if (tmp & BIT(31)) - ErrorF(" Display B/Sprite Enable\n"); - else - ErrorF(" Display B/Sprite Disable\n"); - - if (tmp & BIT(30)) - ErrorF(" Display B pixel data is gamma corrected\n"); - else - ErrorF(" Display B pixel data bypasses gamma correction logic (default)\n"); - - switch ((tmp & 0x3c000000) >> 26) { /* bit 29:26 */ - case 0x00: - case 0x01: - case 0x03: - ErrorF(" Reserved\n"); - break; - case 0x02: - ErrorF(" 8-bpp Indexed\n"); - break; - case 0x04: - ErrorF(" 15-bit (5-5-5) pixel format (Targa compatible)\n"); - break; - case 0x05: - ErrorF(" 16-bit (5-6-5) pixel format (XGA compatible)\n"); - break; - case 0x06: - ErrorF(" 32-bit format (X:8:8:8)\n"); - break; - case 0x07: - ErrorF(" 32-bit format (8:8:8:8)\n"); - break; - default: - ErrorF(" Unknown - Invalid register value maybe?\n"); - } - - if (tmp & BIT(25)) - ErrorF(" Stereo is enabled and both start addresses are used in a two frame sequence\n"); - else - ErrorF(" Stereo disable and only a single start address is used\n"); - - if (tmp & BIT(24)) - ErrorF(" Display B/Sprite, Pipe B Select\n"); - else - ErrorF(" Display B/Sprite, Pipe A Select\n"); - - if (tmp & BIT(22)) - ErrorF(" Sprite source key is enabled\n"); - else - ErrorF(" Sprite source key is disabled (default)\n"); - - switch ((tmp & 0x00300000) >> 20) { /* bit 21:20 */ - case 0x00: - ErrorF(" No line duplication\n"); - break; - case 0x01: - ErrorF(" Line/pixel Doubling\n"); - break; - case 0x02: - case 0x03: - ErrorF(" Reserved\n"); - break; - } - - if (tmp & BIT(18)) - ErrorF(" Stereo output is high during second image\n"); - else - ErrorF(" Stereo output is high during first image\n"); - - if (tmp & BIT(15)) - ErrorF(" Alpha transfer mode enabled\n"); - else - ErrorF(" Alpha transfer mode disabled\n"); - - if (tmp & BIT(0)) - ErrorF(" Sprite is above overlay\n"); - else - ErrorF(" Sprite is above display A (default)\n"); -} - -void -I830_dump_registers(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned int i; - - ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); - - dump_DSPACNTR(pScrn); - dump_DSPBCNTR(pScrn); - - ErrorF("0x71400 == 0x%.8x\n", INREG(0x71400)); - ErrorF("0x70008 == 0x%.8x\n", INREG(0x70008)); - for (i = 0x71410; i <= 0x71428; i += 4) - ErrorF("0x%x == 0x%.8x\n", i, INREG(i)); - - ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); -} -#endif - static void I830PointerMoved(int index, int x, int y) { @@ -3302,10 +3101,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); -#ifdef I830DEBUG - I830_dump_registers(pScrn); -#endif - if (IS_I965G(pI830)) { /* turn off clock gating */ #if 0 @@ -3477,6 +3272,10 @@ I830LeaveVT(int scrnIndex, int flags) ResetState(pScrn, TRUE); RestoreHWState(pScrn); + + i830CompareRegsToSnapshot(pScrn, "After LeaveVT"); + i830DumpRegs (pScrn); + if (I830IsPrimary(pScrn)) I830UnbindAGPMemory(pScrn); if (pI830->AccelInfoRec) From 6777d8044d5cc063698e05afb7a93a58a7a3b64a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Dec 2006 17:10:06 -0800 Subject: [PATCH 26/26] Harmless warning fix. --- src/i830_driver.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 53c0ab85..2f515ede 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2177,7 +2177,6 @@ SaveHWState(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; - CARD32 temp; int i; /* Save video mode information for native mode-setting. */