xf86-video-intel: 3 commits - src/i830_crt.c src/i830_display.c src/i830_display.h src/i830.h src/i830_tv.c
Keith Packard
keithp at kemper.freedesktop.org
Fri Jul 13 13:42:04 PDT 2007
src/i830.h | 2
src/i830_crt.c | 140 ++++++++++++++++++++++++++++-------------------------
src/i830_display.c | 103 ++++++++++++++++++++++++++++++++------
src/i830_display.h | 4 -
src/i830_tv.c | 19 +------
5 files changed, 168 insertions(+), 100 deletions(-)
New commits:
diff-tree ff2be3995d33f9e4b7f63b380f166b6168c9b9c6 (from 00f4587025a3879626623135b0a153fcdb906719)
Author: Keith Packard <keithp at neko.keithp.com>
Date: Fri Jul 13 12:47:18 2007 -0700
Remove hard-coded CRT blanking frobbing for load detection.
CRT blanking needn't be adjusted to perform load detection on 9xx chips, and
the 8xx load detection path now adjusts blanking just during load detection.
Adjusting the blanking interval turned out to cause many monitors to fail to
sync.
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 9e6180e..d7762a0 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -97,8 +97,6 @@ static Bool
i830_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
- /* disable blanking so we can detect monitors */
- adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVTotal - 3;
return TRUE;
}
@@ -360,8 +358,8 @@ i830_crt_detect(xf86OutputPtr output)
return XF86OutputStatusDisconnected;
}
-// if (i830_crt_detect_ddc(output))
-// return XF86OutputStatusConnected;
+ if (i830_crt_detect_ddc(output))
+ return XF86OutputStatusConnected;
/* Use the load-detect method if we have no other way of telling. */
crtc = i830GetLoadDetectPipe (output, NULL, &dpms_mode);
diff --git a/src/i830_display.c b/src/i830_display.c
index 16af496..26873fe 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1509,6 +1509,8 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
output->funcs->commit (output);
}
+ /* let the output get through one full cycle before testing */
+ i830WaitForVblank (pScrn);
return crtc;
}
diff-tree 00f4587025a3879626623135b0a153fcdb906719 (from 6f18300aed1340348c6d395f326061b5315be643)
Author: Keith Packard <keithp at neko.keithp.com>
Date: Fri Jul 13 10:58:06 2007 -0700
Ensure pipe/output active before doing load detection.
If the pipe or output have been set to DPMSOff, then load detection will not
work correctly. Also, share the load detection configuration code between
crt and tv outputs.
diff --git a/src/i830.h b/src/i830.h
index 409057c..b85ee26 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -220,6 +220,8 @@ typedef struct _I830CrtcPrivateRec {
Bool enabled;
+ int dpms_mode;
+
/* Lookup table values to be set when the CRTC is enabled */
CARD8 lut_r[256], lut_g[256], lut_b[256];
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 1900dfb..9e6180e 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -349,8 +349,9 @@ i830_crt_detect(xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
- xf86CrtcPtr crtc;
-
+ xf86CrtcPtr crtc;
+ int dpms_mode;
+
if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830) ||
IS_G33CLASS(pI830)) {
if (i830_crt_detect_hotplug(output))
@@ -359,49 +360,18 @@ i830_crt_detect(xf86OutputPtr output)
return XF86OutputStatusDisconnected;
}
- if (i830_crt_detect_ddc(output))
- return XF86OutputStatusConnected;
+// if (i830_crt_detect_ddc(output))
+// return XF86OutputStatusConnected;
/* Use the load-detect method if we have no other way of telling. */
- crtc = i830GetLoadDetectPipe (output);
+ crtc = i830GetLoadDetectPipe (output, NULL, &dpms_mode);
if (crtc)
{
- /* VESA 640x480x72Hz mode to set on the pipe */
- static DisplayModeRec mode = {
- NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
- 31500,
- 640, 664, 704, 832, 0,
- 480, 489, 491, 520, 0,
- V_NHSYNC | V_NVSYNC,
- 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
- };
Bool connected;
- I830OutputPrivatePtr intel_output = output->driver_private;
-
- 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);
- }
- connected = i830_crt_detect_load (crtc, output);
- i830ReleaseLoadDetectPipe (output);
+ connected = i830_crt_detect_load (crtc, output);
+ i830ReleaseLoadDetectPipe (output, dpms_mode);
if (connected)
return XF86OutputStatusConnected;
else
diff --git a/src/i830_display.c b/src/i830_display.c
index ff25b29..16af496 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -605,6 +605,8 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
break;
}
+ intel_crtc->dpms_mode = mode;
+
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
@@ -1424,58 +1426,116 @@ i830DescribeOutputConfiguration(ScrnInfo
* \return crtc, or NULL if no pipes are available.
*/
+/* VESA 640x480x72Hz mode to set on the pipe */
+static DisplayModeRec load_detect_mode = {
+ NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
+ 31500,
+ 640, 664, 704, 832, 0,
+ 480, 489, 491, 520, 0,
+ V_NHSYNC | V_NVSYNC,
+ 0, 0,
+
+ 640, 640, 664, 704, 832, 832, 0,
+ 480, 489, 489, 491, 520, 520,
+ FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
+};
+
xf86CrtcPtr
-i830GetLoadDetectPipe(xf86OutputPtr output)
+i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode)
{
ScrnInfoPtr pScrn = output->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
+ I830CrtcPrivatePtr intel_crtc;
xf86CrtcPtr supported_crtc =NULL;
- xf86CrtcPtr detect_crtc = NULL;
+ xf86CrtcPtr crtc = NULL;
int i;
if (output->crtc)
- return output->crtc;
+ {
+ crtc = output->crtc;
+ /*
+ * Make sure the crtc and output are running
+ */
+ intel_crtc = crtc->driver_private;
+ *dpms_mode = intel_crtc->dpms_mode;
+ if (intel_crtc->dpms_mode != DPMSModeOn)
+ {
+ crtc->funcs->dpms (crtc, DPMSModeOn);
+ output->funcs->dpms (output, DPMSModeOn);
+ }
+ return crtc;
+ }
for (i = 0; i < xf86_config->num_crtc; i++)
{
- xf86CrtcPtr crtc;
+ xf86CrtcPtr possible_crtc;
if (!(output->possible_crtcs & (1 << i)))
continue;
- crtc = xf86_config->crtc[i];
- if (!crtc->enabled)
+ possible_crtc = xf86_config->crtc[i];
+ if (!possible_crtc->enabled)
{
- detect_crtc = crtc;
+ crtc = possible_crtc;
break;
}
if (!supported_crtc)
- supported_crtc = crtc;
+ supported_crtc = possible_crtc;
+ }
+ if (!crtc)
+ {
+ crtc = supported_crtc;
+ if (!crtc)
+ return NULL;
}
- if (!detect_crtc)
- detect_crtc = supported_crtc;
- if (!detect_crtc)
- return NULL;
- output->crtc = detect_crtc;
+ output->crtc = crtc;
intel_output->load_detect_temp = TRUE;
+
+ intel_crtc = crtc->driver_private;
+ *dpms_mode = intel_crtc->dpms_mode;
- return detect_crtc;
+ if (!crtc->enabled)
+ {
+ if (!mode)
+ mode = &load_detect_mode;
+ xf86CrtcSetMode (crtc, mode, RR_Rotate_0, 0, 0);
+ }
+ else
+ {
+ if (intel_crtc->dpms_mode != DPMSModeOn)
+ crtc->funcs->dpms (crtc, DPMSModeOn);
+
+ /* Add this output to the crtc */
+ output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
+ output->funcs->commit (output);
+ }
+
+ return crtc;
}
void
-i830ReleaseLoadDetectPipe(xf86OutputPtr output)
+i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode)
{
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
+ xf86CrtcPtr crtc = output->crtc;
if (intel_output->load_detect_temp)
{
- xf86CrtcPtr crtc = output->crtc;
output->crtc = NULL;
intel_output->load_detect_temp = FALSE;
crtc->enabled = xf86CrtcInUse (crtc);
xf86DisableUnusedFunctions(pScrn);
}
+ /*
+ * Switch crtc and output back off if necessary
+ */
+ if (crtc->enabled && dpms_mode != DPMSModeOn)
+ {
+ if (output->crtc == crtc)
+ output->funcs->dpms (output, dpms_mode);
+ crtc->funcs->dpms (crtc, dpms_mode);
+ }
}
/* Returns the clock of the currently programmed mode of the given pipe. */
@@ -1623,6 +1683,7 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pi
intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
intel_crtc->pipe = pipe;
+ intel_crtc->dpms_mode = DPMSModeOff;
/* Initialize the LUTs for when we turn on the CRTC. */
for (i = 0; i < 256; i++) {
diff --git a/src/i830_display.h b/src/i830_display.h
index 07dfe93..1eeb7f1 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -32,8 +32,8 @@ void i830PipeSetBase(xf86CrtcPtr crtc, i
void i830WaitForVblank(ScrnInfoPtr pScrn);
void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
-xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
-void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
+xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode);
+void i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode);
void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
void i830_crtc_load_lut(xf86CrtcPtr crtc);
DisplayModePtr i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc);
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 1c818ba..8337d86 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1353,24 +1353,15 @@ i830_tv_detect(xf86OutputPtr output)
DisplayModeRec mode;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ int dpms_mode;
- crtc = i830GetLoadDetectPipe (output);
+ mode = reported_modes[0];
+ xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+ crtc = i830GetLoadDetectPipe (output, &mode, &dpms_mode);
if (crtc)
{
- if (!crtc->enabled)
- {
- /* we only need the pixel clock set correctly here */
- mode = reported_modes[0];
- xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
- crtc->funcs->mode_set(crtc, &mode, &mode, 0, 0);
- }
- else if (intel_output->load_detect_temp)
- {
- output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
- output->funcs->commit (output);
- }
i830_tv_detect_type (crtc, output);
- i830ReleaseLoadDetectPipe (output);
+ i830ReleaseLoadDetectPipe (output, dpms_mode);
}
switch (dev_priv->type) {
diff-tree 6f18300aed1340348c6d395f326061b5315be643 (from 04130ac6b705aa49161fb6dae83ad0bdd76e89d9)
Author: Keith Packard <keithp at neko.keithp.com>
Date: Mon Jul 9 21:29:55 2007 -0700
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.
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 6d70f39..1900dfb 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -209,10 +209,8 @@ i830_crt_detect_load (xf86CrtcPtr cr
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 cr
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 cr
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 cr
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);
}
diff --git a/src/i830_display.c b/src/i830_display.c
index f3b5c50..ff25b29 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1169,13 +1169,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
((adjusted_mode->CrtcVTotal - 1) << 16));
- /*
- * Give us some border at the bottom for load detection
- */
- adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVSyncStart;
- if (adjusted_mode->CrtcVBlankEnd - adjusted_mode->CrtcVBlankStart < 3)
- adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVBlankEnd - 3;
-
OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
((adjusted_mode->CrtcVBlankEnd - 1) << 16));
OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
@@ -1437,25 +1430,36 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
ScrnInfoPtr pScrn = output->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
- xf86CrtcPtr crtc;
+ xf86CrtcPtr supported_crtc =NULL;
+ xf86CrtcPtr detect_crtc = NULL;
int i;
if (output->crtc)
return output->crtc;
for (i = 0; i < xf86_config->num_crtc; i++)
- if (output->possible_crtcs & (1 << i))
+ {
+ xf86CrtcPtr crtc;
+ if (!(output->possible_crtcs & (1 << i)))
+ continue;
+ crtc = xf86_config->crtc[i];
+ if (!crtc->enabled)
+ {
+ detect_crtc = crtc;
break;
-
- if (i == xf86_config->num_crtc)
+ }
+ if (!supported_crtc)
+ supported_crtc = crtc;
+ }
+ if (!detect_crtc)
+ detect_crtc = supported_crtc;
+ if (!detect_crtc)
return NULL;
- crtc = xf86_config->crtc[i];
-
- output->crtc = crtc;
+ output->crtc = detect_crtc;
intel_output->load_detect_temp = TRUE;
- return crtc;
+ return detect_crtc;
}
void
More information about the xorg-commit
mailing list