diff options
Diffstat (limited to 'src/ivch/ivch.c')
-rw-r--r-- | src/ivch/ivch.c | 171 |
1 files changed, 151 insertions, 20 deletions
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, }; |