diff --git a/src/i810_reg.h b/src/i810_reg.h index 248df04..4ef480c 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -822,6 +822,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define PP_SEQUENCE_MASK 0x30000000 #define PP_CONTROL 0x61204 +# define POWER_DOWN_ON_RESET (1 << 1) # define POWER_TARGET_ON (1 << 0) #define LVDSPP_ON 0x61208 @@ -1074,6 +1075,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) #define BLM_LEGACY_MODE (1 << 16) + /** * This is the number of cycles out of the backlight modulation cycle for which * the backlight is on. @@ -1084,6 +1086,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) +/* On 965+ backlight control is in another register */ +#define BLC_PWM_CTL2 0x61250 +#define BLM_LEGACY_MODE2 (1 << 30) + #define BLM_CTL 0x61260 #define BLM_THRESHOLD_0 0x61270 #define BLM_THRESHOLD_1 0x61274 diff --git a/src/i830.h b/src/i830.h index bf072a1..a8de0e6 100644 --- a/src/i830.h +++ b/src/i830.h @@ -532,6 +532,7 @@ typedef struct _I830Rec { CARD32 savePaletteB[256]; CARD32 saveSWF[17]; CARD32 saveBLC_PWM_CTL; + CARD32 saveBLC_PWM_CTL2; CARD32 saveFBC_CFB_BASE; CARD32 saveFBC_LL_BASE; CARD32 saveFBC_CONTROL2; diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 246008b..935ebd3 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -46,6 +46,30 @@ struct i830_lvds_priv { int backlight_duty_cycle; }; +/** + * Use legacy backlight controls? + * + * \param pI830 device in question + * + * Returns TRUE if legacy backlight should be used, false otherwise. + */ +static int +i830_lvds_backlight_legacy(I830Ptr pI830) +{ + CARD32 blc_pwm_ctl, blc_pwm_ctl2; + + /* 965GM+ change the location of the legacy control bit */ + if (IS_I965GM(pI830)) { + blc_pwm_ctl2 = INREG(BLC_PWM_CTL2); + if (blc_pwm_ctl2 & BLM_LEGACY_MODE2) + return TRUE; + } else { + blc_pwm_ctl = INREG(BLC_PWM_CTL); + if (blc_pwm_ctl & BLM_LEGACY_MODE) + return TRUE; + } + return FALSE; +} /** * Sets the backlight level. @@ -60,17 +84,11 @@ i830_lvds_set_backlight(xf86OutputPtr output, int level) CARD32 blc_pwm_ctl; blc_pwm_ctl = INREG(BLC_PWM_CTL); - if (blc_pwm_ctl & BLM_LEGACY_MODE) - { - pciWriteByte (pI830->PciTag, - LEGACY_BACKLIGHT_BRIGHTNESS, - level & 0xff); - } - else - { - blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; - OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); - } + blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; + OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); + + if (i830_lvds_backlight_legacy(pI830)) + pciWriteByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS, 0xfe); } /** @@ -82,12 +100,17 @@ i830_lvds_get_max_backlight(xf86OutputPtr output) ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); CARD32 pwm_ctl = INREG(BLC_PWM_CTL); + CARD32 val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> + BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - if (pwm_ctl & BLM_LEGACY_MODE) - return 0xff; - else - return ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> - BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; + /* + * In legacy control mode, backlight value is calculated: + * if (LBB[7:0] != 0xff) + * backlight = BLC_PWM_CTL[15:0] * BPC[7:0] + * else + * backlight = BLC_PWM_CTL[15:0] + */ + return val; } /** @@ -138,21 +161,18 @@ i830_lvds_save (xf86OutputPtr output) ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); + if (IS_I965GM(pI830)) + pI830->saveBLC_PWM_CTL2 = INREG(BLC_PWM_CTL2); pI830->savePP_ON = INREG(LVDSPP_ON); pI830->savePP_OFF = INREG(LVDSPP_OFF); pI830->savePP_CONTROL = INREG(PP_CONTROL); + pI830->savePP_CONTROL &= ~POWER_DOWN_ON_RESET; + OUTREG(PP_CONTROL, pI830->savePP_CONTROL); pI830->savePP_CYCLE = INREG(PP_CYCLE); pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL); - if (pI830->saveBLC_PWM_CTL & BLM_LEGACY_MODE) - { - dev_priv->backlight_duty_cycle = pciReadByte (pI830->PciTag, - LEGACY_BACKLIGHT_BRIGHTNESS); - } - else - { - dev_priv->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & - BACKLIGHT_DUTY_CYCLE_MASK); - } + dev_priv->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & + BACKLIGHT_DUTY_CYCLE_MASK); + ErrorF("saved duty cycle: 0x%x\n", dev_priv->backlight_duty_cycle); /* * If the light is off at server startup, just make it full brightness @@ -166,14 +186,21 @@ i830_lvds_restore(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; + if (IS_I965GM(pI830)) + OUTREG(BLC_PWM_CTL2, pI830->saveBLC_PWM_CTL2); OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL); OUTREG(LVDSPP_ON, pI830->savePP_ON); OUTREG(LVDSPP_OFF, pI830->savePP_OFF); OUTREG(PP_CYCLE, pI830->savePP_CYCLE); OUTREG(PP_CONTROL, pI830->savePP_CONTROL); - if (pI830->savePP_CONTROL & POWER_TARGET_ON) + pciWriteByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS, 0xfe); + if (pI830->savePP_CONTROL & POWER_TARGET_ON) { + ErrorF("restoring duty cycle: 0x%x\n", dev_priv->backlight_duty_cycle); i830SetLVDSPanelPower(output, TRUE); + } else i830SetLVDSPanelPower(output, FALSE); }