summaryrefslogtreecommitdiff
path: root/src/ivch
diff options
context:
space:
mode:
authorKeith Packard <keithp@dulcimer.keithp.com>2007-05-17 14:11:49 -0700
committerKeith Packard <keithp@dulcimer.keithp.com>2007-05-17 14:11:49 -0700
commita441954630c6cdabbf463bfc3404160f97a04b4f (patch)
treecc38b10d2549776bb3065f5c1c7b63ac33e4e416 /src/ivch
parentc0daa0a982e7074af4b50653b4a45b0a6352b43d (diff)
Enable panel fitter on ivch DVO.
Using BIOS source code as a guide, set up the panel fitter on the ivch. This involves setting the pipe to the panel fixed mode, the DVO to the source size and assigning vertical and horizontal scaling factors in the ivch itself.
Diffstat (limited to 'src/ivch')
-rw-r--r--src/ivch/ivch.c55
-rw-r--r--src/ivch/ivch_reg.h14
2 files changed, 52 insertions, 17 deletions
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index a76e339f..e0755c05 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -157,8 +157,6 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
struct ivch_priv *priv;
CARD16 temp;
- xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ivch\n");
-
priv = xcalloc(1, sizeof(struct ivch_priv));
if (priv == NULL)
return NULL;
@@ -191,10 +189,6 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
goto out;
}
- ivch_read (priv, VR01, &temp); xf86DrvMsg (priv->d.pI2CBus->scrnIndex, X_INFO,
- "ivch VR01 0x%x\n", temp);
- ivch_read (priv, VR40, &temp); xf86DrvMsg (priv->d.pI2CBus->scrnIndex, X_INFO,
- "ivch VR40 0x%x\n", temp);
return priv;
out:
@@ -250,7 +244,9 @@ ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode)
if (panel_fixed_mode)
{
- if (!xf86ModesEqual (mode, panel_fixed_mode))
+ if (mode->HDisplay > panel_fixed_mode->HDisplay)
+ return MODE_PANEL;
+ if (mode->VDisplay > panel_fixed_mode->VDisplay)
return MODE_PANEL;
}
@@ -280,8 +276,6 @@ ivch_dpms(I2CDevPtr d, int mode)
else
vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
- vr01 &= ~VR01_PANEL_FIT_ENABLE;
-
ivch_write(priv, VR01, vr01);
/* Wait for the panel to make its state transition */
@@ -300,6 +294,27 @@ ivch_dpms(I2CDevPtr d, int mode)
static Bool
ivch_mode_fixup(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+ DisplayModePtr panel_fixed_mode = priv->panel_fixed_mode;
+
+ /* If we have timings from the BIOS for the panel, put them in
+ * to the adjusted mode. The CRTC will be set up for this mode,
+ * with the panel scaling set up to source from the H/VDisplay
+ * of the original mode.
+ */
+ if (panel_fixed_mode != NULL) {
+ adjusted_mode->HDisplay = panel_fixed_mode->HDisplay;
+ adjusted_mode->HSyncStart = panel_fixed_mode->HSyncStart;
+ adjusted_mode->HSyncEnd = panel_fixed_mode->HSyncEnd;
+ adjusted_mode->HTotal = panel_fixed_mode->HTotal;
+ adjusted_mode->VDisplay = panel_fixed_mode->VDisplay;
+ adjusted_mode->VSyncStart = panel_fixed_mode->VSyncStart;
+ adjusted_mode->VSyncEnd = panel_fixed_mode->VSyncEnd;
+ adjusted_mode->VTotal = panel_fixed_mode->VTotal;
+ adjusted_mode->Clock = panel_fixed_mode->Clock;
+ xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
+ }
+
return TRUE;
}
@@ -310,22 +325,32 @@ ivch_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
CARD16 vr40 = 0;
CARD16 vr01;
- ivch_read (priv, VR01, &vr01);
- /* Disable panel fitting for now, until we can test. */
- if (adjusted_mode->HDisplay != priv->width || adjusted_mode->VDisplay != priv->height)
+ vr01 = 0;
+ vr40 = (VR40_STALL_ENABLE |
+ VR40_VERTICAL_INTERP_ENABLE |
+ VR40_HORIZONTAL_INTERP_ENABLE);
+
+ if (mode->HDisplay != adjusted_mode->HDisplay ||
+ mode->VDisplay != adjusted_mode->VDisplay)
{
+ CARD16 x_ratio, y_ratio;
+
vr01 |= VR01_PANEL_FIT_ENABLE;
- vr40 |= VR40_AUTO_RATIO_ENABLE;
+ vr40 |= VR40_CLOCK_GATING_ENABLE;
+ x_ratio = (((mode->HDisplay - 1) << 16) / (adjusted_mode->HDisplay - 1)) >> 2;
+ y_ratio = (((mode->VDisplay - 1) << 16) / (adjusted_mode->VDisplay - 1)) >> 2;
+ ivch_write (priv, VR42, x_ratio);
+ ivch_write (priv, VR41, y_ratio);
}
else
{
vr01 &= ~VR01_PANEL_FIT_ENABLE;
- vr40 &= ~VR40_AUTO_RATIO_ENABLE;
+ vr40 &= ~VR40_CLOCK_GATING_ENABLE;
}
+ vr40 &= ~VR40_AUTO_RATIO_ENABLE;
ivch_write(priv, VR01, vr01);
ivch_write(priv, VR40, vr40);
- ivch_dpms(d, DPMSModeOn);
ivch_dump_regs(d);
}
diff --git a/src/ivch/ivch_reg.h b/src/ivch/ivch_reg.h
index fe5507a8..bcd8c56a 100644
--- a/src/ivch/ivch_reg.h
+++ b/src/ivch/ivch_reg.h
@@ -46,6 +46,9 @@
* @{
*/
#define VR01 0x01
+/**
+ * Enable the panel fitter
+ */
# define VR01_PANEL_FIT_ENABLE (1 << 3)
/**
* Enables the LCD display.
@@ -185,26 +188,33 @@
*/
#define VR40 0x40
# define VR40_STALL_ENABLE (1 << 13)
-# define VR40_VERTICAL_INTERP_ENABLE (1 << 11)
+# define VR40_VERTICAL_INTERP_ENABLE (1 << 12)
+# define VR40_ENHANCED_PANEL_FITTING (1 << 11)
# define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10)
# define VR40_AUTO_RATIO_ENABLE (1 << 9)
-# define VR40_PANEL_FIT_ENABLE (1 << 8)
+# define VR40_CLOCK_GATING_ENABLE (1 << 8)
/** @} */
/** @defgroup VR41 Panel Fitting Vertical Ratio
* @{
+ *
+ * (((image_height - 1) << 16) / ((panel_height - 1))) >> 2
*/
/** @} */
+#define VR41 0x41
/** @defgroup VR42 Panel Fitting Horizontal Ratio
* @{
+ * (((image_width - 1) << 16) / ((panel_width - 1))) >> 2
*/
/** @} */
+#define VR42 0x42
/** @defgroup VR43 Horizontal Image Size
* @{
*/
/** @} */
+#define VR43 0x43
/** @defgroup VR44 Panel Fitting Coefficient 0
* @{