summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyu.z.wang@intel.com>2009-02-19 20:23:02 +0800
committerZhenyu Wang <zhenyu.z.wang@intel.com>2009-03-03 20:43:39 +0800
commitab1ef05cc0fd5ba9768c26cc51bc2c7b52baa45f (patch)
tree2b7842329847bf4cd587b561ee26074faaba4d23
parenta67a911a93ff3c0b3d2e6f6fb20c0787b9d4d41d (diff)
TV: update output and crtc modes when TV format change (try 3)
This is to fix bug #16566, change TV format will cause BadMatch error when crtc config apply. Everytime when we change TV format, we may generate a new list of modelines as TV clock changed. After randr get info request, new modelines will be probed and randr output's modes will be renewed too. But crtc's mode failed to be updated, as it never can find a matching mode now within new modes list. So get info will return an invalid crtc's mode, later set crtc config will pass that info, and xserver catches a bad match. This patch trys to refresh output modes and setup crtc's mode with new modelines in TV format change. So get info would be sure to turn valid crtc mode that reference in current new modelines.
-rw-r--r--src/i830_tv.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 267da3b2..210070cb 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1605,9 +1605,14 @@ i830_tv_set_property(xf86OutputPtr output, Atom property,
{
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ I830Ptr pI830 = I830PTR(output->scrn);
Atom atom;
const char *name;
char *val;
+ RRCrtcPtr randr_crtc;
+ xRRModeInfo modeinfo;
+ RRModePtr mode;
+ DisplayModePtr crtc_mode;
if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
return FALSE;
@@ -1626,6 +1631,51 @@ i830_tv_set_property(xf86OutputPtr output, Atom property,
}
xfree (dev_priv->tv_format);
dev_priv->tv_format = val;
+
+ if (pI830->starting)
+ return TRUE;
+
+ /* TV format change will generate new modelines, try
+ to probe them and update outputs. */
+ xf86ProbeOutputModes(output->scrn, 0, 0);
+ /* Mirror output modes to scrn mode list */
+ xf86SetScrnInfoModes (output->scrn);
+
+ for (crtc_mode = output->probed_modes; crtc_mode;
+ crtc_mode = crtc_mode->next)
+ {
+ if (output->crtc->mode.HDisplay == crtc_mode->HDisplay &&
+ output->crtc->mode.VDisplay == crtc_mode->VDisplay)
+ break;
+ }
+ if (!crtc_mode)
+ crtc_mode = output->probed_modes;
+
+ xf86CrtcSetMode(output->crtc, crtc_mode, output->crtc->rotation,
+ output->crtc->x, output->crtc->y);
+
+ xf86RandR12TellChanged(output->scrn->pScreen);
+
+ modeinfo.width = crtc_mode->HDisplay;
+ modeinfo.height = crtc_mode->VDisplay;
+ modeinfo.dotClock = crtc_mode->Clock * 1000;
+ modeinfo.hSyncStart = crtc_mode->HSyncStart;
+ modeinfo.hSyncEnd = crtc_mode->HSyncEnd;
+ modeinfo.hTotal = crtc_mode->HTotal;
+ modeinfo.hSkew = crtc_mode->HSkew;
+ modeinfo.vSyncStart = crtc_mode->VSyncStart;
+ modeinfo.vSyncEnd = crtc_mode->VSyncEnd;
+ modeinfo.vTotal = crtc_mode->VTotal;
+ modeinfo.nameLength = strlen(crtc_mode->name);
+ modeinfo.modeFlags = crtc_mode->Flags;
+
+ mode = RRModeGet(&modeinfo, crtc_mode->name);
+ randr_crtc = output->crtc->randr_crtc;
+ if (mode != randr_crtc->mode) {
+ if (randr_crtc->mode)
+ RRModeDestroy(randr_crtc->mode);
+ randr_crtc->mode = mode;
+ }
return TRUE;
}
for (i = 0; i < 4; i++)