xserver-xorg-video-intel: Changes to 'upstream-experimental'
README | 7
configure.ac | 41
man/Makefile.am | 13
man/intel.man | 51
src/bios_reader/bios_reader.c | 9
src/ch7017/Makefile.am | 4
src/ch7017/ch7017.c | 2
src/ch7xxx/Makefile.am | 3
src/ch7xxx/ch7xxx.c | 2
src/common.h | 1
src/exa_sf.g4a | 28
src/exa_sf_mask.g4a | 25
src/exa_sf_rotation.g4a | 26
src/exa_wm_maskca.g4a | 26
src/exa_wm_maskca_srcalpha.g4a | 26
src/exa_wm_masknoca.g4a | 26
src/exa_wm_nomask.g4a | 26
src/exa_wm_rotation.g4a | 26
src/i2c_vid.h | 136 +
src/i810_driver.c | 4
src/i810_reg.h | 120 -
src/i830.h | 52
src/i830_accel.c | 17
src/i830_bios.c | 59
src/i830_bios.h | 52
src/i830_crt.c | 98
src/i830_debug.c | 58
src/i830_display.c | 87
src/i830_dri.c | 29
src/i830_driver.c | 215 +
src/i830_dvo.c | 209 +
src/i830_exa.c | 38
src/i830_lvds.c | 193 +
src/i830_memory.c | 164 +
src/i830_reg.h | 2
src/i830_render.c | 129 -
src/i830_sdvo.c | 48
src/i830_sdvo_regs.h | 6
src/i830_tv.c | 2
src/i830_video.c | 4619 ++++++++++++++++++++---------------------
src/i830_video.h | 4
src/i830_xaa.c | 4
src/i915_render.c | 12
src/i965_render.c | 10
src/i965_video.c | 10
src/ivch/Makefile.am | 3
src/ivch/ivch.c | 283 ++
src/ivch/ivch_reg.h | 208 +
src/packed_yuv_sf.g4a | 28
src/packed_yuv_wm.g4a | 28
src/sil164/Makefile.am | 3
src/sil164/sil164.c | 2
52 files changed, 4432 insertions(+), 2842 deletions(-)
New commits:
commit 516fb73ffee0aea7cf892e6703d37f8ecf52b812
Author: Eric Anholt <eric@anholt.net>
Date: Tue May 29 10:22:25 2007 -0700
Remove README statement that 830M panels are unsupported.
diff --git a/README b/README
index f209baa..bcb0205 100644
--- a/README
+++ b/README
@@ -57,11 +57,6 @@ options.
Known Limitations
-- Bug #8534: i830 laptop panels not supported. The driver
- will fail to recognize them, and only function through VGA output. Two
- partial DVO chip drivers (ivch and ch7017) are included which contain some of
- the code necessary for i830 laptop panel support, but some I2C debugging will
- be necessary to get those drivers to attach.
- No support for "zaphod mode" dualhead. This is the mode in which two
Device sections are placed in the config file, and doesn't support DRI or
many other features. Instead, only "MergedFB-style" dualhead is supported.
commit 72462568da589054828b72ace83232a71636ee73
Author: Eric Anholt <eric@anholt.net>
Date: Tue May 29 10:21:12 2007 -0700
Expand manpage description of outputs supported.
diff --git a/man/intel.man b/man/intel.man
index daf9030..8991619 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -168,11 +168,28 @@ Enable printing of additional debugging information about modesetting to
the server log.
.PP
-The 830M and newer driver supports RandR 1.2, exposing the VGA, LVDS
-(laptop panel), TMDS (DVI on SDVO/DVO cards), and TV (on 915GM/945GM)
-outputs. Per-output configuration is done through the
-.B Monitor
-section of __xconfigfile__(__filemansuffix__).
+The 830M and newer driver supports the following outputs through RandR 1.2:
+.PP
+.TP
+.BI "VGA"
+Analog VGA output
+.TP
+.BI "LVDS"
+Laptop panel
+.TP
+.BI "TV"
+Integrated TV output
+.TP
+.BI "TMDS-1"
+First DVI SDVO output
+.TP
+.BI "TMDS-2"
+Second DVI SDVO output
+.PP
+SDVO and DVO TV outputs are not supported by the driver at this time.
+.PP
+See __xconfigfile__(__filemansuffix__) for information on associating Monitor
+sections with these outputs for configuration.
.SH "SEE ALSO"
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
commit 906b974bfeeed18d79c244ad3db4f5d30e13e4c8
Author: Eric Anholt <eric@anholt.net>
Date: Tue May 29 09:49:08 2007 -0700
Add a fixup to LVDS panel mode detection for 1280x768 panel from text mode.
Apparently some BIOSes will program a small mode with large blanking instead of
using the pannel fitter.
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 566c868..ecc91aa 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -496,6 +496,22 @@ i830_lvds_init(ScrnInfoPtr pScrn)
dev_priv->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
if (dev_priv->panel_fixed_mode != NULL)
dev_priv->panel_fixed_mode->type |= M_T_PREFERRED;
+
+ /* Fixup for a 1280x768 panel with the horizontal trimmed
+ * down to 1024 for text mode.
+ */
+ if (!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode) &&
+ dev_priv->panel_fixed_mode->HDisplay == 1024 &&
+ dev_priv->panel_fixed_mode->HSyncStart == 1200 &&
+ dev_priv->panel_fixed_mode->HSyncEnd == 1312 &&
+ dev_priv->panel_fixed_mode->HTotal == 1688 &&
+ dev_priv->panel_fixed_mode->VDisplay == 768)
+ {
+ dev_priv->panel_fixed_mode->HDisplay = 1280;
+ dev_priv->panel_fixed_mode->HSyncStart = 1328;
+ dev_priv->panel_fixed_mode->HSyncEnd = 1440;
+ dev_priv->panel_fixed_mode->HTotal = 1688;
+ }
}
}
commit 4b2781291844b61b397e257a0fdb43e964e5f603
Author: Keith Packard <keithp@neko.keithp.com>
Date: Sat May 26 10:09:11 2007 -0700
Mark IVCH as connected when detected
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index e0755c0..eac878e 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -219,7 +219,7 @@ ivch_setup (I2CDevPtr d, xf86OutputPtr output)
static xf86OutputStatus
ivch_detect(I2CDevPtr d)
{
- return XF86OutputStatusUnknown;
+ return XF86OutputStatusConnected;
}
static DisplayModePtr
commit 2a365eab0178c28782fba97bdd22365f30ce8963
Author: Keith Packard <keithp@dulcimer.keithp.com>
Date: Sun May 27 12:35:55 2007 -0700
On i830, Pipe B cannot be lit the first time unless Pipe A is running.
I don't understand it, but just like the video overlay, if Pipe A is not
running, Pipe B will not turn the first time it is activated. This
patch restructures the code used for the video overlay to share it
with the crtc commit function.
diff --git a/src/i830.h b/src/i830.h
index 35f8192..76cc6e8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -216,6 +216,8 @@ extern const char *i830_output_type_names[];
typedef struct _I830CrtcPrivateRec {
int pipe;
+ Bool enabled;
+
/* Lookup table values to be set when the CRTC is enabled */
CARD8 lut_r[256], lut_g[256], lut_b[256];
@@ -579,6 +581,15 @@ extern void I830InitVideo(ScreenPtr pScreen);
extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on);
#endif
+int
+i830_crtc_pipe (xf86CrtcPtr crtc);
+
+Bool
+i830_pipe_a_require_activate (ScrnInfoPtr scrn);
+
+void
+i830_pipe_a_require_deactivate (ScrnInfoPtr scrn);
+
#ifdef XF86DRI
extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags);
extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index 023a1aa..adc7479 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -429,6 +429,76 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
#endif
}
+/*
+ * Both crtc activation and video overlay enablement on pipe B
+ * will fail on i830 if pipe A is not running. This function
+ * makes sure pipe A is active for these cases
+ */
+
+int
+i830_crtc_pipe (xf86CrtcPtr crtc)
+{
+ if (crtc == NULL)
+ return 0;
+ return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
+}
+
+static xf86CrtcPtr
+i830_crtc_for_pipe (ScrnInfoPtr scrn, int pipe)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ if (i830_crtc_pipe (crtc) == pipe)
+ return crtc;
+ }
+ return NULL;
+}
+
+Bool
+i830_pipe_a_require_activate (ScrnInfoPtr scrn)
+{
+ xf86CrtcPtr crtc = i830_crtc_for_pipe (scrn, 0);
+ /* 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
+ };
+
+ if (!crtc)
+ return FALSE;
+ if (crtc->enabled)
+ return FALSE;
+ xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+ crtc->funcs->mode_set (crtc, &mode, &mode, 0, 0);
+ crtc->funcs->dpms (crtc, DPMSModeOn);
+ return TRUE;
+}
+
+void
+i830_pipe_a_require_deactivate (ScrnInfoPtr scrn)
+{
+ xf86CrtcPtr crtc = i830_crtc_for_pipe (scrn, 0);
+
+ if (!crtc)
+ return;
+ if (crtc->enabled)
+ return;
+ crtc->funcs->dpms (crtc, DPMSModeOff);
+ return;
+}
+
+
/**
* Sets the power management mode of the pipe and plane.
*
@@ -593,9 +663,19 @@ i830_crtc_prepare (xf86CrtcPtr crtc)
static void
i830_crtc_commit (xf86CrtcPtr crtc)
{
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ Bool deactivate = FALSE;
+
+ if (!intel_crtc->enabled && intel_crtc->pipe != 0)
+ deactivate = i830_pipe_a_require_activate (crtc->scrn);
+
+ intel_crtc->enabled = TRUE;
+
crtc->funcs->dpms (crtc, DPMSModeOn);
if (crtc->scrn->pScreen != NULL)
xf86_reload_cursors (crtc->scrn->pScreen);
+ if (deactivate)
+ i830_pipe_a_require_deactivate (crtc->scrn);
}
void
diff --git a/src/i830_video.c b/src/i830_video.c
index d57519b..4517975 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -382,6 +382,7 @@ i830_overlay_on(ScrnInfoPtr pScrn)
I830Ptr pI830 = I830PTR(pScrn);
I830OverlayRegPtr overlay = I830OVERLAYREG(pI830);
I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ Bool deactivate = FALSE;
xf86CrtcPtr crtc0 = NULL;
if (*pI830->overlayOn)
@@ -393,30 +394,12 @@ i830_overlay_on(ScrnInfoPtr pScrn)
* screen. Light up pipe A in this case to provide a clock
* for the overlay hardware
*/
- if (!pPriv->started_video)
+ if (pPriv->current_crtc &&
+ i830_crtc_pipe (pPriv->current_crtc) != 0 &&
+ !pPriv->started_video)
{
pPriv->started_video = TRUE;
- crtc0 = I830CrtcForPipe (pScrn, 0);
- if (!crtc0->enabled)
- {
- /* 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
- };
- xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
- crtc0->funcs->mode_set (crtc0, &mode, &mode, 0, 0);
- crtc0->funcs->dpms (crtc0, DPMSModeOn);
- }
- else
- crtc0 = NULL;
+ deactivate = i830_pipe_a_require_activate (pScrn);
}
overlay->OCMD &= ~OVERLAY_ENABLE;
@@ -435,8 +418,8 @@ i830_overlay_on(ScrnInfoPtr pScrn)
* If we turned pipe A on up above, turn it
* back off
*/
- if (crtc0)
- crtc0->funcs->dpms (crtc0, DPMSModeOff);
+ if (deactivate)
+ i830_pipe_a_require_deactivate (pScrn);
OVERLAY_DEBUG("overlay_on\n");
*pI830->overlayOn = TRUE;
commit ff8c8cb869a3c780dbd826f7c94f06e4f3fda6af
Author: Keith Packard <keithp@dulcimer.keithp.com>
Date: Fri May 25 20:29:59 2007 -0700
Compute and clip to crtc before call to xf86XVClipVideoHelper.
By clipping to the crtc ahead of time, xf86XVClipVideoHelper will
correctly clip to the bounds of the crtc, eliminating the need for any
custom crtc clipping.
Also, replace the broken xf86XVFillKeyHelper with a private version that
doesn't end up stuck with the wrong clip list when the root window changes
size.
diff --git a/src/i830_video.c b/src/i830_video.c
index c2d3b4b..d57519b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1636,38 +1636,35 @@ UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff)
}
}
-/*
- * Return the number of pixels from 'box' covered by 'crtc'.
- * That is, the area of the intersection of 'box' and 'crtc'
- */
-static int
-I830CrtcBoxCoverage (xf86CrtcPtr crtc, BoxPtr box)
+static void
+i830_box_intersect (BoxPtr dest, BoxPtr a, BoxPtr b)
{
- BoxRec dest;
- BoxRec pipe;
+ dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+ dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+ dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+ dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+ if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
+ dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+}
+static void
+i830_crtc_box (xf86CrtcPtr crtc, BoxPtr crtc_box)
+{
if (crtc->enabled)
{
- pipe.x1 = crtc->x;
- pipe.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
- pipe.y1 = crtc->y;
- pipe.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+ crtc_box->x1 = crtc->x;
+ crtc_box->x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+ crtc_box->y1 = crtc->y;
+ crtc_box->y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
}
else
- {
- pipe.x1 = pipe.x2 = 0;
- pipe.y1 = pipe.y2 = 0;
- }
- dest.x1 = pipe.x1 > box->x1 ? pipe.x1 : box->x1;
- dest.x2 = pipe.x2 < box->x2 ? pipe.x2 : box->x2;
- dest.y1 = pipe.y1 > box->y1 ? pipe.y1 : box->y1;
- dest.y2 = pipe.y2 < box->y2 ? pipe.y2 : box->y2;
- if (dest.x1 >= dest.x2 || dest.y1 >= dest.y2)
- {
- dest.x1 = dest.x2 = 0;
- dest.y1 = dest.y2 = 0;
- }
- return (int) (dest.x2 - dest.x1) * (int) (dest.y2 - dest.y1);
+ crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
+static int
+i830_box_area (BoxPtr box)
+{
+ return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
}
/*
@@ -1677,21 +1674,28 @@ I830CrtcBoxCoverage (xf86CrtcPtr crtc, BoxPtr box)
*/
static xf86CrtcPtr
-I830CoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr desired)
+i830_covering_crtc (ScrnInfoPtr pScrn,
+ BoxPtr box,
+ xf86CrtcPtr desired,
+ BoxPtr crtc_box_ret)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
xf86CrtcPtr crtc, best_crtc;
int coverage, best_coverage;
int c;
+ BoxRec crtc_box, cover_box;
best_crtc = NULL;
best_coverage = 0;
for (c = 0; c < xf86_config->num_crtc; c++)
{
crtc = xf86_config->crtc[c];
- coverage = I830CrtcBoxCoverage (crtc, pBox);
+ i830_crtc_box (crtc, &crtc_box);
+ i830_box_intersect (&cover_box, &crtc_box, box);
+ coverage = i830_box_area (&cover_box);
if (coverage > best_coverage)
{
+ *crtc_box_ret = crtc_box;
if (crtc == desired)
return crtc;
best_crtc = crtc;
@@ -1713,19 +1717,19 @@ i830_swidth (I830Ptr pI830, unsigned int offset,
}
static void
-I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
- int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
- short src_w, short src_h, short drw_w, short drw_h)
+i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
+ int id, short width, short height,
+ int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
+ short src_w, short src_h, short drw_w, short drw_h)
{
- I830Ptr pI830 = I830PTR(pScrn);
- I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
I830OverlayRegPtr overlay = I830OVERLAYREG(pI830);
- unsigned int swidth, swidthy, swidthuv;
- unsigned int mask, shift, offsety, offsetu;
- xf86CrtcPtr crtc;
- int tmp;
- CARD32 OCMD;
- Bool scaleChanged = FALSE;
+ unsigned int swidth, swidthy, swidthuv;
+ unsigned int mask, shift, offsety, offsetu;
+ int tmp;
+ CARD32 OCMD;
+ Bool scaleChanged = FALSE;
OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
dstPitch);
@@ -1736,23 +1740,23 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
#if VIDEO_DEBUG
CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
#endif
-
- crtc = I830CoveringCrtc (pScrn, dstBox, pPriv->desired_crtc);
- if (crtc != pPriv->current_crtc)
- {
- pPriv->current_crtc = crtc;
- I830ResetVideo (pScrn);
- }
-
+
/*
* If the video isn't visible on any CRTC, turn it off
*/
if (!crtc)
{
+ pPriv->current_crtc = NULL;
i830_overlay_off (pScrn);
return;
}
+ if (crtc != pPriv->current_crtc)
+ {
+ pPriv->current_crtc = crtc;
+ I830ResetVideo (pScrn);
+ }
+
switch (crtc->rotation & 0xf) {
case RR_Rotate_0:
dstBox->x1 -= crtc->x;
@@ -1792,44 +1796,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
break;
}
- /* Fix up the dstBox if outside the visible screen */
- {
- int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
- int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0;
- int offset, offset2;
-
- /* align */
- offset_x = (offset_x + 3) & ~3;
- offset_y = (offset_y + 3) & ~3;
-
- if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
- height -= offset_x;
- width -= offset_y;
- } else {
- height -= offset_y;
- width -= offset_x;
- }
-
- if (id == FOURCC_I420 || id == FOURCC_YV12) {
- offset = ((offset_x/2) + (dstPitch * offset_y)) * 2;
- offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y));
- } else {
- offset = ((offset_x*2) + (dstPitch * offset_y));
- offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y));
- }
-
- /* buffer locations */
- pPriv->YBuf0offset += offset;
- pPriv->UBuf0offset += offset2;
- pPriv->VBuf0offset += offset2;
-
- if(pPriv->doubleBuffer) {
- pPriv->YBuf1offset += offset;
- pPriv->UBuf1offset += offset2;
- pPriv->VBuf1offset += offset2;
- }
- }
-
if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
tmp = width;
width = height;
@@ -1851,32 +1817,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
}
- {
- /* Keep the engine happy and clip to the real vertical size just
- * in case an LFP is in use and it's not at it's native resolution.
- */
- int vactive = I830CrtcPipe (pPriv->current_crtc) ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
- int hactive = pPriv->current_crtc->mode.HDisplay;
-
- vactive += 1;
-
- if (dstBox->y1 < 0) dstBox->y1 = 0;
- if (dstBox->y2 < 0) dstBox->y2 = 0;
- if (dstBox->x1 < 0) dstBox->x1 = 0;
- if (dstBox->x2 < 0) dstBox->x2 = 0;
- if (dstBox->y1 > vactive) dstBox->y1 = vactive;
- if (dstBox->y2 > vactive) dstBox->y2 = vactive;
- if (dstBox->x1 > hactive) dstBox->x1 = hactive;
- if (dstBox->x2 > hactive) dstBox->x2 = hactive;
-
- /* nothing do to */
- if (dstBox->x2 - dstBox->x1 <= 2 || dstBox->y2 - dstBox->y1 < N_VERT_Y_TAPS)
- {
- OVERLAY_DEBUG("NOTHING TO DO\n");
- return;
- }
- }
-
if (IS_I9XX(pI830)) {
shift = 6;
mask = 0x3f;
@@ -2220,6 +2160,84 @@ I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear)
linear->offset = 0;
}
+static Bool
+i830_clip_video_helper (ScrnInfoPtr pScrn,
+ xf86CrtcPtr *crtc_ret,
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height)
+{
+ Bool ret;
+ RegionRec crtc_region_local;
+ RegionPtr crtc_region = reg;
+
+ /*
+ * For overlay video, compute the relevant CRTC and
+ * clip video to that
+ */
+ if (crtc_ret)
+ {
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ BoxRec crtc_box;
+ xf86CrtcPtr crtc = i830_covering_crtc (pScrn, dst,
+ pPriv->desired_crtc,
+ &crtc_box);
+
+ if (crtc)
+ {
+ REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
+ crtc_region = &crtc_region_local;
+ REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
+ }
+ *crtc_ret = crtc;
+ }
+ ret = xf86XVClipVideoHelper (dst, xa, xb, ya, yb,
+ crtc_region, width, height);
+ if (crtc_region != reg)
+ REGION_UNINIT (pScreen, &crtc_region_local);
+ return ret;
+}
+
+static void
+i830_fill_colorkey (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes)
+{
+ DrawablePtr root = &WindowTable[pScreen->myNum]->drawable;
+ XID pval[2];
+ BoxPtr pbox = REGION_RECTS(clipboxes);
+ int i, nbox = REGION_NUM_RECTS(clipboxes);
+ xRectangle *rects;
+ GCPtr gc;
+
+ if(!xf86Screens[pScreen->myNum]->vtSema) return;
+
+ gc = GetScratchGC(root->depth, pScreen);
+ pval[0] = key;
+ pval[1] = IncludeInferiors;
+ (void) ChangeGC(gc, GCForeground|GCSubwindowMode, pval);
+ ValidateGC(root, gc);
+
+ rects = xalloc (nbox * sizeof(xRectangle));
+
+ for(i = 0; i < nbox; i++, pbox++)
+ {
+ rects[i].x = pbox->x1;
+ rects[i].y = pbox->y1;
+ rects[i].width = pbox->x2 - pbox->x1;
+ rects[i].height = pbox->y2 - pbox->y1;
+ }
+
+ (*gc->ops->PolyFillRect)(root, gc, nbox, rects);
+
+ xfree (rects);
+ FreeScratchGC (gc);
+}
+
/*
* The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
* The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
@@ -2255,6 +2273,7 @@ I830PutImage(ScrnInfoPtr pScrn,
BoxRec dstBox;
int pitchAlignMask;
int extraLinear;
+ xf86CrtcPtr crtc;
if (pPriv->textured)
overlay = NULL;
@@ -2301,8 +2320,10 @@ I830PutImage(ScrnInfoPtr pScrn,
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
- if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
- width, height))
+ if (!i830_clip_video_helper(pScrn,
+ pPriv->textured ? NULL : &crtc,
+ &dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+ width, height))
return Success;
destId = id;
@@ -2455,14 +2476,15 @@ I830PutImage(ScrnInfoPtr pScrn,
}
if (!pPriv->textured) {
+ i830_display_video(pScrn, crtc, destId, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h,
+ drw_w, drw_h);
+
/* update cliplist */
if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
- xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
+ i830_fill_colorkey (pScreen, pPriv->colorKey, clipBoxes);
}
-
- I830DisplayVideo(pScrn, destId, width, height, dstPitch,
- x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
} else if (IS_I965G(pI830)) {
I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
dstPitch, x1, y1, x2, y2,
@@ -2754,8 +2776,8 @@ I830DisplaySurface(XF86SurfacePtr surface,
I830Ptr pI830 = I830PTR(pScrn);
I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
INT32 x1, y1, x2, y2;
- INT32 loops = 0;
BoxRec dstBox;
+ xf86CrtcPtr crtc;
OVERLAY_DEBUG("I830DisplaySurface\n");
@@ -2785,43 +2807,24 @@ I830DisplaySurface(XF86SurfacePtr surface,
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
- if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
- surface->width, surface->height))
+ if (!i830_clip_video_helper (pScrn, &crtc, &dstBox,
+ &x1, &x2, &y1, &y2, clipBoxes,
+ surface->width, surface->height))
return Success;
/* fixup pointers */
pI830Priv->YBuf0offset = surface->offsets[0];
pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
- /* Make sure this buffer isn't in use */
- loops = 0;
- if (*pI830->overlayOn && pI830Priv->doubleBuffer)
- {
- while (loops < 1000000) {
-#if USE_USLEEP_FOR_VIDEO
- usleep(10);
-#endif
- if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) {
- break;
- }
- loops++;
- }
- if (loops >= 1000000) {
- ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf);
-#if 0
- pI830Priv->currentBuf = !pI830Priv->currentBuf;
-#endif
- }
-
- /* buffer swap */
- pI830Priv->currentBuf = !pI830Priv->currentBuf;
- }
+ /* Pick the idle buffer */
+ if (!pI830Priv->textured && *pI830->overlayOn && pI830Priv->doubleBuffer)
+ pI830Priv->currentBuf = !((INREG(DOVSTA) & OC_BUF) >> 20);
- I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+ i830_display_video(pScrn, crtc, surface->id, surface->width, surface->height,
surface->pitches[0], x1, y1, x2, y2, &dstBox,
src_w, src_h, drw_w, drw_h);
- xf86XVFillKeyHelper(pScreen, pI830Priv->colorKey, clipBoxes);
+ i830_fill_colorkey (pScreen, pI830Priv->colorKey, clipBoxes);
pPriv->isOn = TRUE;
/* we've prempted the XvImage stream so set its free timer */
commit 33f635d79fe891079558fd909d564f3cf424c482
Author: Keith Packard <keithp@dulcimer.keithp.com>
Date: Fri May 25 17:32:06 2007 -0700
Ensure Pipe A is active when enabling overlay the first time.
The overlay on the i830 appears to be clocked by Pipe A when being enabled.
If pipe A is not running, it will freeze the overlay and blank the screen.
Setting a random mode on the Pipe and turning it on fixes this problem
nicely.
diff --git a/src/i830_video.c b/src/i830_video.c
index e2d132e..c2d3b4b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -321,6 +321,9 @@ typedef struct {
CARD16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
} I830OverlayRegRec, *I830OverlayRegPtr;
+#define I830OVERLAYREG(pI830) ((I830OverlayRegPtr)\
+ ((pI830)->FbBase + \
+ (pI830)->overlay_regs->offset))
#if VIDEO_DEBUG
static void
CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size)
@@ -342,6 +345,29 @@ CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size)
}
#endif
+static int
+I830CrtcPipe (xf86CrtcPtr crtc)
+{
+ if (crtc == NULL)
+ return 0;
+ return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
+}
+
+static xf86CrtcPtr
+I830CrtcForPipe (ScrnInfoPtr pScrn, int pipe)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ if (I830CrtcPipe (crtc) == pipe)
+ return crtc;
+ }
+ return NULL;
+}
+
/*
* This is more or less the correct way to initalise, update, and shut down
* the overlay.
@@ -353,40 +379,91 @@ CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size)
static void
i830_overlay_on(ScrnInfoPtr pScrn)
{
- I830Ptr pI830 = I830PTR(pScrn);
- I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase +
- pI830->overlay_regs->offset);
-
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OverlayRegPtr overlay = I830OVERLAYREG(pI830);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ xf86CrtcPtr crtc0 = NULL;
+
if (*pI830->overlayOn)
return;
+ /*
+ * On I830, if pipe A is off the first time the overlay
+ * is enabled, it will fail to turn and blank the entire
+ * screen. Light up pipe A in this case to provide a clock
+ * for the overlay hardware
+ */
+ if (!pPriv->started_video)
+ {
+ pPriv->started_video = TRUE;
+ crtc0 = I830CrtcForPipe (pScrn, 0);
+ if (!crtc0->enabled)
+ {
+ /* 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
+ };
+ xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+ crtc0->funcs->mode_set (crtc0, &mode, &mode, 0, 0);
+ crtc0->funcs->dpms (crtc0, DPMSModeOn);
+ }
+ else
+ crtc0 = NULL;
+ }
+
overlay->OCMD &= ~OVERLAY_ENABLE;
- BEGIN_LP_RING(4);
+ BEGIN_LP_RING(6);
OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
OUT_RING(MI_NOOP);
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
+ /* Wait for the overlay to light up before attempting to use it */
+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+ OUT_RING(MI_NOOP);
ADVANCE_LP_RING();
+ i830WaitSync(pScrn);
+
+ /*
+ * If we turned pipe A on up above, turn it
+ * back off
+ */
+ if (crtc0)
+ crtc0->funcs->dpms (crtc0, DPMSModeOff);
+
OVERLAY_DEBUG("overlay_on\n");
*pI830->overlayOn = TRUE;
+
+ overlay->OCMD |= OVERLAY_ENABLE;
}
static void
-i830_overlay_continue(ScrnInfoPtr pScrn)
+i830_overlay_continue(ScrnInfoPtr pScrn, Bool update_filter)
{
- I830Ptr pI830 = I830PTR(pScrn);
- I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase +
- pI830->overlay_regs->offset);
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 flip_addr;
+ I830OverlayRegPtr overlay = I830OVERLAYREG(pI830);
if (!*pI830->overlayOn)
return;
- overlay->OCMD |= OVERLAY_ENABLE;
+ flip_addr = pI830->overlay_regs->bus_addr;
+ if (update_filter)
+ flip_addr |= OFC_UPDATE;
+ OVERLAY_DEBUG ("overlay_continue cmd 0x%08lx -> 0x%08lx sta 0x%08lx\n",
+ overlay->OCMD, INREG(OCMD_REGISTER), INREG(DOVSTA));
BEGIN_LP_RING(4);
OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
OUT_RING(MI_NOOP);
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
- OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
+ OUT_RING(flip_addr);
ADVANCE_LP_RING();
OVERLAY_DEBUG("overlay_continue\n");
}
@@ -395,22 +472,43 @@ static void
i830_overlay_off(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
- I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase +
- pI830->overlay_regs->offset);
+ I830OverlayRegPtr overlay = I830OVERLAYREG(pI830);
if (!*pI830->overlayOn)
return;
- overlay->OCMD &= ~OVERLAY_ENABLE;
- BEGIN_LP_RING(6);
- OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
- OUT_RING(MI_NOOP);
- OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
- OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
- OUT_RING(MI_NOOP);
- ADVANCE_LP_RING();
- i830WaitSync(pScrn);
Reply to: