diff options
author | Keith Packard <keithp@neko.keithp.com> | 2007-07-09 21:29:55 -0700 |
---|---|---|
committer | Kyle McMartin <kyle@freedesktop.org> | 2007-07-26 19:45:34 -0400 |
commit | 9d6fca93760b7fba7dfb774171eca94ca52d0115 (patch) | |
tree | a98e23f5c77367967d943d18a108c9a294b57207 /src/i830_crt.c | |
parent | 3c552af65d28fafec1d09484a8914b690b961349 (diff) |
Eliminate bogus (and harmful) blanking adjustment for load detect.
Instead of always adding blanking to mode lines, use the FORCE_BORDER option
on i9xx hardware where it works, and dynamically add a bit of border if
necessary on i8xx hardware to make load detection work. This may cause
flashing when a usable crtc is not otherwise idle when load detection is
requested.
(cherry picked from commit 6f18300aed1340348c6d395f326061b5315be643)
Diffstat (limited to 'src/i830_crt.c')
-rw-r--r-- | src/i830_crt.c | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/src/i830_crt.c b/src/i830_crt.c index 6d70f39a..1900dfb7 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -209,10 +209,8 @@ i830_crt_detect_load (xf86CrtcPtr crtc, CARD32 dsl; CARD8 st00; int bclrpat_reg, pipeconf_reg, pipe_dsl_reg; - int vtotal_reg; - int vblank_reg; + int vtotal_reg, vblank_reg, vsync_reg; int pipe = i830_crtc->pipe; - int count, detect; Bool present; if (pipe == 0) @@ -220,6 +218,7 @@ i830_crt_detect_load (xf86CrtcPtr crtc, bclrpat_reg = BCLRPAT_A; vtotal_reg = VTOTAL_A; vblank_reg = VBLANK_A; + vsync_reg = VSYNC_A; pipeconf_reg = PIPEACONF; pipe_dsl_reg = PIPEA_DSL; } @@ -228,6 +227,7 @@ i830_crt_detect_load (xf86CrtcPtr crtc, bclrpat_reg = BCLRPAT_B; vtotal_reg = VTOTAL_B; vblank_reg = VBLANK_B; + vsync_reg = VSYNC_B; pipeconf_reg = PIPEBCONF; pipe_dsl_reg = PIPEB_DSL; } @@ -242,45 +242,78 @@ i830_crt_detect_load (xf86CrtcPtr crtc, vblank_start = (vblank & 0xfff) + 1; vblank_end = ((vblank >> 16) & 0xfff) + 1; - /* sample in the vertical border, selecting the larger one */ - if (vblank_start - vactive >= vtotal - vblank_end) - vsample = (vblank_start + vactive) >> 1; - else - vsample = (vtotal + vblank_end) >> 1; - /* Set the border color to purple. */ OUTREG(bclrpat_reg, 0x500050); - /* - * Wait for the border to be displayed - */ - while (INREG(pipe_dsl_reg) >= vactive) - ; - while ((dsl = INREG(pipe_dsl_reg)) <= vsample) - ; - /* - * Watch ST00 for an entire scanline - */ - detect = 0; - count = 0; - do { - count++; - /* Read the ST00 VGA status register */ - st00 = pI830->readStandard(pI830, 0x3c2); - if (st00 & (1 << 4)) - detect++; - } while ((INREG(pipe_dsl_reg) == dsl)); + if (IS_I9XX (pI830)) + { + CARD32 pipeconf = INREG(pipeconf_reg); + OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); + + st00 = pI830->readStandard (pI830, 0x3c2); + present = (st00 & (1 << 4)) != 0; + OUTREG(pipeconf_reg, pipeconf); + } + else + { + Bool restore_vblank = FALSE; + int count, detect; + + /* + * If there isn't any border, add some. + * Yes, this will flicker + */ + if (vblank_start <= vactive && vblank_end >= vtotal) + { + CARD32 vsync = INREG(vsync_reg); + CARD32 vsync_start = (vsync & 0xffff) + 1; + + vblank_start = vsync_start; + OUTREG(vblank_reg, (vblank_start - 1) | ((vblank_end - 1) << 16)); + restore_vblank = TRUE; + } + + /* sample in the vertical border, selecting the larger one */ + if (vblank_start - vactive >= vtotal - vblank_end) + vsample = (vblank_start + vactive) >> 1; + else + vsample = (vtotal + vblank_end) >> 1; + + /* + * Wait for the border to be displayed + */ + while (INREG(pipe_dsl_reg) >= vactive) + ; + while ((dsl = INREG(pipe_dsl_reg)) <= vsample) + ; + /* + * Watch ST00 for an entire scanline + */ + detect = 0; + count = 0; + do { + count++; + /* Read the ST00 VGA status register */ + st00 = pI830->readStandard(pI830, 0x3c2); + if (st00 & (1 << 4)) + detect++; + } while ((INREG(pipe_dsl_reg) == dsl)); + + /* restore vblank if necessary */ + if (restore_vblank) + OUTREG(vblank_reg, vblank); + /* + * If more than 3/4 of the scanline detected a monitor, + * then it is assumed to be present. This works even on i830, + * where there isn't any way to force the border color across + * the screen + */ + present = detect * 4 > count * 3; + } /* Restore previous settings */ OUTREG(bclrpat_reg, save_bclrpat); - /* - * If more than 3/4 of the scanline detected a monitor, - * then it is assumed to be present. This works even on i830, - * where there isn't any way to force the border color across - * the screen - */ - present = detect * 4 > count * 3; return present; } @@ -352,10 +385,17 @@ i830_crt_detect(xf86OutputPtr output) if (!crtc->enabled) { xf86SetModeCrtc (&mode, INTERLACE_HALVE_V); + /* + * Give us some border at the bottom for load detection on i8xx + */ + mode.CrtcVBlankStart = mode.CrtcVSyncStart; + if (mode.CrtcVBlankEnd - mode.CrtcVBlankStart < 3) + mode.CrtcVBlankStart = mode.CrtcVBlankEnd - 3; xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0); } else if (intel_output->load_detect_temp) { + /* Add this output to the crtc */ output->funcs->mode_set (output, &crtc->mode, &crtc->mode); output->funcs->commit (output); } |