diff options
author | Owain G. Ainsworth <oga@openbsd.org> | 2010-05-29 14:50:40 +0100 |
---|---|---|
committer | Owain G. Ainsworth <oga@openbsd.org> | 2010-05-29 14:50:40 +0100 |
commit | 0b03a6cf1409d58996ba1d69dd7d8b1d64278d46 (patch) | |
tree | f383880e987ac20c661f36a9fa9592468a202c7f /src/i830_lvds.c | |
parent | e275a0001c4d30aa9327cabd9efd5db0dd33ae7e (diff) |
Initial Ironlake support
VGA works. LVDS is still screwy. panel fitting hasn't been messed with
(yet). Mostly from RHEL5's 2.2.1 branch, courtesy of airlied.
Diffstat (limited to 'src/i830_lvds.c')
-rw-r--r-- | src/i830_lvds.c | 164 |
1 files changed, 137 insertions, 27 deletions
diff --git a/src/i830_lvds.c b/src/i830_lvds.c index b33b461d..34b3cbce 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -140,6 +140,10 @@ i830_set_lvds_backlight_method(xf86OutputPtr output) if (i830_kernel_backlight_available(output)) { method = BCM_KERNEL; +#if 0 + } else if (IS_IGDNG(intel)) { + method = BCM_IRONLAKE_NULL; +#endif } else if (IS_I965GM(intel) || IS_GM45(intel)) { blc_pwm_ctl2 = INREG(BLC_PWM_CTL2); if (blc_pwm_ctl2 & BLM_LEGACY_MODE2) @@ -161,11 +165,16 @@ i830_lvds_set_backlight_native(xf86OutputPtr output, int level) { ScrnInfoPtr scrn = output->scrn; intel_screen_private *intel = intel_get_screen_private(scrn); - uint32_t blc_pwm_ctl; + uint32_t blc_pwm_ctl, reg; - blc_pwm_ctl = INREG(BLC_PWM_CTL); + if (IS_IGDNG(intel)) + reg = BLC_PWM_CPU_CTL; + else + reg = BLC_PWM_CTL; + + blc_pwm_ctl = INREG(reg); blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; - OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); + OUTREG(reg, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); } static int @@ -185,8 +194,15 @@ i830_lvds_get_backlight_max_native(xf86OutputPtr output) { ScrnInfoPtr scrn = output->scrn; intel_screen_private *intel = intel_get_screen_private(scrn); - uint32_t pwm_ctl = INREG(BLC_PWM_CTL); - int val; + uint32_t pwm_ctl; + int val, reg; + + if (IS_IGDNG(intel)) + reg = BLC_PWM_PCH_CTL2; + else + reg = BLC_PWM_CTL; + + pwm_ctl = INREG(reg); if (IS_I965GM(intel) || IS_GM45(intel)) { val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK2) >> @@ -278,6 +294,18 @@ i830_lvds_get_backlight_max_combo(xf86OutputPtr output) return i830_lvds_get_backlight_max_native(output) >> 1; } +/* null methods */ +static int +i830_lvds_get_backlight_null(xf86OutputPtr output) +{ + return 1; +} + +static void +i830_lvds_set_backlight_null(xf86OutputPtr output, int level) +{ +} + /* * Kernel methods */ @@ -482,11 +510,33 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on) struct i830_lvds_priv *dev_priv = intel_output->dev_priv; ScrnInfoPtr scrn = output->scrn; intel_screen_private *intel = intel_get_screen_private(scrn); - uint32_t pp_status; + uint32_t pp_status, ctl_reg, status_reg; + + if (IS_IGDNG(intel)) { + ctl_reg = PCH_PP_CONTROL; + status_reg = PCH_PP_STATUS; + } else { + ctl_reg = PP_CONTROL; + status_reg = PP_STATUS; + } + + if (IS_IGDNG(intel)) { + CARD32 temp; + if (on) { + temp = INREG(PCH_LVDS); + OUTREG(PCH_LVDS, temp | PORT_ENABLE); + temp = INREG(PCH_LVDS); + } else { + temp = INREG(PCH_LVDS); + OUTREG(PCH_LVDS, temp & ~PORT_ENABLE); + temp = INREG(PCH_LVDS); + } + usleep(100); + } if (on) { /* if we're going from on->on, be aware to current level. */ - if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) + if ((INREG(ctl_reg) & POWER_TARGET_ON) && !dev_priv->dpmsoff) dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); /* @@ -496,14 +546,14 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on) * controller for example), so on them, when turning LVDS back on, * they'll always re-maximize the brightness. */ - if (!(INREG(PP_CONTROL) & POWER_TARGET_ON) && + if (!(INREG(ctl_reg) & POWER_TARGET_ON) && dev_priv->backlight_duty_cycle == 0 && intel->backlight_control_method < BCM_KERNEL) dev_priv->backlight_duty_cycle = dev_priv->backlight_max; - OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); + OUTREG(ctl_reg, INREG(ctl_reg) | POWER_TARGET_ON); do { - pp_status = INREG(PP_STATUS); + pp_status = INREG(status_reg); } while ((pp_status & PP_ON) == 0); dev_priv->set_backlight(output, dev_priv->backlight_duty_cycle); @@ -513,13 +563,13 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on) * Only save the current backlight value if we're going from * on to off. */ - if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) + if ((INREG(ctl_reg) & POWER_TARGET_ON) && !dev_priv->dpmsoff) dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); dev_priv->set_backlight(output, 0); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); + OUTREG(ctl_reg, INREG(ctl_reg) & ~POWER_TARGET_ON); do { - pp_status = INREG(PP_STATUS); + pp_status = INREG(status_reg); } while (pp_status & PP_ON); dev_priv->dpmsoff = TRUE; @@ -544,14 +594,29 @@ i830_lvds_save (xf86OutputPtr output) struct i830_lvds_priv *dev_priv = intel_output->dev_priv; ScrnInfoPtr scrn = output->scrn; intel_screen_private *intel = intel_get_screen_private(scrn); + uint32_t pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg, pwm_ctl_reg; + + if (IS_IGDNG(intel)) { + pp_on_reg = PCH_PP_ON_DELAYS; + pp_off_reg = PCH_PP_OFF_DELAYS; + pp_ctl_reg = PCH_PP_CONTROL; + pp_div_reg = PCH_PP_DIVISOR; + pwm_ctl_reg = BLC_PWM_CPU_CTL; + } else { + pp_on_reg = PP_ON_DELAYS; + pp_off_reg = PP_OFF_DELAYS; + pp_ctl_reg = PP_CONTROL; + pp_div_reg = PP_DIVISOR; + pwm_ctl_reg = BLC_PWM_CTL; + } if (IS_I965GM(intel) || IS_GM45(intel)) intel->saveBLC_PWM_CTL2 = INREG(BLC_PWM_CTL2); - intel->savePP_ON = INREG(PP_ON_DELAYS); - intel->savePP_OFF = INREG(PP_OFF_DELAYS); - intel->savePP_CONTROL = INREG(PP_CONTROL); - intel->savePP_DIVISOR = INREG(PP_DIVISOR); - intel->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL); + intel->savePP_ON = INREG(pp_on_reg); + intel->savePP_OFF = INREG(pp_off_reg); + intel->savePP_CONTROL = INREG(pp_ctl_reg); + intel->savePP_DIVISOR = INREG(pp_div_reg); + intel->saveBLC_PWM_CTL = INREG(pwm_ctl_reg); if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); } @@ -561,14 +626,31 @@ i830_lvds_restore(xf86OutputPtr output) { ScrnInfoPtr scrn = output->scrn; intel_screen_private *intel = intel_get_screen_private(scrn); + uint32_t pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; + uint32_t pwm_ctl_reg; + + if (IS_IGDNG(intel)) { + pp_on_reg = PCH_PP_ON_DELAYS; + pp_off_reg = PCH_PP_OFF_DELAYS; + pp_ctl_reg = PCH_PP_CONTROL; + pp_div_reg = PCH_PP_DIVISOR; + pwm_ctl_reg = BLC_PWM_CPU_CTL; + } else { + pp_on_reg = PP_ON_DELAYS; + pp_off_reg = PP_OFF_DELAYS; + pp_ctl_reg = PP_CONTROL; + pp_div_reg = PP_DIVISOR; + pwm_ctl_reg = BLC_PWM_CTL; + } if (IS_I965GM(intel) || IS_GM45(intel)) OUTREG(BLC_PWM_CTL2, intel->saveBLC_PWM_CTL2); - OUTREG(BLC_PWM_CTL, intel->saveBLC_PWM_CTL); - OUTREG(PP_ON_DELAYS, intel->savePP_ON); - OUTREG(PP_OFF_DELAYS, intel->savePP_OFF); - OUTREG(PP_DIVISOR, intel->savePP_DIVISOR); - OUTREG(PP_CONTROL, intel->savePP_CONTROL); + OUTREG(pwm_ctl_reg, intel->saveBLC_PWM_CTL); + OUTREG(pp_on_reg, intel->savePP_ON); + OUTREG(pp_off_reg, intel->savePP_OFF); + OUTREG(pp_div_reg, intel->savePP_DIVISOR); + OUTREG(pp_ctl_reg, intel->savePP_CONTROL); + if (intel->savePP_CONTROL & POWER_TARGET_ON) i830SetLVDSPanelPower(output, TRUE); else @@ -624,7 +706,7 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, } } - if (intel_crtc->pipe == 0) { + if (!IS_IGDNG(intel) && intel_crtc->pipe == 0) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Can't support LVDS on pipe A\n"); return FALSE; @@ -1070,12 +1152,13 @@ static Atom backlight_atom; * or not at all. */ #define BACKLIGHT_CONTROL_NAME "BACKLIGHT_CONTROL" -#define NUM_BACKLIGHT_CONTROL_METHODS 4 +#define NUM_BACKLIGHT_CONTROL_METHODS 5 static char *backlight_control_names[] = { "native", "legacy", "combination", "kernel", + "null", }; static Atom backlight_control_atom; static Atom backlight_control_name_atoms[NUM_BACKLIGHT_CONTROL_METHODS]; @@ -1135,6 +1218,11 @@ i830_lvds_set_backlight_control(xf86OutputPtr output) dev_priv->backlight_max = i830_lvds_get_backlight_max_kernel(output); break; + case BCM_IRONLAKE_NULL: + dev_priv->set_backlight = i830_lvds_set_backlight_null; + dev_priv->get_backlight = i830_lvds_get_backlight_null; + dev_priv->backlight_max = 1; + break; default: /* * Should be impossible to get here unless the caller set a bogus @@ -1447,6 +1535,7 @@ i830_lvds_init(ScrnInfoPtr scrn) DisplayModePtr modes, scan; DisplayModePtr lvds_ddc_mode = NULL; struct i830_lvds_priv *dev_priv; + int gpio = GPIOC; if (!intel->integrated_lvds) { if (intel->debug_modes) @@ -1458,6 +1547,12 @@ i830_lvds_init(ScrnInfoPtr scrn) if (intel->quirk_flag & QUIRK_IGNORE_LVDS) return; + if (IS_IGDNG(intel)) { + if ((INREG(PCH_LVDS) & LVDS_DETECTED) == 0) + return; + gpio = PCH_GPIOC; + } + output = xf86OutputCreate (scrn, &i830_lvds_output_funcs, "LVDS"); if (!output) return; @@ -1470,6 +1565,8 @@ i830_lvds_init(ScrnInfoPtr scrn) } intel_output->type = I830_OUTPUT_LVDS; intel_output->pipe_mask = (1 << 1); + if (0 && IS_IGDNG(intel)) /* XXX put me back */ + intel_output->pipe_mask |= (1 << 0); intel_output->clone_mask = (1 << I830_OUTPUT_LVDS); output->driver_private = intel_output; @@ -1492,7 +1589,7 @@ i830_lvds_init(ScrnInfoPtr scrn) /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. */ - I830I2CInit(scrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C"); + I830I2CInit(scrn, &intel_output->pDDCBus, gpio, "LVDSDDC_C"); if (intel->skip_panel_detect) { xf86DrvMsg(scrn->scrnIndex, X_INFO, @@ -1541,7 +1638,7 @@ i830_lvds_init(ScrnInfoPtr scrn) * turned on. If so, assume that whatever is currently programmed is the * correct mode. */ - if (!intel->lvds_fixed_mode) { + if (!intel->lvds_fixed_mode && !IS_IGDNG(intel)) { uint32_t lvds = INREG(LVDS); int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); @@ -1619,6 +1716,19 @@ found_mode: */ dev_priv->fitting_mode = FULL_ASPECT; + if (IS_IGDNG(intel)) { + CARD32 pwm; + /* make sure PWM is enabled */ + pwm = INREG(BLC_PWM_CPU_CTL2); + pwm |= (PWM_ENABLE | PWM_PIPE_B); + OUTREG(BLC_PWM_CPU_CTL2, pwm); + + pwm = INREG(BLC_PWM_PCH_CTL1); + pwm |= PWM_PCH_ENABLE; + OUTREG(BLC_PWM_PCH_CTL1, pwm); + } + + return; disable_exit: |