From: Daniel Vetter Date: Tue, 5 Jun 2012 12:14:54 +0200 Subject: drm/i915: properly enable the blc controller on the right pipe commit 24ded204429fa0f5501d37c63ee35c555c0b75ee upstream. On gen4+ we have a bitfield to specify from which pipe the backlight controller should take it's clock. For PCH split platforms we've already set these up, but only at initialization time. And without taking into account the 3rd pipe added with ivb. For gen4, we've completely ignored these. Although we do restrict lvds to the 2nd pipe, so this is only a problem on machines where we boot up with the lvds on the first pipe. So restructure the code to enable the backlight on the right pipe at modeset time. v2: For odd reasons panel_enable_backlight gets called twice in a modeset, so we can't WARN_ON in there if the backlight controller is switched on already. v3: backlight enable can also be called through dpms on, so the check in there is legit. Update the comment to reflect that. Tested-By: Kamal Mostafa Bugzilla: https://bugs.launchpad.net/bugs/954661 Cc: Carsten Emde Reviewed-by: Eugeni Dodonov Signed-Off-by: Daniel Vetter [jrnieder@gmail.com: backporting to kernels without 7cf416014813 ("drm/i915: clear up backlight #define confusion on gen4+"): - use old names for backlight modulation #defines - add BLM_PIPE_SELECT_IVB and BLM_PIPE(pipe) definitions to i915_reg.h] Signed-off-by: Jonathan Nieder --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_drv.h | 3 ++- drivers/gpu/drm/i915/intel_lvds.c | 32 ++++++-------------------------- drivers/gpu/drm/i915/intel_panel.c | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 47 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fd53122298fb..63baf63b9b1f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1639,6 +1639,8 @@ #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) #define BLC_PWM_CTL2 0x61250 /* 965+ only */ #define BLM_COMBINATION_MODE (1 << 30) +#define BLM_PIPE_SELECT_IVB (3 << 29) +#define BLM_PIPE(pipe) ((pipe) << 29) /* * This is the most significant 15 bits of the number of backlight cycles in a * complete cycle of the modulated backlight control. diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 83e820ea95b3..1fca5f0195bd 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -302,7 +302,8 @@ extern u32 intel_panel_get_max_backlight(struct drm_device *dev); extern u32 intel_panel_get_backlight(struct drm_device *dev); extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); extern int intel_panel_setup_backlight(struct drm_device *dev); -extern void intel_panel_enable_backlight(struct drm_device *dev); +extern void intel_panel_enable_backlight(struct drm_device *dev, + enum pipe pipe); extern void intel_panel_disable_backlight(struct drm_device *dev); extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index ceec71b61b5f..0c3d16c64f3d 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -71,6 +71,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) static void intel_lvds_enable(struct intel_lvds *intel_lvds) { struct drm_device *dev = intel_lvds->base.base.dev; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc); struct drm_i915_private *dev_priv = dev->dev_private; u32 ctl_reg, lvds_reg, stat_reg; @@ -107,7 +108,7 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds) if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) DRM_ERROR("timed out waiting for panel to power on\n"); - intel_panel_enable_backlight(dev); + intel_panel_enable_backlight(dev, intel_crtc->pipe); } static void intel_lvds_disable(struct intel_lvds *intel_lvds) @@ -1052,35 +1053,14 @@ bool intel_lvds_init(struct drm_device *dev) goto failed; out: + /* + * Unlock registers and just + * leave them unlocked + */ if (HAS_PCH_SPLIT(dev)) { - u32 pwm; - - pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0; - - /* make sure PWM is enabled and locked to the LVDS pipe */ - pwm = I915_READ(BLC_PWM_CPU_CTL2); - if (pipe == 0 && (pwm & PWM_PIPE_B)) - I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE); - if (pipe) - pwm |= PWM_PIPE_B; - else - pwm &= ~PWM_PIPE_B; - I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE); - - pwm = I915_READ(BLC_PWM_PCH_CTL1); - pwm |= PWM_PCH_ENABLE; - I915_WRITE(BLC_PWM_PCH_CTL1, pwm); - /* - * Unlock registers and just - * leave them unlocked - */ I915_WRITE(PCH_PP_CONTROL, I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); } else { - /* - * Unlock registers and just - * leave them unlocked - */ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); } diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 04d79fd1dc9d..dd95f8b6e318 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -263,9 +263,18 @@ void intel_panel_disable_backlight(struct drm_device *dev) dev_priv->backlight_enabled = false; intel_panel_actually_set_backlight(dev, 0); + + if (INTEL_INFO(dev)->gen >= 4) { + uint32_t reg; + + reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; + + I915_WRITE(reg, I915_READ(reg) & ~PWM_ENABLE); + } } -void intel_panel_enable_backlight(struct drm_device *dev) +void intel_panel_enable_backlight(struct drm_device *dev, + enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -274,6 +283,33 @@ void intel_panel_enable_backlight(struct drm_device *dev) dev_priv->backlight_enabled = true; intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); + + if (INTEL_INFO(dev)->gen >= 4) { + uint32_t reg, tmp; + + reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; + + + tmp = I915_READ(reg); + + /* Note that this can also get called through dpms changes. And + * we don't track the backlight dpms state, hence check whether + * we have to do anything first. */ + if (tmp & PWM_ENABLE) + return; + + if (dev_priv->num_pipe == 3) + tmp &= ~BLM_PIPE_SELECT_IVB; + else + tmp &= ~PWM_PIPE_B; + + tmp |= BLM_PIPE(pipe); + tmp &= ~PWM_ENABLE; + + I915_WRITE(reg, tmp); + POSTING_READ(reg); + I915_WRITE(reg, tmp | PWM_ENABLE); + } } static void intel_panel_init_backlight(struct drm_device *dev) -- 1.7.11.rc3