diff options
author | Keith Packard <keithp@dulcimer.keithp.com> | 2007-05-16 14:02:00 -0700 |
---|---|---|
committer | Keith Packard <keithp@dulcimer.keithp.com> | 2007-05-16 14:02:00 -0700 |
commit | c0daa0a982e7074af4b50653b4a45b0a6352b43d (patch) | |
tree | 784a6d552d5ff6e957d5a5fefac99f206f654c46 | |
parent | b28817a87a1608e849e4a9a736dda43533a84b0c (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.c | 2 | ||||
-rw-r--r-- | src/ch7xxx/ch7xxx.c | 2 | ||||
-rw-r--r-- | src/i2c_vid.h | 136 | ||||
-rw-r--r-- | src/i830.h | 11 | ||||
-rw-r--r-- | src/i830_dvo.c | 121 | ||||
-rw-r--r-- | src/i830_lvds.c | 174 | ||||
-rw-r--r-- | src/ivch/ivch.c | 171 | ||||
-rw-r--r-- | src/ivch/ivch_reg.h | 194 | ||||
-rw-r--r-- | src/sil164/sil164.c | 2 |
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 @@ -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 |