summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/i830.h14
-rw-r--r--src/i830_crt.c8
-rw-r--r--src/i830_dvo.c18
-rw-r--r--src/i830_lvds.c8
-rw-r--r--src/i830_sdvo.c22
5 files changed, 62 insertions, 8 deletions
diff --git a/src/i830.h b/src/i830.h
index c41cb569..90fdcb85 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -211,6 +211,9 @@ typedef struct _I830SDVODriver {
CARD32 output_device; /* SDVOB or SDVOC */
i830_sdvo_caps caps;
+
+ CARD16 pixel_clock_min, pixel_clock_max;
+
int save_sdvo_mult;
Bool save_sdvo_active_1, save_sdvo_active_2;
i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
@@ -245,6 +248,17 @@ struct _I830OutputRec {
void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output);
/**
+ * Callback for testing a video mode for a given output.
+ *
+ * This function should only check for cases where a mode can't be supported
+ * on the pipe specifically, and not represent generic CRTC limitations.
+ *
+ * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
+ */
+ int (*mode_valid)(ScrnInfoPtr pScrn, I830OutputPtr output,
+ DisplayModePtr pMode);
+
+ /**
* Callback for setting up a video mode before any pipe/dpll changes.
*
* \param pMode the mode that will be set, or NULL if the mode to be set is
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 1cf1687e..7721a0c2 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -76,6 +76,13 @@ i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
OUTREG(ADPA, pI830->saveADPA);
}
+static int
+i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+ DisplayModePtr pMode)
+{
+ return MODE_OK;
+}
+
static void
i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
@@ -114,6 +121,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
pI830->output[pI830->num_outputs].dpms = i830_crt_dpms;
pI830->output[pI830->num_outputs].save = i830_crt_save;
pI830->output[pI830->num_outputs].restore = i830_crt_restore;
+ pI830->output[pI830->num_outputs].mode_valid = i830_crt_mode_valid;
pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode;
pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode;
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index ea74337a..01858f2c 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -92,15 +92,22 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
}
+static int
+i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+ DisplayModePtr pMode)
+{
+ if (output->i2c_drv->vid_rec->ModeValid(output->i2c_drv->dev_priv, pMode))
+ return MODE_OK;
+ else
+ return MODE_BAD;
+}
+
static void
i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
{
I830Ptr pI830 = I830PTR(pScrn);
- if (output->i2c_drv == NULL)
- return;
-
output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode);
OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
@@ -179,8 +186,9 @@ i830_dvo_init(ScrnInfoPtr pScrn)
pI830->output[i].dpms = i830_dvo_dpms;
pI830->output[i].save = i830_dvo_save;
pI830->output[i].restore = i830_dvo_restore;
- pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode ;
- pI830->output[i].post_set_mode = i830_dvo_post_set_mode ;
+ pI830->output[i].mode_valid = i830_dvo_mode_valid;
+ pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode;
+ pI830->output[i].post_set_mode = i830_dvo_post_set_mode;
/* Set up the I2C and DDC buses */
ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 186d33b5..399324f0 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -123,6 +123,13 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
i830SetLVDSPanelPower(pScrn, FALSE);
}
+static int
+i830_lvds_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+ DisplayModePtr pMode)
+{
+ return MODE_OK;
+}
+
static void
i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
@@ -178,6 +185,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms;
pI830->output[pI830->num_outputs].save = i830_lvds_save;
pI830->output[pI830->num_outputs].restore = i830_lvds_restore;
+ pI830->output[pI830->num_outputs].mode_valid = i830_lvds_mode_valid;
pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode;
pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 9a1e1550..76080dfa 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -545,7 +545,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
CARD8 c16a[8];
CARD8 c17a[8];
CARD16 out_timings[6];
- CARD16 clock_min, clock_max;
Bool out1, out2;
I830SDVOPtr s = output->sdvo_drv;
@@ -588,8 +587,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
I830SDVOSetTargetInput(s, FALSE, FALSE);
- I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max);
- ErrorF("clock min/max: %d %d\n", clock_min, clock_max);
I830SDVOGetActiveOutputs(s, &out1, &out2);
@@ -775,6 +772,21 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
sdvo->save_sdvo_active_2);
}
+static int
+i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+ DisplayModePtr pMode)
+{
+ I830SDVOPtr sdvo = output->sdvo_drv;
+
+ if (sdvo->pixel_clock_min > pMode->Clock)
+ return MODE_CLOCK_HIGH;
+
+ if (sdvo->pixel_clock_max < pMode->Clock)
+ return MODE_CLOCK_LOW;
+
+ return MODE_OK;
+}
+
static void
I830SDVOGetCapabilities(I830SDVOPtr s, i830_sdvo_caps *caps)
{
@@ -954,6 +966,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms;
pI830->output[pI830->num_outputs].save = i830_sdvo_save;
pI830->output[pI830->num_outputs].restore = i830_sdvo_restore;
+ pI830->output[pI830->num_outputs].mode_valid = i830_sdvo_mode_valid;
pI830->output[pI830->num_outputs].pre_set_mode = i830_sdvo_pre_set_mode;
pI830->output[pI830->num_outputs].post_set_mode = i830_sdvo_post_set_mode;
@@ -1042,6 +1055,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
I830SDVOGetCapabilities(sdvo, &sdvo->caps);
+ I830SDVOGetInputPixelClockRange(sdvo, &sdvo->pixel_clock_min,
+ &sdvo->pixel_clock_max);
+
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"SDVO device VID/DID: %02X:%02X.%02X, %02X,"
"output 1: %c, output 2: %c\n",