summaryrefslogtreecommitdiff
path: root/src/i830_crt.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@neko.keithp.com>2007-07-09 21:29:55 -0700
committerKeith Packard <keithp@neko.keithp.com>2007-07-13 13:39:36 -0700
commit6f18300aed1340348c6d395f326061b5315be643 (patch)
treed66e1598f709c7359fefcba8c3b1532814742f77 /src/i830_crt.c
parent04130ac6b705aa49161fb6dae83ad0bdd76e89d9 (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.
Diffstat (limited to 'src/i830_crt.c')
-rw-r--r--src/i830_crt.c110
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);
}