On Fri, 2013-11-08 at 16:48 +0200, Jani Nikula wrote: > The backlight code has grown rather hairy, not least because the > hardware registers and bits have repeatedly been shuffled around. And > this isn't expected to get any easier with new hardware. Make things > easier for our (read: my) poor brains, and split the code up into chip > specific functions. > > There should be no functional changes. > > Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> This was rather difficult to read. Perhaps breaking it to per-callback refactoring patches would've been feasible and easier to review, but looks anyway good to me: Reviewed-by: Imre Deak <imre.deak@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_drv.h | 9 + > drivers/gpu/drm/i915/intel_display.c | 2 + > drivers/gpu/drm/i915/intel_drv.h | 2 + > drivers/gpu/drm/i915/intel_panel.c | 642 +++++++++++++++++++++++----------- > 4 files changed, 447 insertions(+), 208 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 0517d47..2d70ae4 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -351,6 +351,7 @@ struct drm_i915_error_state { > enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS]; > }; > > +struct intel_connector; > struct intel_crtc_config; > struct intel_crtc; > struct intel_limit; > @@ -413,6 +414,14 @@ struct drm_i915_display_funcs { > /* render clock increase/decrease */ > /* display clock increase/decrease */ > /* pll clock increase/decrease */ > + > + int (*setup_backlight)(struct intel_connector *connector); > + uint32_t (*get_max_backlight)(struct intel_connector *connector); > + uint32_t (*get_backlight)(struct intel_connector *connector); > + void (*set_backlight)(struct intel_connector *connector, > + uint32_t level); > + void (*disable_backlight)(struct intel_connector *connector); > + void (*enable_backlight)(struct intel_connector *connector); > }; > > struct intel_uncore_funcs { > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 30d3993..b6533f8 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -10604,6 +10604,8 @@ static void intel_init_display(struct drm_device *dev) > dev_priv->display.queue_flip = intel_gen7_queue_flip; > break; > } > + > + intel_panel_init_backlight_funcs(dev); > } > > /* > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 68bec63..7384a7b 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -161,6 +161,7 @@ struct intel_panel { > struct { > bool present; > u32 level; > + u32 max; > bool enabled; > struct backlight_device *device; > } backlight; > @@ -817,6 +818,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector); > void intel_panel_enable_backlight(struct intel_connector *connector); > void intel_panel_disable_backlight(struct intel_connector *connector); > void intel_panel_destroy_backlight(struct drm_connector *connector); > +void intel_panel_init_backlight_funcs(struct drm_device *dev); > enum drm_connector_status intel_panel_detect(struct drm_device *dev); > > > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c > index c80bffc..a821949 100644 > --- a/drivers/gpu/drm/i915/intel_panel.c > +++ b/drivers/gpu/drm/i915/intel_panel.c > @@ -338,79 +338,117 @@ static int is_backlight_combination_mode(struct drm_device *dev) > return 0; > } > > -/* XXX: query mode clock or hardware clock and program max PWM appropriately > - * when it's 0. > - */ > -static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) > +static u32 pch_get_max_backlight(struct intel_connector *connector) > { > + struct drm_device *dev = connector->base.dev; > struct drm_i915_private *dev_priv = dev->dev_private; > u32 val; > > - WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight_lock)); > + val = I915_READ(BLC_PWM_PCH_CTL2); > + if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) { > + dev_priv->regfile.saveBLC_PWM_CTL2 = val; > + } else if (val == 0) { > + val = dev_priv->regfile.saveBLC_PWM_CTL2; > + I915_WRITE(BLC_PWM_PCH_CTL2, val); > + } > > - /* Restore the CTL value if it lost, e.g. GPU reset */ > + val >>= 16; > > - if (HAS_PCH_SPLIT(dev_priv->dev)) { > - val = I915_READ(BLC_PWM_PCH_CTL2); > - if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) { > - dev_priv->regfile.saveBLC_PWM_CTL2 = val; > - } else if (val == 0) { > - val = dev_priv->regfile.saveBLC_PWM_CTL2; > - I915_WRITE(BLC_PWM_PCH_CTL2, val); > - } > - } else if (IS_VALLEYVIEW(dev)) { > - val = I915_READ(VLV_BLC_PWM_CTL(pipe)); > - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { > - dev_priv->regfile.saveBLC_PWM_CTL = val; > - dev_priv->regfile.saveBLC_PWM_CTL2 = > - I915_READ(VLV_BLC_PWM_CTL2(pipe)); > - } else if (val == 0) { > - val = dev_priv->regfile.saveBLC_PWM_CTL; > - I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); > - I915_WRITE(VLV_BLC_PWM_CTL2(pipe), > - dev_priv->regfile.saveBLC_PWM_CTL2); > - } > + return val; > +} > > - if (!val) > - val = 0x0f42ffff; > - } else { > - val = I915_READ(BLC_PWM_CTL); > - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { > - dev_priv->regfile.saveBLC_PWM_CTL = val; > - if (INTEL_INFO(dev)->gen >= 4) > - dev_priv->regfile.saveBLC_PWM_CTL2 = > - I915_READ(BLC_PWM_CTL2); > - } else if (val == 0) { > - val = dev_priv->regfile.saveBLC_PWM_CTL; > - I915_WRITE(BLC_PWM_CTL, val); > - if (INTEL_INFO(dev)->gen >= 4) > - I915_WRITE(BLC_PWM_CTL2, > - dev_priv->regfile.saveBLC_PWM_CTL2); > - } > +static u32 i9xx_get_max_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 val; > + > + val = I915_READ(BLC_PWM_CTL); > + if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { > + dev_priv->regfile.saveBLC_PWM_CTL = val; > + } else if (val == 0) { > + val = dev_priv->regfile.saveBLC_PWM_CTL; > + I915_WRITE(BLC_PWM_CTL, val); > } > > + val >>= 17; > + > + if (is_backlight_combination_mode(dev)) > + val *= 0xff; > + > return val; > } > > -static u32 intel_panel_get_max_backlight(struct drm_device *dev, > - enum pipe pipe) > +static u32 i965_get_max_backlight(struct intel_connector *connector) > { > - u32 max; > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 val; > + > + val = I915_READ(BLC_PWM_CTL); > + if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { > + dev_priv->regfile.saveBLC_PWM_CTL = val; > + dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); > + } else if (val == 0) { > + val = dev_priv->regfile.saveBLC_PWM_CTL; > + I915_WRITE(BLC_PWM_CTL, val); > + I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); > + } > > - max = i915_read_blc_pwm_ctl(dev, pipe); > + val >>= 16; > > - if (HAS_PCH_SPLIT(dev)) { > - max >>= 16; > - } else { > - if (INTEL_INFO(dev)->gen < 4) > - max >>= 17; > - else > - max >>= 16; > + if (is_backlight_combination_mode(dev)) > + val *= 0xff; > + > + return val; > +} > + > +static u32 _vlv_get_max_backlight(struct drm_device *dev, enum pipe pipe) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 val; > > - if (is_backlight_combination_mode(dev)) > - max *= 0xff; > + val = I915_READ(VLV_BLC_PWM_CTL(pipe)); > + if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { > + dev_priv->regfile.saveBLC_PWM_CTL = val; > + dev_priv->regfile.saveBLC_PWM_CTL2 = > + I915_READ(VLV_BLC_PWM_CTL2(pipe)); > + } else if (val == 0) { > + val = dev_priv->regfile.saveBLC_PWM_CTL; > + I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); > + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), > + dev_priv->regfile.saveBLC_PWM_CTL2); > } > > + if (!val) > + val = 0x0f42ffff; > + > + val >>= 16; > + > + return val; > +} > + > +static u32 vlv_get_max_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + enum pipe pipe = intel_get_pipe_from_connector(connector); > + > + return _vlv_get_max_backlight(dev, pipe); > +} > + > +/* XXX: query mode clock or hardware clock and program max PWM appropriately > + * when it's 0. > + */ > +static u32 intel_panel_get_max_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 max; > + > + WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight_lock)); > + > + max = dev_priv->display.get_max_backlight(connector); > + > DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); > > return max; > @@ -423,9 +461,10 @@ MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " > "to dri-devel@xxxxxxxxxxxxxxxxxxxxx, if your machine needs it. " > "It will then be included in an upcoming module version."); > module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); > -static u32 intel_panel_compute_brightness(struct drm_device *dev, > - enum pipe pipe, u32 val) > +static u32 intel_panel_compute_brightness(struct intel_connector *connector, > + u32 val) > { > + struct drm_device *dev = connector->base.dev; > struct drm_i915_private *dev_priv = dev->dev_private; > > if (i915_panel_invert_brightness < 0) > @@ -433,7 +472,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, > > if (i915_panel_invert_brightness > 0 || > dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { > - u32 max = intel_panel_get_max_backlight(dev, pipe); > + u32 max = intel_panel_get_max_backlight(connector); > if (max) > return max - val; > } > @@ -441,37 +480,60 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, > return val; > } > > -static u32 intel_panel_get_backlight(struct drm_device *dev, > - enum pipe pipe) > +static u32 pch_get_backlight(struct intel_connector *connector) > { > + struct drm_device *dev = connector->base.dev; > struct drm_i915_private *dev_priv = dev->dev_private; > - u32 val; > - unsigned long flags; > - int reg; > > - spin_lock_irqsave(&dev_priv->backlight_lock, flags); > + return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; > +} > > - if (HAS_PCH_SPLIT(dev)) { > - val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; > - } else { > - if (IS_VALLEYVIEW(dev)) > - reg = VLV_BLC_PWM_CTL(pipe); > - else > - reg = BLC_PWM_CTL; > +static u32 i9xx_get_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 val; > > - val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK; > - if (INTEL_INFO(dev)->gen < 4) > - val >>= 1; > + val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; > + if (INTEL_INFO(dev)->gen < 4) > + val >>= 1; > > - if (is_backlight_combination_mode(dev)) { > - u8 lbpc; > + if (is_backlight_combination_mode(dev)) { > + u8 lbpc; > > - pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); > - val *= lbpc; > - } > + pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); > + val *= lbpc; > } > > - val = intel_panel_compute_brightness(dev, pipe, val); > + return val; > +} > + > +static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; > +} > + > +static u32 vlv_get_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + enum pipe pipe = intel_get_pipe_from_connector(connector); > + > + return _vlv_get_backlight(dev, pipe); > +} > + > +static u32 intel_panel_get_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 val; > + unsigned long flags; > + > + spin_lock_irqsave(&dev_priv->backlight_lock, flags); > + > + val = dev_priv->display.get_backlight(connector); > + val = intel_panel_compute_brightness(connector, val); > > spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); > > @@ -479,28 +541,24 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, > return val; > } > > -static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) > +static void pch_set_backlight(struct intel_connector *connector, u32 level) > { > + struct drm_device *dev = connector->base.dev; > struct drm_i915_private *dev_priv = dev->dev_private; > - u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; > - I915_WRITE(BLC_PWM_CPU_CTL, val | level); > + u32 tmp; > + > + tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; > + I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); > } > > -static void intel_panel_actually_set_backlight(struct drm_device *dev, > - enum pipe pipe, u32 level) > +static void i9xx_set_backlight(struct intel_connector *connector, u32 level) > { > + struct drm_device *dev = connector->base.dev; > struct drm_i915_private *dev_priv = dev->dev_private; > u32 tmp; > - int reg; > - > - DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); > - level = intel_panel_compute_brightness(dev, pipe, level); > - > - if (HAS_PCH_SPLIT(dev)) > - return intel_pch_panel_set_backlight(dev, level); > > if (is_backlight_combination_mode(dev)) { > - u32 max = intel_panel_get_max_backlight(dev, pipe); > + u32 max = intel_panel_get_max_backlight(connector); > u8 lbpc; > > /* we're screwed, but keep behaviour backwards compatible */ > @@ -512,16 +570,34 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, > pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); > } > > - if (IS_VALLEYVIEW(dev)) > - reg = VLV_BLC_PWM_CTL(pipe); > - else > - reg = BLC_PWM_CTL; > - > - tmp = I915_READ(reg); > if (INTEL_INFO(dev)->gen < 4) > level <<= 1; > - tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; > - I915_WRITE(reg, tmp | level); > + > + tmp = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; > + I915_WRITE(BLC_PWM_CTL, tmp | level); > +} > + > +static void vlv_set_backlight(struct intel_connector *connector, u32 level) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe = intel_get_pipe_from_connector(connector); > + u32 tmp; > + > + tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; > + I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); > +} > + > +static void > +intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); > + > + level = intel_panel_compute_brightness(connector, level); > + dev_priv->display.set_backlight(connector, level); > } > > /* set backlight brightness to level in range [0..max] */ > @@ -540,7 +616,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, > > spin_lock_irqsave(&dev_priv->backlight_lock, flags); > > - freq = intel_panel_get_max_backlight(dev, pipe); > + freq = intel_panel_get_max_backlight(connector); > if (!freq) { > /* we are screwed, bail out */ > goto out; > @@ -557,11 +633,45 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, > panel->backlight.device->props.brightness = level; > > if (panel->backlight.enabled) > - intel_panel_actually_set_backlight(dev, pipe, level); > + intel_panel_actually_set_backlight(connector, level); > out: > spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); > } > > +static void pch_disable_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 tmp; > + > + tmp = I915_READ(BLC_PWM_CPU_CTL2); > + I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); > + > + tmp = I915_READ(BLC_PWM_PCH_CTL1); > + I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); > +} > + > +static void i965_disable_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 tmp; > + > + tmp = I915_READ(BLC_PWM_CTL2); > + I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); > +} > + > +static void vlv_disable_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe = intel_get_pipe_from_connector(connector); > + u32 tmp; > + > + tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); > + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); > +} > + > void intel_panel_disable_backlight(struct intel_connector *connector) > { > struct drm_device *dev = connector->base.dev; > @@ -587,28 +697,100 @@ void intel_panel_disable_backlight(struct intel_connector *connector) > spin_lock_irqsave(&dev_priv->backlight_lock, flags); > > panel->backlight.enabled = false; > - intel_panel_actually_set_backlight(dev, pipe, 0); > + intel_panel_actually_set_backlight(connector, 0); > > - if (INTEL_INFO(dev)->gen >= 4) { > - uint32_t reg, tmp; > + if (dev_priv->display.disable_backlight) > + dev_priv->display.disable_backlight(connector); > > - if (HAS_PCH_SPLIT(dev)) > - reg = BLC_PWM_CPU_CTL2; > - else if (IS_VALLEYVIEW(dev)) > - reg = VLV_BLC_PWM_CTL2(pipe); > - else > - reg = BLC_PWM_CTL2; > + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); > +} > > - I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); > +static void pch_enable_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe = intel_get_pipe_from_connector(connector); > + enum transcoder cpu_transcoder = > + intel_pipe_to_cpu_transcoder(dev_priv, pipe); > + u32 tmp; > > - if (HAS_PCH_SPLIT(dev)) { > - tmp = I915_READ(BLC_PWM_PCH_CTL1); > - tmp &= ~BLM_PCH_PWM_ENABLE; > - I915_WRITE(BLC_PWM_PCH_CTL1, tmp); > - } > + tmp = I915_READ(BLC_PWM_CPU_CTL2); > + > + /* 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 & BLM_PWM_ENABLE) > + return; > + > + if (INTEL_INFO(dev)->num_pipes == 3) > + tmp &= ~BLM_PIPE_SELECT_IVB; > + else > + tmp &= ~BLM_PIPE_SELECT; > + > + if (cpu_transcoder == TRANSCODER_EDP) > + tmp |= BLM_TRANSCODER_EDP; > + else > + tmp |= BLM_PIPE(cpu_transcoder); > + tmp &= ~BLM_PWM_ENABLE; > + > + I915_WRITE(BLC_PWM_CPU_CTL2, tmp); > + POSTING_READ(BLC_PWM_CPU_CTL2); > + I915_WRITE(BLC_PWM_CPU_CTL2, tmp | BLM_PWM_ENABLE); > + > + if (!(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { > + tmp = I915_READ(BLC_PWM_PCH_CTL1); > + tmp |= BLM_PCH_PWM_ENABLE; > + tmp &= ~BLM_PCH_OVERRIDE_ENABLE; > + I915_WRITE(BLC_PWM_PCH_CTL1, tmp); > } > +} > > - spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); > +static void i965_enable_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe = intel_get_pipe_from_connector(connector); > + u32 tmp; > + > + tmp = I915_READ(BLC_PWM_CTL2); > + > + /* 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 & BLM_PWM_ENABLE) > + return; > + > + tmp &= ~BLM_PIPE_SELECT; > + tmp |= BLM_PIPE(pipe); > + tmp &= ~BLM_PWM_ENABLE; > + > + I915_WRITE(BLC_PWM_CTL2, tmp); > + POSTING_READ(BLC_PWM_CTL2); > + I915_WRITE(BLC_PWM_CTL2, tmp | BLM_PWM_ENABLE); > +} > + > +static void vlv_enable_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe = intel_get_pipe_from_connector(connector); > + u32 tmp; > + > + tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); > + > + /* 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 & BLM_PWM_ENABLE) > + return; > + > + tmp &= ~BLM_PIPE_SELECT; > + tmp |= BLM_PIPE(pipe); > + tmp &= ~BLM_PWM_ENABLE; > + > + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp); > + POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); > + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp | BLM_PWM_ENABLE); > } > > void intel_panel_enable_backlight(struct intel_connector *connector) > @@ -617,8 +799,6 @@ void intel_panel_enable_backlight(struct intel_connector *connector) > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_panel *panel = &connector->panel; > enum pipe pipe = intel_get_pipe_from_connector(connector); > - enum transcoder cpu_transcoder = > - intel_pipe_to_cpu_transcoder(dev_priv, pipe); > unsigned long flags; > > if (pipe == INVALID_PIPE) > @@ -629,89 +809,25 @@ void intel_panel_enable_backlight(struct intel_connector *connector) > spin_lock_irqsave(&dev_priv->backlight_lock, flags); > > if (panel->backlight.level == 0) { > - panel->backlight.level = intel_panel_get_max_backlight(dev, > - pipe); > + panel->backlight.level = intel_panel_get_max_backlight(connector); > if (panel->backlight.device) > panel->backlight.device->props.brightness = > panel->backlight.level; > } > > - if (INTEL_INFO(dev)->gen >= 4) { > - uint32_t reg, tmp; > - > - if (HAS_PCH_SPLIT(dev)) > - reg = BLC_PWM_CPU_CTL2; > - else if (IS_VALLEYVIEW(dev)) > - reg = VLV_BLC_PWM_CTL2(pipe); > - else > - reg = 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 & BLM_PWM_ENABLE) > - goto set_level; > - > - if (INTEL_INFO(dev)->num_pipes == 3) > - tmp &= ~BLM_PIPE_SELECT_IVB; > - else > - tmp &= ~BLM_PIPE_SELECT; > - > - if (cpu_transcoder == TRANSCODER_EDP) > - tmp |= BLM_TRANSCODER_EDP; > - else > - tmp |= BLM_PIPE(cpu_transcoder); > - tmp &= ~BLM_PWM_ENABLE; > - > - I915_WRITE(reg, tmp); > - POSTING_READ(reg); > - I915_WRITE(reg, tmp | BLM_PWM_ENABLE); > - > - if (HAS_PCH_SPLIT(dev) && > - !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { > - tmp = I915_READ(BLC_PWM_PCH_CTL1); > - tmp |= BLM_PCH_PWM_ENABLE; > - tmp &= ~BLM_PCH_OVERRIDE_ENABLE; > - I915_WRITE(BLC_PWM_PCH_CTL1, tmp); > - } > - } > + if (dev_priv->display.enable_backlight) > + dev_priv->display.enable_backlight(connector); > > -set_level: > /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. > * BLC_PWM_CPU_CTL may be cleared to zero automatically when these > * registers are set. > */ > panel->backlight.enabled = true; > - intel_panel_actually_set_backlight(dev, pipe, > - panel->backlight.level); > + intel_panel_actually_set_backlight(connector, panel->backlight.level); > > spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); > } > > -/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */ > -static void intel_panel_init_backlight_regs(struct drm_device *dev) > -{ > - struct drm_i915_private *dev_priv = dev->dev_private; > - > - if (IS_VALLEYVIEW(dev)) { > - enum pipe pipe; > - > - for_each_pipe(pipe) { > - u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); > - > - /* Skip if the modulation freq is already set */ > - if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) > - continue; > - > - cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; > - I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | > - cur_val); > - } > - } > -} > - > enum drm_connector_status > intel_panel_detect(struct drm_device *dev) > { > @@ -753,15 +869,13 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd) > { > struct intel_connector *connector = bl_get_data(bd); > struct drm_device *dev = connector->base.dev; > - enum pipe pipe; > + int ret; > > mutex_lock(&dev->mode_config.mutex); > - pipe = intel_get_pipe_from_connector(connector); > + ret = intel_panel_get_backlight(connector); > mutex_unlock(&dev->mode_config.mutex); > - if (pipe == INVALID_PIPE) > - return 0; > > - return intel_panel_get_backlight(connector->base.dev, pipe); > + return ret; > } > > static const struct backlight_ops intel_backlight_device_ops = { > @@ -771,27 +885,18 @@ static const struct backlight_ops intel_backlight_device_ops = { > > static int intel_backlight_device_register(struct intel_connector *connector) > { > - struct drm_device *dev = connector->base.dev; > - struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_panel *panel = &connector->panel; > struct backlight_properties props; > - unsigned long flags; > > if (WARN_ON(panel->backlight.device)) > return -ENODEV; > > + BUG_ON(panel->backlight.max == 0); > + > memset(&props, 0, sizeof(props)); > props.type = BACKLIGHT_RAW; > props.brightness = panel->backlight.level; > - > - spin_lock_irqsave(&dev_priv->backlight_lock, flags); > - props.max_brightness = intel_panel_get_max_backlight(dev, 0); > - spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); > - > - if (props.max_brightness == 0) { > - DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); > - return -ENODEV; > - } > + props.max_brightness = panel->backlight.max; > > /* > * Note: using the same name independent of the connector prevents > @@ -831,15 +936,102 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) > } > #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ > > +/* Note: The setup hooks can't assume pipe is set! */ > +static int pch_setup_backlight(struct intel_connector *connector) > +{ > + struct intel_panel *panel = &connector->panel; > + u32 val; > + > + panel->backlight.max = pch_get_max_backlight(connector); > + if (!panel->backlight.max) > + return -ENODEV; > + > + val = pch_get_backlight(connector); > + panel->backlight.level = intel_panel_compute_brightness(connector, val); > + > + return 0; > +} > + > +static int i9xx_setup_backlight(struct intel_connector *connector) > +{ > + struct intel_panel *panel = &connector->panel; > + u32 val; > + > + panel->backlight.max = i9xx_get_max_backlight(connector); > + if (!panel->backlight.max) > + return -ENODEV; > + > + val = i9xx_get_backlight(connector); > + panel->backlight.level = intel_panel_compute_brightness(connector, val); > + > + return 0; > +} > + > +static int i965_setup_backlight(struct intel_connector *connector) > +{ > + struct intel_panel *panel = &connector->panel; > + u32 val; > + > + panel->backlight.max = i965_get_max_backlight(connector); > + if (!panel->backlight.max) > + return -ENODEV; > + > + val = i9xx_get_backlight(connector); > + panel->backlight.level = intel_panel_compute_brightness(connector, val); > + > + return 0; > +} > + > +static int vlv_setup_backlight(struct intel_connector *connector) > +{ > + struct drm_device *dev = connector->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_panel *panel = &connector->panel; > + enum pipe pipe; > + u32 val; > + > + for_each_pipe(pipe) { > + u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); > + > + /* Skip if the modulation freq is already set */ > + if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) > + continue; > + > + cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; > + I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | > + cur_val); > + } > + > + panel->backlight.max = _vlv_get_max_backlight(dev, PIPE_A); > + if (!panel->backlight.max) > + return -ENODEV; > + > + val = _vlv_get_backlight(dev, PIPE_A); > + panel->backlight.level = intel_panel_compute_brightness(connector, val); > + > + return 0; > +} > + > int intel_panel_setup_backlight(struct drm_connector *connector) > { > struct drm_device *dev = connector->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_connector *intel_connector = to_intel_connector(connector); > struct intel_panel *panel = &intel_connector->panel; > + unsigned long flags; > + int ret; > > - intel_panel_init_backlight_regs(dev); > + /* set level and max in panel struct */ > + spin_lock_irqsave(&dev_priv->backlight_lock, flags); > + ret = dev_priv->display.setup_backlight(intel_connector); > + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); > + > + if (ret) { > + DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", > + drm_get_connector_name(connector)); > + return ret; > + } > > - panel->backlight.level = intel_panel_get_backlight(dev, 0); > panel->backlight.enabled = panel->backlight.level != 0; > > intel_backlight_device_register(intel_connector); > @@ -858,6 +1050,40 @@ void intel_panel_destroy_backlight(struct drm_connector *connector) > intel_backlight_device_unregister(intel_connector); > } > > +/* Set up chip specific backlight functions */ > +void intel_panel_init_backlight_funcs(struct drm_device *dev) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + if (HAS_PCH_SPLIT(dev)) { > + dev_priv->display.setup_backlight = pch_setup_backlight; > + dev_priv->display.enable_backlight = pch_enable_backlight; > + dev_priv->display.disable_backlight = pch_disable_backlight; > + dev_priv->display.set_backlight = pch_set_backlight; > + dev_priv->display.get_backlight = pch_get_backlight; > + dev_priv->display.get_max_backlight = pch_get_max_backlight; > + } else if (IS_VALLEYVIEW(dev)) { > + dev_priv->display.setup_backlight = vlv_setup_backlight; > + dev_priv->display.enable_backlight = vlv_enable_backlight; > + dev_priv->display.disable_backlight = vlv_disable_backlight; > + dev_priv->display.set_backlight = vlv_set_backlight; > + dev_priv->display.get_backlight = vlv_get_backlight; > + dev_priv->display.get_max_backlight = vlv_get_max_backlight; > + } else if (IS_GEN4(dev)) { > + dev_priv->display.setup_backlight = i965_setup_backlight; > + dev_priv->display.enable_backlight = i965_enable_backlight; > + dev_priv->display.disable_backlight = i965_disable_backlight; > + dev_priv->display.set_backlight = i9xx_set_backlight; > + dev_priv->display.get_backlight = i9xx_get_backlight; > + dev_priv->display.get_max_backlight = i965_get_max_backlight; > + } else { > + dev_priv->display.setup_backlight = i9xx_setup_backlight; > + dev_priv->display.set_backlight = i9xx_set_backlight; > + dev_priv->display.get_backlight = i9xx_get_backlight; > + dev_priv->display.get_max_backlight = i9xx_get_max_backlight; > + } > +} > + > int intel_panel_init(struct intel_panel *panel, > struct drm_display_mode *fixed_mode) > { _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx