summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@dulcimer.keithp.com>2007-05-16 14:02:00 -0700
committerKeith Packard <keithp@dulcimer.keithp.com>2007-05-16 14:02:00 -0700
commitc0daa0a982e7074af4b50653b4a45b0a6352b43d (patch)
tree784a6d552d5ff6e957d5a5fefac99f206f654c46
parentb28817a87a1608e849e4a9a736dda43533a84b0c (diff)
Change DVO module interface to pass more state across. Fix IVCH display.
The DVO module interface reflected most of the xf86Output API to the underlying functions; finish that work given the changes that have since occurred in the xf86Output API. Move the LVDS-specific code into the IVCH module and make that work on the Thinkpad X30 (an i830-based laptop). Panel scaling does not work yet.
-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