summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@dulcimer.keithp.com>2007-05-27 12:35:55 -0700
committerKeith Packard <keithp@dulcimer.keithp.com>2007-05-27 12:35:55 -0700
commit2a365eab0178c28782fba97bdd22365f30ce8963 (patch)
tree3f194e499b075e351e9a8558763f4eb6e230165d
parentff8c8cb869a3c780dbd826f7c94f06e4f3fda6af (diff)
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.
-rw-r--r--src/i830.h11
-rw-r--r--src/i830_display.c80
-rw-r--r--src/i830_video.c31
3 files changed, 98 insertions, 24 deletions
diff --git a/src/i830.h b/src/i830.h
index 35f81929..76cc6e87 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 023a1aab..adc7479e 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 d57519b9..4517975c 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;