summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ch7017/ch7017.c2
-rw-r--r--src/ch7xxx/ch7xxx.c2
-rw-r--r--src/i2c_vid.h136
-rw-r--r--src/i830.h11
-rw-r--r--src/i830_dvo.c121
-rw-r--r--src/i830_lvds.c174
-rw-r--r--src/ivch/ivch.c171
-rw-r--r--src/ivch/ivch_reg.h194
-rw-r--r--src/sil164/sil164.c2
9 files changed, 646 insertions, 167 deletions
diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
index 7070c7d3..8e3a6ef4 100644
--- a/src/ch7017/ch7017.c
+++ b/src/ch7017/ch7017.c
@@ -144,7 +144,7 @@ ch7017_mode_valid(I2CDevPtr d, DisplayModePtr mode)
}
static void
-ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode)
+ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
struct ch7017_priv *priv = d->DriverPrivate.ptr;
CARD8 lvds_pll_feedback_div, lvds_pll_vco_control;
diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 0a96555d..09a96271 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -206,7 +206,7 @@ ch7xxx_mode_valid(I2CDevPtr d, DisplayModePtr mode)
}
static void
-ch7xxx_mode_set(I2CDevPtr d, DisplayModePtr mode)
+ch7xxx_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
CARD8 tvco, tpcp, tpd, tlpf, idf;
diff --git a/src/i2c_vid.h b/src/i2c_vid.h
index 3be394d7..1a21fcad 100644
--- a/src/i2c_vid.h
+++ b/src/i2c_vid.h
@@ -1,16 +1,142 @@
-/* this needs to go in the server */
+/*
+ * Copyright © 2006 Eric Anholt
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
#ifndef I2C_VID_H
#define I2C_VID_H
+#include <randrstr.h>
typedef struct _I830I2CVidOutputRec {
+ /**
+ * Initialize the device at startup time.
+ * Returns NULL if the device does not exist.
+ */
void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
- xf86OutputStatus (*detect)(I2CDevPtr d);
- ModeStatus (*mode_valid)(I2CDevPtr d, DisplayModePtr mode);
- void (*mode_set)(I2CDevPtr d, DisplayModePtr mode);
+
+ /**
+ * Setup the device for use, after the relevant output has been created
+ */
+ Bool
+ (*setup) (I2CDevPtr d, xf86OutputPtr output);
+
+ /**
+ * Called to allow the output a chance to create properties after the
+ * RandR objects have been created.
+ */
+ void
+ (*create_resources)(I2CDevPtr d);
+
+ /**
+ * Turns the output on/off, or sets intermediate power levels if available.
+ *
+ * Unsupported intermediate modes drop to the lower power setting. If the
+ * mode is DPMSModeOff, the output must be disabled, as the DPLL may be
+ * disabled afterwards.
+ */
void (*dpms)(I2CDevPtr d, int mode);
- void (*dump_regs)(I2CDevPtr d);
+
+ /**
+ * Saves the output's state for restoration on VT switch.
+ */
void (*save)(I2CDevPtr d);
+
+ /**
+ * Restore's the output's state at VT switch.
+ */
void (*restore)(I2CDevPtr d);
+
+ /**
+ * 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 output specifically, and not represent generic CRTC limitations.
+ *
+ * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
+ */
+ int (*mode_valid)(I2CDevPtr d, DisplayModePtr mode);
+
+ /**
+ * Callback to adjust the mode to be set in the CRTC.
+ *
+ * This allows an output to adjust the clock or even the entire set of
+ * timings, which is used for panels with fixed timings or for
+ * buses with clock limitations.
+ */
+ Bool (*mode_fixup)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+
+ /**
+ * Callback for preparing mode changes on an output
+ */
+ void (*prepare)(I2CDevPtr d);
+
+ /**
+ * Callback for committing mode changes on an output
+ */
+ void (*commit)(I2CDevPtr d);
+
+ /**
+ * Callback for setting up a video mode after fixups have been made.
+ *
+ * This is only called while the output is disabled. The dpms callback
+ * must be all that's necessary for the output, to turn the output on
+ * after this function is called.
+ */
+ void (*mode_set)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+
+ /**
+ * Probe for a connected output, and return detect_status.
+ */
+ xf86OutputStatus (*detect)(I2CDevPtr d);
+
+ /**
+ * Query the device for the modes it provides.
+ *
+ * This function may also update MonInfo, mm_width, and mm_height.
+ *
+ * \return singly-linked list of modes or NULL if no modes found.
+ */
+ DisplayModePtr
+ (*get_modes)(I2CDevPtr d);
+
+#ifdef RANDR_12_INTERFACE
+ /**
+ * Callback when an output's property has changed.
+ */
+ Bool
+ (*set_property)(I2CDevPtr d, Atom property, RRPropertyValuePtr value);
+#endif
+
+ /**
+ * Clean up driver-specific bits of the output
+ */
+ void (*destroy) (I2CDevPtr d);
+
+ /**
+ * Debugging hook to dump device registers to log file
+ */
+ void (*dump_regs)(I2CDevPtr d);
} I830I2CVidOutputRec, *I830I2CVidOutputPtr;
+/* XXX change this name to avoid driver-specific prefix */
+DisplayModePtr
+i830_dvo_get_current_mode (xf86OutputPtr output);
+
#endif
diff --git a/src/i830.h b/src/i830.h
index c91be791..0fe5d414 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -205,6 +205,7 @@ struct _I830DVODriver {
int type;
char *modulename;
char *fntablename;
+ unsigned int dvo_reg;
int address;
const char **symbols;
I830I2CVidOutputRec *vid_rec;
@@ -466,13 +467,6 @@ typedef struct _I830Rec {
int ddc2;
- /* The BIOS's fixed timings for the LVDS */
- DisplayModePtr panel_fixed_mode;
-
- int backlight_duty_cycle; /* restore backlight to this value */
-
- Bool panel_wants_dither;
-
CARD32 saveDSPACNTR;
CARD32 saveDSPBCNTR;
CARD32 savePIPEACONF;
@@ -637,9 +631,6 @@ extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
/* return a mask of output indices matching outputs against type_mask */
int i830_output_clones (ScrnInfoPtr pScrn, int type_mask);
-/* i830_bios.c */
-DisplayModePtr i830_bios_get_panel_mode(ScrnInfoPtr pScrn);
-
/* i830_display.c */
Bool
i830PipeHasType (xf86CrtcPtr crtc, int type);
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 129651c9..b69105e9 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -60,11 +60,11 @@ static const char *ch7017_symbols[] = {
/* driver list */
struct _I830DVODriver i830_dvo_drivers[] =
{
- {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
+ {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", DVOC,
(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
- {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
+ {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", DVOC,
(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
- {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+ {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods", DVOA,
0x04, ivch_symbols, NULL, NULL, NULL},
/*
{I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
@@ -88,20 +88,18 @@ i830_dvo_dpms(xf86OutputPtr output, int mode)
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
- void * dev_priv = intel_output->i2c_drv->dev_priv;
- unsigned int dvo_reg;
-
- if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS)
- dvo_reg = DVOA;
- else
- dvo_reg = DVOC;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ void * dev_priv = drv->dev_priv;
+ unsigned int dvo_reg = drv->dvo_reg;
if (mode == DPMSModeOn) {
OUTREG(dvo_reg, INREG(dvo_reg) | DVO_ENABLE);
+ POSTING_READ(dvo_reg);
(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
} else {
(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
OUTREG(dvo_reg, INREG(dvo_reg) & ~DVO_ENABLE);
+ POSTING_READ(dvo_reg);
}
}
@@ -131,18 +129,18 @@ i830_dvo_restore(xf86OutputPtr output)
I830OutputPrivatePtr intel_output = output->driver_private;
void * dev_priv = intel_output->i2c_drv->dev_priv;
+ (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
+
OUTREG(DVOA, pI830->saveDVOA);
OUTREG(DVOB, pI830->saveDVOB);
OUTREG(DVOC, pI830->saveDVOC);
-
- (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
}
static int
i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
I830OutputPrivatePtr intel_output = output->driver_private;
- void *dev_priv = intel_output->i2c_drv->dev_priv;
+ void *dev_priv = intel_output->i2c_drv->dev_priv;
if (pMode->Flags & V_DBLSCAN)
return MODE_NO_DBLESCAN;
@@ -156,8 +154,11 @@ static Bool
i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
- /* XXX: Hook this up to a DVO driver function */
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ if (intel_output->i2c_drv->vid_rec->mode_fixup)
+ return intel_output->i2c_drv->vid_rec->mode_fixup (intel_output->i2c_drv->dev_priv,
+ mode, adjusted_mode);
return TRUE;
}
@@ -170,21 +171,26 @@ i830_dvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
xf86CrtcPtr crtc = output->crtc;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
I830OutputPrivatePtr intel_output = output->driver_private;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
int pipe = intel_crtc->pipe;
CARD32 dvo;
- unsigned int dvo_reg, dvo_srcdim_reg;
+ unsigned int dvo_reg = drv->dvo_reg, dvo_srcdim_reg;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
- if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS) {
- dvo_reg = DVOA;
+ switch (dvo_reg) {
+ case DVOA:
dvo_srcdim_reg = DVOA_SRCDIM;
- } else {
- dvo_reg = DVOC;
+ break;
+ case DVOB:
+ dvo_srcdim_reg = DVOB_SRCDIM;
+ break;
+ case DVOC:
dvo_srcdim_reg = DVOC_SRCDIM;
+ break;
}
intel_output->i2c_drv->vid_rec->mode_set(intel_output->i2c_drv->dev_priv,
- mode);
+ mode, adjusted_mode);
/* Save the data order, since I don't know what it should be set to. */
dvo = INREG(dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
@@ -227,8 +233,6 @@ i830_dvo_detect(xf86OutputPtr output)
static DisplayModePtr
i830_dvo_get_modes(xf86OutputPtr output)
{
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
DisplayModePtr modes;
@@ -241,11 +245,11 @@ i830_dvo_get_modes(xf86OutputPtr output)
if (modes != NULL)
return modes;
- if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS &&
- pI830->panel_fixed_mode != NULL)
+ if (intel_output->i2c_drv->vid_rec->get_modes)
{
- xf86PrintModeline(pScrn->scrnIndex, pI830->panel_fixed_mode);
- return xf86DuplicateMode(pI830->panel_fixed_mode);
+ modes = intel_output->i2c_drv->vid_rec->get_modes (intel_output->i2c_drv->dev_priv);
+ if (modes != NULL)
+ return modes;
}
return NULL;
@@ -258,11 +262,12 @@ i830_dvo_destroy (xf86OutputPtr output)
if (intel_output)
{
+ if (intel_output->i2c_drv->vid_rec->destroy)
+ intel_output->i2c_drv->vid_rec->destroy (intel_output->i2c_drv->dev_priv);
if (intel_output->pI2CBus)
xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE);
if (intel_output->pDDCBus)
xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE);
- /* XXX sub module cleanup? */
xfree (intel_output);
}
}
@@ -287,35 +292,49 @@ static const xf86OutputFuncsRec i830_dvo_output_funcs = {
* Other chips with DVO LVDS will need to extend this to deal with the LVDS
* chip being on DVOB/C and having multiple pipes.
*/
-static void
-i830_dvo_get_panel_timings(xf86OutputPtr output)
+DisplayModePtr
+i830_dvo_get_current_mode (xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
I830Ptr pI830 = I830PTR(pScrn);
- CARD32 dvoa = INREG(DVOA);
-
- if (!IS_I830(pI830))
- return;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ unsigned int dvo_reg = drv->dvo_reg;
+ CARD32 dvo = INREG(dvo_reg);
+ DisplayModePtr mode = NULL;
- assert(pI830->fixed_panel_mode == NULL);
-
- /* If the DVOA port is active, that'll be the LVDS, so we can pull out
+ /* If the DVO port is active, that'll be the LVDS, so we can pull out
* its timings to get how the BIOS set up the panel.
*/
- if (dvoa & DVO_ENABLE) {
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- int pipe = (dvoa & DVO_PIPE_B_SELECT) ? 1 : 0;
- xf86CrtcPtr crtc = xf86_config->crtc[pipe];
-
- pI830->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
- if (pI830->panel_fixed_mode != NULL)
- pI830->panel_fixed_mode->type |= M_T_PREFERRED;
-
- if (dvoa & DVO_HSYNC_ACTIVE_HIGH)
- pI830->panel_fixed_mode->Flags |= V_PHSYNC;
- if (dvoa & DVO_VSYNC_ACTIVE_HIGH)
- pI830->panel_fixed_mode->Flags |= V_PVSYNC;
+ if (dvo & DVO_ENABLE)
+ {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int pipe = (dvo & DVO_PIPE_B_SELECT) ? 1 : 0;
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+ if (intel_crtc->pipe == pipe)
+ {
+ mode = i830_crtc_mode_get(pScrn, crtc);
+
+ if (mode)
+ {
+ mode->type |= M_T_PREFERRED;
+
+ if (dvo & DVO_HSYNC_ACTIVE_HIGH)
+ mode->Flags |= V_PHSYNC;
+ if (dvo & DVO_VSYNC_ACTIVE_HIGH)
+ mode->Flags |= V_PVSYNC;
+ }
+ break;
+ }
+ }
}
+ return mode;
}
void
@@ -394,9 +413,6 @@ i830_dvo_init(ScrnInfoPtr pScrn)
return;
}
- if (drv->type & I830_DVO_CHIP_LVDS)
- i830_dvo_get_panel_timings(output);
-
output->driver_private = intel_output;
output->subpixel_order = SubPixelHorizontalRGB;
output->interlaceAllowed = FALSE;
@@ -405,6 +421,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
drv->dev_priv = ret_ptr;
intel_output->i2c_drv = drv;
intel_output->pI2CBus = pI2CBus;
+ drv->vid_rec->setup (drv->dev_priv, output);
return;
}
xf86UnloadSubModule(drv->modhandle);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index d16eccb5..e9098129 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -35,14 +35,27 @@
#include "i830_display.h"
#include "X11/Xatom.h"
+struct i830_lvds_priv {
+ /* The BIOS's fixed timings for the LVDS */
+ DisplayModePtr panel_fixed_mode;
+
+ /* The panel needs dithering enabled */
+ Bool panel_wants_dither;
+
+ /* restore backlight to this value */
+ int backlight_duty_cycle;
+};
+
+
/**
* Sets the backlight level.
*
* \param level backlight level, from 0 to i830_lvds_get_max_backlight().
*/
static void
-i830_lvds_set_backlight(ScrnInfoPtr pScrn, int level)
+i830_lvds_set_backlight(xf86OutputPtr output, int level)
{
+ ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
CARD32 blc_pwm_ctl;
@@ -54,9 +67,10 @@ i830_lvds_set_backlight(ScrnInfoPtr pScrn, int level)
* Returns the maximum level of the backlight duty cycle field.
*/
static CARD32
-i830_lvds_get_max_backlight(ScrnInfoPtr pScrn)
+i830_lvds_get_max_backlight(xf86OutputPtr output)
{
- I830Ptr pI830 = I830PTR(pScrn);
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
return ((INREG(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
@@ -66,10 +80,13 @@ i830_lvds_get_max_backlight(ScrnInfoPtr pScrn)
* Sets the power state for the panel.
*/
static void
-i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
+i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
{
- I830Ptr pI830 = I830PTR(pScrn);
- CARD32 pp_status;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 pp_status;
if (on) {
OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
@@ -77,9 +94,9 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
pp_status = INREG(PP_STATUS);
} while ((pp_status & PP_ON) == 0);
- i830_lvds_set_backlight(pScrn, pI830->backlight_duty_cycle);
+ i830_lvds_set_backlight(output, dev_priv->backlight_duty_cycle);
} else {
- i830_lvds_set_backlight(pScrn, 0);
+ i830_lvds_set_backlight(output, 0);
OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
do {
@@ -91,12 +108,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
static void
i830_lvds_dpms (xf86OutputPtr output, int mode)
{
- ScrnInfoPtr pScrn = output->scrn;
-
if (mode == DPMSModeOn)
- i830SetLVDSPanelPower(pScrn, TRUE);
+ i830SetLVDSPanelPower(output, TRUE);
else
- i830SetLVDSPanelPower(pScrn, FALSE);
+ i830SetLVDSPanelPower(output, FALSE);
/* XXX: We never power down the LVDS pairs. */
}
@@ -104,22 +119,24 @@ i830_lvds_dpms (xf86OutputPtr output, int mode)
static void
i830_lvds_save (xf86OutputPtr output)
{
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
pI830->savePP_ON = INREG(LVDSPP_ON);
pI830->savePP_OFF = INREG(LVDSPP_OFF);
pI830->savePP_CONTROL = INREG(PP_CONTROL);
pI830->savePP_CYCLE = INREG(PP_CYCLE);
pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
- pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
- BACKLIGHT_DUTY_CYCLE_MASK);
+ dev_priv->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
+ BACKLIGHT_DUTY_CYCLE_MASK);
/*
* If the light is off at server startup, just make it full brightness
*/
- if (pI830->backlight_duty_cycle == 0)
- pI830->backlight_duty_cycle = i830_lvds_get_max_backlight(pScrn);
+ if (dev_priv->backlight_duty_cycle == 0)
+ dev_priv->backlight_duty_cycle = i830_lvds_get_max_backlight(output);
}
static void
@@ -134,17 +151,17 @@ i830_lvds_restore(xf86OutputPtr output)
OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
if (pI830->savePP_CONTROL & POWER_TARGET_ON)
- i830SetLVDSPanelPower(pScrn, TRUE);
+ i830SetLVDSPanelPower(output, TRUE);
else
- i830SetLVDSPanelPower(pScrn, FALSE);
+ i830SetLVDSPanelPower(output, FALSE);
}
static int
i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
- DisplayModePtr pFixedMode = pI830->panel_fixed_mode;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ DisplayModePtr pFixedMode = dev_priv->panel_fixed_mode;
if (pFixedMode)
{
@@ -161,10 +178,11 @@ static Bool
i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
- ScrnInfoPtr pScrn = output->scrn;
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- I830Ptr pI830 = I830PTR(pScrn);
- I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
int i;
for (i = 0; i < xf86_config->num_output; i++) {
@@ -189,16 +207,16 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
* with the panel scaling set up to source from the H/VDisplay
* of the original mode.
*/
- if (pI830->panel_fixed_mode != NULL) {
- adjusted_mode->HDisplay = pI830->panel_fixed_mode->HDisplay;
- adjusted_mode->HSyncStart = pI830->panel_fixed_mode->HSyncStart;
- adjusted_mode->HSyncEnd = pI830->panel_fixed_mode->HSyncEnd;
- adjusted_mode->HTotal = pI830->panel_fixed_mode->HTotal;
- adjusted_mode->VDisplay = pI830->panel_fixed_mode->VDisplay;
- adjusted_mode->VSyncStart = pI830->panel_fixed_mode->VSyncStart;
- adjusted_mode->VSyncEnd = pI830->panel_fixed_mode->VSyncEnd;
- adjusted_mode->VTotal = pI830->panel_fixed_mode->VTotal;
- adjusted_mode->Clock = pI830->panel_fixed_mode->Clock;
+ if (dev_priv->panel_fixed_mode != NULL) {
+ adjusted_mode->HDisplay = dev_priv->panel_fixed_mode->HDisplay;
+ adjusted_mode->HSyncStart = dev_priv->panel_fixed_mode->HSyncStart;
+ adjusted_mode->HSyncEnd = dev_priv->panel_fixed_mode->HSyncEnd;
+ adjusted_mode->HTotal = dev_priv->panel_fixed_mode->HTotal;
+ adjusted_mode->VDisplay = dev_priv->panel_fixed_mode->VDisplay;
+ adjusted_mode->VSyncStart = dev_priv->panel_fixed_mode->VSyncStart;
+ adjusted_mode->VSyncEnd = dev_priv->panel_fixed_mode->VSyncEnd;
+ adjusted_mode->VTotal = dev_priv->panel_fixed_mode->VTotal;
+ adjusted_mode->Clock = dev_priv->panel_fixed_mode->Clock;
xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
}
@@ -214,10 +232,12 @@ static void
i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
- I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
- CARD32 pfit_control;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
+ CARD32 pfit_control;
/* The LVDS pin pair will already have been turned on in the
* i830_crtc_mode_set since it has a large impact on the DPLL settings.
@@ -232,7 +252,7 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
if (!IS_I965G(pI830)) {
- if (pI830->panel_wants_dither)
+ if (dev_priv->panel_wants_dither)
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
} else {
pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
@@ -260,8 +280,7 @@ static DisplayModePtr
i830_lvds_get_modes(xf86OutputPtr output)
{
I830OutputPrivatePtr intel_output = output->driver_private;
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
xf86MonPtr edid_mon;
DisplayModePtr modes;
@@ -290,8 +309,8 @@ i830_lvds_get_modes(xf86OutputPtr output)
}
}
- if (pI830->panel_fixed_mode != NULL)
- return xf86DuplicateMode(pI830->panel_fixed_mode);
+ if (dev_priv->panel_fixed_mode != NULL)
+ return xf86DuplicateMode(dev_priv->panel_fixed_mode);
return NULL;
}
@@ -302,7 +321,12 @@ i830_lvds_destroy (xf86OutputPtr output)
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output)
+ {
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+
+ xf86DeleteMode (&dev_priv->panel_fixed_mode, dev_priv->panel_fixed_mode);
xfree (intel_output);
+ }
}
#ifdef RANDR_12_INTERFACE
@@ -314,10 +338,11 @@ static void
i830_lvds_create_resources(xf86OutputPtr output)
{
#ifdef RANDR_12_INTERFACE
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
- INT32 range[2];
- int data, err;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ INT32 range[2];
+ int data, err;
/* Set up the backlight property, which takes effect immediately
* and accepts values only within the range.
@@ -329,7 +354,7 @@ i830_lvds_create_resources(xf86OutputPtr output)
TRUE);
range[0] = 0;
- range[1] = i830_lvds_get_max_backlight(pScrn);
+ range[1] = i830_lvds_get_max_backlight(output);
err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
FALSE, TRUE, FALSE, 2, range);
if (err != 0) {
@@ -337,7 +362,7 @@ i830_lvds_create_resources(xf86OutputPtr output)
"RRConfigureOutputProperty error, %d\n", err);
}
/* Set the current value of the backlight property */
- data = pI830->backlight_duty_cycle;
+ data = dev_priv->backlight_duty_cycle;
err = RRChangeOutputProperty(output->randr_output, backlight_atom,
XA_INTEGER, 32, PropModeReplace, 1, &data,
FALSE, TRUE);
@@ -354,8 +379,8 @@ static Bool
i830_lvds_set_property(xf86OutputPtr output, Atom property,
RRPropertyValuePtr value)
{
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
if (property == backlight_atom) {
INT32 val;
@@ -367,13 +392,13 @@ i830_lvds_set_property(xf86OutputPtr output, Atom property,
}
val = *(INT32 *)value->data;
- if (val < 0 || val > i830_lvds_get_max_backlight(pScrn))
+ if (val < 0 || val > i830_lvds_get_max_backlight(output))
return FALSE;
- if (val != pI830->backlight_duty_cycle)
+ if (val != dev_priv->backlight_duty_cycle)
{
- i830_lvds_set_backlight(pScrn, val);
- pI830->backlight_duty_cycle = val;
+ i830_lvds_set_backlight(output, val);
+ dev_priv->backlight_duty_cycle = val;
}
return TRUE;
}
@@ -407,11 +432,13 @@ i830_lvds_init(ScrnInfoPtr pScrn)
xf86OutputPtr output;
I830OutputPrivatePtr intel_output;
DisplayModePtr modes, scan, bios_mode;
+ struct i830_lvds_priv *dev_priv;
output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS");
if (!output)
return;
- intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+ intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
+ sizeof (struct i830_lvds_priv), 1);
if (!intel_output)
{
xf86OutputDestroy (output);
@@ -423,6 +450,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
output->interlaceAllowed = FALSE;
output->doubleScanAllowed = FALSE;
+ dev_priv = (struct i830_lvds_priv *) (intel_output + 1);
+ intel_output->dev_priv = dev_priv;
+
/* Set up the LVDS DDC channel. Most panels won't support it, but it can
* be useful if available.
*/
@@ -444,7 +474,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
scan->prev = scan->next;
if (scan->next != NULL)
scan->next = scan->prev;
- pI830->panel_fixed_mode = scan;
+ dev_priv->panel_fixed_mode = scan;
}
/* Delete the mode list */
while (modes != NULL)
@@ -453,16 +483,16 @@ i830_lvds_init(ScrnInfoPtr pScrn)
/* If we didn't get EDID, try checking if the panel is already turned on.
* If so, assume that whatever is currently programmed is the correct mode.
*/
- if (pI830->panel_fixed_mode == NULL) {
+ if (dev_priv->panel_fixed_mode == NULL) {
CARD32 lvds = INREG(LVDS);
int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
xf86CrtcPtr crtc = xf86_config->crtc[pipe];
if (lvds & LVDS_PORT_EN) {
- pI830->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
- if (pI830->panel_fixed_mode != NULL)
- pI830->panel_fixed_mode->type |= M_T_PREFERRED;
+ 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;
}
}
@@ -470,11 +500,11 @@ i830_lvds_init(ScrnInfoPtr pScrn)
* the BIOS being unavailable or broken, but lack the configuration options
* for now.
*/
- bios_mode = i830_bios_get_panel_mode(pScrn);
+ bios_mode = i830_bios_get_panel_mode(pScrn, &dev_priv->panel_wants_dither);
if (bios_mode != NULL) {
- if (pI830->panel_fixed_mode != NULL) {
+ if (dev_priv->panel_fixed_mode != NULL) {
if (pI830->debug_modes &&
- !xf86ModesEqual(pI830->panel_fixed_mode, bios_mode))
+ !xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode))
{
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"BIOS panel mode data doesn't match probed data, "
@@ -482,12 +512,12 @@ i830_lvds_init(ScrnInfoPtr pScrn)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n");
xf86PrintModeline(pScrn->scrnIndex, bios_mode);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n");
- xf86PrintModeline(pScrn->scrnIndex, pI830->panel_fixed_mode);
+ xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode);
xfree(bios_mode->name);
xfree(bios_mode);
}
} else {
- pI830->panel_fixed_mode = bios_mode;
+ dev_priv->panel_fixed_mode = bios_mode;
}
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -513,9 +543,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
* display.
*/
- if (pI830->panel_fixed_mode != NULL &&
- pI830->panel_fixed_mode->HDisplay == 800 &&
- pI830->panel_fixed_mode->VDisplay == 600)
+ if (dev_priv->panel_fixed_mode != NULL &&
+ dev_priv->panel_fixed_mode->HDisplay == 800 &&
+ dev_priv->panel_fixed_mode->VDisplay == 600)
{
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Suspected Mac Mini, ignoring the LVDS\n");
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index efc74f83..a76e339f 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -38,17 +38,42 @@
#include "xf86Crtc.h"
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
+#include <unistd.h>
#include "../i2c_vid.h"
+#include "../i830_bios.h"
#include "ivch_reg.h"
struct ivch_priv {
- I2CDevRec d;
+ I2CDevRec d;
- CARD16 save_VR01;
- CARD16 save_VR40;
+ xf86OutputPtr output;
+
+ DisplayModePtr panel_fixed_mode;
+ Bool panel_wants_dither;
+
+ CARD16 width;
+ CARD16 height;
+
+ CARD16 save_VR01;
+ CARD16 save_VR40;
};
+struct vch_capabilities {
+ struct aimdb_block aimdb_block;
+ CARD8 panel_type;
+ CARD8 set_panel_type;
+ CARD8 slave_address;
+ CARD8 capabilities;
+#define VCH_PANEL_FITTING_SUPPORT (0x3 << 0)
+#define VCH_PANEL_FITTING_TEXT (1 << 2)
+#define VCH_PANEL_FITTING_GRAPHICS (1 << 3)
+#define VCH_PANEL_FITTING_RATIO (1 << 4)
+#define VCH_DITHERING (1 << 5)
+ CARD8 backlight_gpio;
+ CARD8 set_panel_type_us_gpios;
+} __attribute__ ((packed));
+
static void
ivch_dump_regs(I2CDevPtr d);
@@ -129,8 +154,8 @@ ivch_write(struct ivch_priv *priv, int addr, CARD16 data)
static void *
ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
{
- struct ivch_priv *priv;
- CARD16 temp;
+ struct ivch_priv *priv;
+ CARD16 temp;
xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ivch\n");
@@ -138,6 +163,7 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
if (priv == NULL)
return NULL;
+ priv->output = NULL;
priv->d.DevName = "i82807aa \"ivch\" LVDS/CMOS panel controller";
priv->d.SlaveAddr = addr;
priv->d.pI2CBus = b;
@@ -165,6 +191,10 @@ 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:
@@ -172,18 +202,58 @@ out:
return NULL;
}
+/** Gets the panel mode */
+static Bool
+ivch_setup (I2CDevPtr d, xf86OutputPtr output)
+{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+
+ priv->output = output;
+ ivch_read (priv, VR20, &priv->width);
+ ivch_read (priv, VR21, &priv->height);
+
+ priv->panel_fixed_mode = i830_bios_get_panel_mode (output->scrn, &priv->panel_wants_dither);
+ if (!priv->panel_fixed_mode)
+ {
+ priv->panel_fixed_mode = i830_dvo_get_current_mode (output);
+ priv->panel_wants_dither = TRUE;
+ }
+
+ return TRUE;
+}
+
static xf86OutputStatus
ivch_detect(I2CDevPtr d)
{
return XF86OutputStatusUnknown;
}
+static DisplayModePtr
+ivch_get_modes (I2CDevPtr d)
+{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+
+ if (priv->panel_fixed_mode)
+ return xf86DuplicateMode (priv->panel_fixed_mode);
+
+ return NULL;
+}
+
static ModeStatus
ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode)
{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+ DisplayModePtr panel_fixed_mode = priv->panel_fixed_mode;
+
if (mode->Clock > 112000)
return MODE_CLOCK_HIGH;
+ if (panel_fixed_mode)
+ {
+ if (!xf86ModesEqual (mode, panel_fixed_mode))
+ return MODE_PANEL;
+ }
+
return MODE_OK;
}
@@ -193,37 +263,68 @@ ivch_dpms(I2CDevPtr d, int mode)
{
struct ivch_priv *priv = d->DriverPrivate.ptr;
int i;
- CARD16 temp;
+ CARD16 vr01, vr30, backlight;
/* Set the new power state of the panel. */
- if (!ivch_read(priv, VR01, &temp))
+ if (!ivch_read(priv, VR01, &vr01))
return;
if (mode == DPMSModeOn)
- temp |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
+ backlight = 1;
else
- temp &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
+ backlight = 0;
+ ivch_write(priv, VR80, backlight);
+
+ if (mode == DPMSModeOn)
+ vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
+ else
+ vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
+
+ vr01 &= ~VR01_PANEL_FIT_ENABLE;
- ivch_write(priv, VR01, temp);
+ ivch_write(priv, VR01, vr01);
/* Wait for the panel to make its state transition */
- for (i = 0; i < 1000; i++) {
- if (!ivch_read(priv, VR30, &temp))
+ for (i = 0; i < 100; i++) {
+ if (!ivch_read(priv, VR30, &vr30))
break;
- if (((temp & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn))
+ if (((vr30 & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn))
break;
+ usleep (1000);
}
+ /* And wait some more; without this, the vch fails to resync sometimes */
+ usleep (16 * 1000);
}
+static Bool
+ivch_mode_fixup(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ return TRUE;
+}
+
static void
-ivch_mode_set(I2CDevPtr d, DisplayModePtr mode)
+ivch_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
- struct ivch_priv *priv = d->DriverPrivate.ptr;
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+ CARD16 vr40 = 0;
+ CARD16 vr01;
+ ivch_read (priv, VR01, &vr01);
/* Disable panel fitting for now, until we can test. */
- ivch_write(priv, VR40, 0);
+ if (adjusted_mode->HDisplay != priv->width || adjusted_mode->VDisplay != priv->height)
+ {
+ vr01 |= VR01_PANEL_FIT_ENABLE;
+ vr40 |= VR40_AUTO_RATIO_ENABLE;
+ }
+ else
+ {
+ vr01 &= ~VR01_PANEL_FIT_ENABLE;
+ vr40 &= ~VR40_AUTO_RATIO_ENABLE;
+ }
+ ivch_write(priv, VR01, vr01);
+ ivch_write(priv, VR40, vr40);
ivch_dpms(d, DPMSModeOn);
ivch_dump_regs(d);
@@ -244,6 +345,33 @@ ivch_dump_regs(I2CDevPtr d)
ivch_read(priv, VR40, &val);
xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR40: 0x%04x\n", val);
+ /* GPIO registers */
+ ivch_read(priv, VR80, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR80: 0x%04x\n", val);
+ ivch_read(priv, VR81, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR81: 0x%04x\n", val);
+ ivch_read(priv, VR82, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR82: 0x%04x\n", val);
+ ivch_read(priv, VR83, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR83: 0x%04x\n", val);
+ ivch_read(priv, VR84, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR84: 0x%04x\n", val);
+ ivch_read(priv, VR85, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR85: 0x%04x\n", val);
+ ivch_read(priv, VR86, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR86: 0x%04x\n", val);
+ ivch_read(priv, VR87, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR87: 0x%04x\n", val);
+ ivch_read(priv, VR88, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR88: 0x%04x\n", val);
+
+ /* Scratch register 0 - AIM Panel type */
+ ivch_read(priv, VR8E, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR8E: 0x%04x\n", val);
+
+ /* Scratch register 1 - Status register */
+ ivch_read(priv, VR8F, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR8F: 0x%04x\n", val);
}
static void
@@ -267,11 +395,14 @@ ivch_restore(I2CDevPtr d)
I830I2CVidOutputRec ivch_methods = {
.init = ivch_init,
- .detect = ivch_detect,
- .mode_valid = ivch_mode_valid,
- .mode_set = ivch_mode_set,
+ .setup = ivch_setup,
.dpms = ivch_dpms,
- .dump_regs = ivch_dump_regs,
.save = ivch_save,
.restore = ivch_restore,
+ .mode_valid = ivch_mode_valid,
+ .mode_fixup = ivch_mode_fixup,
+ .mode_set = ivch_mode_set,
+ .detect = ivch_detect,
+ .get_modes = ivch_get_modes,
+ .dump_regs = ivch_dump_regs,
};
diff --git a/src/ivch/ivch_reg.h b/src/ivch/ivch_reg.h
index 112c97d6..fe5507a8 100644
--- a/src/ivch/ivch_reg.h
+++ b/src/ivch/ivch_reg.h
@@ -35,14 +35,14 @@
#ifndef I82807AA_REG_H
#define I82807AA_REG_H
-/** @defgroup VR00
+/** @defgroup VR00 VCH Revision & GMBus Base Addr
* @{
*/
#define VR00 0x00
# define VR00_BASE_ADDRESS_MASK 0x007f
/** @} */
-/** @defgroup VR01
+/** @defgroup VR01 VCH Functionality Enable
* @{
*/
#define VR01 0x01
@@ -59,7 +59,7 @@
# define VR01_DVO_ENABLE (1 << 0)
/** @} */
-/** @defgroup VR10
+/** @defgroup VR10 LCD Interface Format
* @{
*/
#define VR10 0x10
@@ -75,7 +75,79 @@
# define VR10_INTERFACE_2X24 (3 << 2)
/** @} */
-/** @defgroup VR30
+/** @defgroup VR11 CMOS Output Control
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR12 LVDS Output Control
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR18 PLL clock select
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR19 PLL clock divisor M
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR1A PLL clock divisor N
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR1F FIFO Pre-load
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR20 LCD Horizontal Display Size
+ * @{
+ */
+#define VR20 0x20
+/** @} */
+
+/** @defgroup VR21 LCD Vertical Display Size
+ * @{
+ */
+#define VR21 0x20
+/** @} */
+
+/** @defgroup VR22 Horizontal TRP to DE Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR23 Horizontal TRP to DE End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR24 Horizontal TRP To LP Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR25 Horizontal TRP To LP End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR26 Vertical TRP To FLM Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR27 Vertical TRP To FLM End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR30 Panel power down status
* @{
*/
#define VR30 0x30
@@ -83,6 +155,31 @@
# define VR30_PANEL_ON (1 << 15)
/** @} */
+/** @defgroup VR31 Tpon Panel power on sequencing delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR32 Tpon Panel power off sequencing delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR33 Tstay Panel power off stay down delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR34 Maximal FLM Pulse Interval
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR35 Maximal LP Pulse Interval
+ * @{
+ */
+/** @} */
+
/** @defgroup VR40
* @{
*/
@@ -90,8 +187,95 @@
# define VR40_STALL_ENABLE (1 << 13)
# define VR40_VERTICAL_INTERP_ENABLE (1 << 11)
# define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10)
-# define VR40_RATIO_ENABLE (1 << 9)
+# define VR40_AUTO_RATIO_ENABLE (1 << 9)
# define VR40_PANEL_FIT_ENABLE (1 << 8)
/** @} */
+/** @defgroup VR41 Panel Fitting Vertical Ratio
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR42 Panel Fitting Horizontal Ratio
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR43 Horizontal Image Size
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR44 Panel Fitting Coefficient 0
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR45 Panel Fitting Coefficient 1
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR46 Panel Fitting Coefficient 2
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR47 Panel Fitting Coefficient 3
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR48 Panel Fitting Coefficient 4
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR49 Panel Fitting Coefficient 5
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR80 GPIO 0
+ * @{
+ */
+/** @} */
+
+#define VR80 0x80
+#define VR81 0x81
+#define VR82 0x82
+#define VR83 0x83
+#define VR84 0x84
+#define VR85 0x85
+#define VR86 0x86
+#define VR87 0x87
+
+/** @defgroup VR88 GPIO 8
+ * @{
+ */
+/** @} */
+
+#define VR88 0x88
+
+/** @defgroup VR8E Graphics BIOS scratch 0
+ * @{
+ */
+#define VR8E 0x8E
+# define VR8E_PANEL_TYPE_MASK (0xf << 0)
+# define VR8E_PANEL_INTERFACE_CMOS (0 << 4)
+# define VR8E_PANEL_INTERFACE_LVDS (1 << 4)
+# define VR8E_FORCE_DEFAULT_PANEL (1 << 5)
+/** @} */
+
+/** @defgroup VR8F Graphics BIOS scratch 1
+ * @{
+ */
+#define VR8F 0x8F
+# define VR8F_VCH_PRESENT (1 << 0)
+# define VR8F_DISPLAY_CONN (1 << 1)
+# define VR8F_POWER_MASK (0x3c)
+# define VR8F_POWER_POS (2)
+/** @} */
+
+
#endif /* I82807AA_REG_H */
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 80b1b6a8..60a03e22 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -144,7 +144,7 @@ sil164_mode_valid(I2CDevPtr d, DisplayModePtr mode)
}
static void
-sil164_mode_set(I2CDevPtr d, DisplayModePtr mode)
+sil164_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
/* As long as the basics are set up, since we don't have clock dependencies
* in the mode setup, we can just leave the registers alone and everything