|
@@ -325,214 +325,263 @@ out:
|
|
pipe_config->gmch_pfit.lvds_border_bits = border;
|
|
pipe_config->gmch_pfit.lvds_border_bits = border;
|
|
}
|
|
}
|
|
|
|
|
|
-static int is_backlight_combination_mode(struct drm_device *dev)
|
|
|
|
|
|
+static int i915_panel_invert_brightness;
|
|
|
|
+MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
|
|
|
|
+ "(-1 force normal, 0 machine defaults, 1 force inversion), please "
|
|
|
|
+ "report PCI device ID, subsystem vendor and subsystem device ID "
|
|
|
|
+ "to dri-devel@lists.freedesktop.org, 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 intel_connector *connector,
|
|
|
|
+ u32 val)
|
|
{
|
|
{
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
|
|
- if (IS_GEN4(dev))
|
|
|
|
- return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
|
|
|
|
|
|
+ WARN_ON(panel->backlight.max == 0);
|
|
|
|
|
|
- if (IS_GEN2(dev))
|
|
|
|
- return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
|
|
|
|
|
|
+ if (i915_panel_invert_brightness < 0)
|
|
|
|
+ return val;
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+ if (i915_panel_invert_brightness > 0 ||
|
|
|
|
+ dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
|
|
|
|
+ return panel->backlight.max - val;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return val;
|
|
}
|
|
}
|
|
|
|
|
|
-/* 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)
|
|
|
|
|
|
+static u32 bdw_get_backlight(struct intel_connector *connector)
|
|
{
|
|
{
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- u32 val;
|
|
|
|
-
|
|
|
|
- WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock));
|
|
|
|
|
|
|
|
- /* Restore the CTL value if it lost, e.g. GPU reset */
|
|
|
|
-
|
|
|
|
- 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 {
|
|
|
|
- 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);
|
|
|
|
- }
|
|
|
|
|
|
+ return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
+}
|
|
|
|
|
|
- if (IS_VALLEYVIEW(dev) && !val)
|
|
|
|
- val = 0x0f42ffff;
|
|
|
|
- }
|
|
|
|
|
|
+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;
|
|
|
|
|
|
- return val;
|
|
|
|
|
|
+ return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
|
}
|
|
}
|
|
|
|
|
|
-static u32 intel_panel_get_max_backlight(struct drm_device *dev)
|
|
|
|
|
|
+static u32 i9xx_get_backlight(struct intel_connector *connector)
|
|
{
|
|
{
|
|
- u32 max;
|
|
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ u32 val;
|
|
|
|
|
|
- max = i915_read_blc_pwm_ctl(dev);
|
|
|
|
|
|
+ val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
+ if (INTEL_INFO(dev)->gen < 4)
|
|
|
|
+ val >>= 1;
|
|
|
|
|
|
- if (HAS_PCH_SPLIT(dev)) {
|
|
|
|
- max >>= 16;
|
|
|
|
- } else {
|
|
|
|
- if (INTEL_INFO(dev)->gen < 4)
|
|
|
|
- max >>= 17;
|
|
|
|
- else
|
|
|
|
- max >>= 16;
|
|
|
|
|
|
+ if (panel->backlight.combination_mode) {
|
|
|
|
+ u8 lbpc;
|
|
|
|
|
|
- if (is_backlight_combination_mode(dev))
|
|
|
|
- max *= 0xff;
|
|
|
|
|
|
+ pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
|
|
|
|
+ val *= lbpc;
|
|
}
|
|
}
|
|
|
|
|
|
- DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
|
|
|
|
-
|
|
|
|
- return max;
|
|
|
|
|
|
+ return val;
|
|
}
|
|
}
|
|
|
|
|
|
-static int i915_panel_invert_brightness;
|
|
|
|
-MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
|
|
|
|
- "(-1 force normal, 0 machine defaults, 1 force inversion), please "
|
|
|
|
- "report PCI device ID, subsystem vendor and subsystem device ID "
|
|
|
|
- "to dri-devel@lists.freedesktop.org, 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, u32 val)
|
|
|
|
|
|
+static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
- if (i915_panel_invert_brightness < 0)
|
|
|
|
- return val;
|
|
|
|
|
|
+ return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
+}
|
|
|
|
|
|
- if (i915_panel_invert_brightness > 0 ||
|
|
|
|
- dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
|
|
|
|
- u32 max = intel_panel_get_max_backlight(dev);
|
|
|
|
- if (max)
|
|
|
|
- return max - val;
|
|
|
|
- }
|
|
|
|
|
|
+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 val;
|
|
|
|
|
|
+ return _vlv_get_backlight(dev, pipe);
|
|
}
|
|
}
|
|
|
|
|
|
-static u32 intel_panel_get_backlight(struct drm_device *dev)
|
|
|
|
|
|
+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;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
u32 val;
|
|
u32 val;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
|
|
|
-
|
|
|
|
- if (HAS_PCH_SPLIT(dev)) {
|
|
|
|
- val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
- } else {
|
|
|
|
- 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;
|
|
|
|
-
|
|
|
|
- pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
|
|
|
|
- val *= lbpc;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ spin_lock_irqsave(&dev_priv->backlight_lock, flags);
|
|
|
|
|
|
- val = intel_panel_compute_brightness(dev, val);
|
|
|
|
|
|
+ val = dev_priv->display.get_backlight(connector);
|
|
|
|
+ val = intel_panel_compute_brightness(connector, val);
|
|
|
|
|
|
- spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
|
|
|
|
|
|
DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
|
|
DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
|
|
return val;
|
|
return val;
|
|
}
|
|
}
|
|
|
|
|
|
-static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
|
|
|
|
|
|
+static void bdw_set_backlight(struct intel_connector *connector, u32 level)
|
|
{
|
|
{
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
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 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
|
|
}
|
|
}
|
|
|
|
|
|
-static void intel_panel_actually_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;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
u32 tmp;
|
|
u32 tmp;
|
|
|
|
|
|
- DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
|
|
|
|
- level = intel_panel_compute_brightness(dev, level);
|
|
|
|
|
|
+ tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
+ I915_WRITE(BLC_PWM_CPU_CTL, tmp | 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;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ u32 tmp, mask;
|
|
|
|
|
|
- if (HAS_PCH_SPLIT(dev))
|
|
|
|
- return intel_pch_panel_set_backlight(dev, level);
|
|
|
|
|
|
+ WARN_ON(panel->backlight.max == 0);
|
|
|
|
|
|
- if (is_backlight_combination_mode(dev)) {
|
|
|
|
- u32 max = intel_panel_get_max_backlight(dev);
|
|
|
|
|
|
+ if (panel->backlight.combination_mode) {
|
|
u8 lbpc;
|
|
u8 lbpc;
|
|
|
|
|
|
- /* we're screwed, but keep behaviour backwards compatible */
|
|
|
|
- if (!max)
|
|
|
|
- max = 1;
|
|
|
|
-
|
|
|
|
- lbpc = level * 0xfe / max + 1;
|
|
|
|
|
|
+ lbpc = level * 0xfe / panel->backlight.max + 1;
|
|
level /= lbpc;
|
|
level /= lbpc;
|
|
pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
|
|
pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
|
|
}
|
|
}
|
|
|
|
|
|
- tmp = I915_READ(BLC_PWM_CTL);
|
|
|
|
- if (INTEL_INFO(dev)->gen < 4)
|
|
|
|
|
|
+ if (IS_GEN4(dev)) {
|
|
|
|
+ mask = BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
+ } else {
|
|
level <<= 1;
|
|
level <<= 1;
|
|
- tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
|
|
+ mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tmp = I915_READ(BLC_PWM_CTL) & ~mask;
|
|
I915_WRITE(BLC_PWM_CTL, tmp | level);
|
|
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] */
|
|
/* set backlight brightness to level in range [0..max] */
|
|
-void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max)
|
|
|
|
|
|
+void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
|
|
|
|
+ u32 max)
|
|
{
|
|
{
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ enum pipe pipe = intel_get_pipe_from_connector(connector);
|
|
u32 freq;
|
|
u32 freq;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ if (pipe == INVALID_PIPE)
|
|
|
|
+ return;
|
|
|
|
|
|
- freq = intel_panel_get_max_backlight(dev);
|
|
|
|
- if (!freq) {
|
|
|
|
- /* we are screwed, bail out */
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ spin_lock_irqsave(&dev_priv->backlight_lock, flags);
|
|
|
|
+
|
|
|
|
+ WARN_ON(panel->backlight.max == 0);
|
|
|
|
|
|
- /* scale to hardware, but be careful to not overflow */
|
|
|
|
|
|
+ /* scale to hardware max, but be careful to not overflow */
|
|
|
|
+ freq = panel->backlight.max;
|
|
if (freq < max)
|
|
if (freq < max)
|
|
level = level * freq / max;
|
|
level = level * freq / max;
|
|
else
|
|
else
|
|
level = freq / max * level;
|
|
level = freq / max * level;
|
|
|
|
|
|
- dev_priv->backlight.level = level;
|
|
|
|
- if (dev_priv->backlight.device)
|
|
|
|
- dev_priv->backlight.device->props.brightness = level;
|
|
|
|
|
|
+ panel->backlight.level = level;
|
|
|
|
+ if (panel->backlight.device)
|
|
|
|
+ panel->backlight.device->props.brightness = level;
|
|
|
|
|
|
- if (dev_priv->backlight.enabled)
|
|
|
|
- intel_panel_actually_set_backlight(dev, level);
|
|
|
|
-out:
|
|
|
|
- spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ if (panel->backlight.enabled)
|
|
|
|
+ intel_panel_actually_set_backlight(connector, level);
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ intel_panel_actually_set_backlight(connector, 0);
|
|
|
|
+
|
|
|
|
+ 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 i9xx_disable_backlight(struct intel_connector *connector)
|
|
|
|
+{
|
|
|
|
+ intel_panel_actually_set_backlight(connector, 0);
|
|
}
|
|
}
|
|
|
|
|
|
-void intel_panel_disable_backlight(struct drm_device *dev)
|
|
|
|
|
|
+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;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ u32 tmp;
|
|
|
|
+
|
|
|
|
+ intel_panel_actually_set_backlight(connector, 0);
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ intel_panel_actually_set_backlight(connector, 0);
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ enum pipe pipe = intel_get_pipe_from_connector(connector);
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
+ if (pipe == INVALID_PIPE)
|
|
|
|
+ return;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Do not disable backlight on the vgaswitcheroo path. When switching
|
|
* Do not disable backlight on the vgaswitcheroo path. When switching
|
|
* away from i915, the other client may depend on i915 to handle the
|
|
* away from i915, the other client may depend on i915 to handle the
|
|
@@ -544,116 +593,215 @@ void intel_panel_disable_backlight(struct drm_device *dev)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ spin_lock_irqsave(&dev_priv->backlight_lock, flags);
|
|
|
|
|
|
- dev_priv->backlight.enabled = false;
|
|
|
|
- intel_panel_actually_set_backlight(dev, 0);
|
|
|
|
|
|
+ panel->backlight.enabled = false;
|
|
|
|
+ dev_priv->display.disable_backlight(connector);
|
|
|
|
|
|
- if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
- uint32_t reg, tmp;
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void bdw_enable_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;
|
|
|
|
+ u32 pch_ctl1, pch_ctl2;
|
|
|
|
+
|
|
|
|
+ pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
|
|
|
|
+ if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
|
|
|
|
+ DRM_DEBUG_KMS("pch backlight already enabled\n");
|
|
|
|
+ pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
|
|
|
|
+ }
|
|
|
|
|
|
- reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
|
|
|
|
|
|
+ pch_ctl2 = panel->backlight.max << 16;
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
|
|
|
|
|
|
- I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
|
|
|
|
|
|
+ pch_ctl1 = 0;
|
|
|
|
+ if (panel->backlight.active_low_pwm)
|
|
|
|
+ pch_ctl1 |= BLM_PCH_POLARITY;
|
|
|
|
|
|
- if (HAS_PCH_SPLIT(dev)) {
|
|
|
|
- tmp = I915_READ(BLC_PWM_PCH_CTL1);
|
|
|
|
- tmp &= ~BLM_PCH_PWM_ENABLE;
|
|
|
|
- I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ /* BDW always uses the pch pwm controls. */
|
|
|
|
+ pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
|
|
|
|
+
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
|
|
|
|
+ POSTING_READ(BLC_PWM_PCH_CTL1);
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
|
|
|
|
|
|
- spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ /* This won't stick until the above enable. */
|
|
|
|
+ intel_panel_actually_set_backlight(connector, panel->backlight.level);
|
|
}
|
|
}
|
|
|
|
|
|
-void intel_panel_enable_backlight(struct drm_device *dev,
|
|
|
|
- enum pipe pipe)
|
|
|
|
|
|
+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;
|
|
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 =
|
|
enum transcoder cpu_transcoder =
|
|
intel_pipe_to_cpu_transcoder(dev_priv, pipe);
|
|
intel_pipe_to_cpu_transcoder(dev_priv, pipe);
|
|
- unsigned long flags;
|
|
|
|
-
|
|
|
|
- DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
|
|
|
|
|
|
+ u32 cpu_ctl2, pch_ctl1, pch_ctl2;
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
|
|
|
|
+ if (cpu_ctl2 & BLM_PWM_ENABLE) {
|
|
|
|
+ WARN(1, "cpu backlight already enabled\n");
|
|
|
|
+ cpu_ctl2 &= ~BLM_PWM_ENABLE;
|
|
|
|
+ I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
|
|
|
|
+ }
|
|
|
|
|
|
- if (dev_priv->backlight.level == 0) {
|
|
|
|
- dev_priv->backlight.level = intel_panel_get_max_backlight(dev);
|
|
|
|
- if (dev_priv->backlight.device)
|
|
|
|
- dev_priv->backlight.device->props.brightness =
|
|
|
|
- dev_priv->backlight.level;
|
|
|
|
|
|
+ pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
|
|
|
|
+ if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
|
|
|
|
+ DRM_DEBUG_KMS("pch backlight already enabled\n");
|
|
|
|
+ pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
|
|
}
|
|
}
|
|
|
|
|
|
- if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
- uint32_t reg, tmp;
|
|
|
|
|
|
+ if (cpu_transcoder == TRANSCODER_EDP)
|
|
|
|
+ cpu_ctl2 = BLM_TRANSCODER_EDP;
|
|
|
|
+ else
|
|
|
|
+ cpu_ctl2 = BLM_PIPE(cpu_transcoder);
|
|
|
|
+ I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
|
|
|
|
+ POSTING_READ(BLC_PWM_CPU_CTL2);
|
|
|
|
+ I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
|
|
|
|
|
|
- reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
|
|
|
|
|
|
+ /* This won't stick until the above enable. */
|
|
|
|
+ intel_panel_actually_set_backlight(connector, panel->backlight.level);
|
|
|
|
|
|
|
|
+ pch_ctl2 = panel->backlight.max << 16;
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
|
|
|
|
|
|
- tmp = I915_READ(reg);
|
|
|
|
|
|
+ pch_ctl1 = 0;
|
|
|
|
+ if (panel->backlight.active_low_pwm)
|
|
|
|
+ pch_ctl1 |= BLM_PCH_POLARITY;
|
|
|
|
|
|
- /* 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;
|
|
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
|
|
|
|
+ POSTING_READ(BLC_PWM_PCH_CTL1);
|
|
|
|
+ I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
|
|
|
|
+}
|
|
|
|
|
|
- if (INTEL_INFO(dev)->num_pipes == 3)
|
|
|
|
- tmp &= ~BLM_PIPE_SELECT_IVB;
|
|
|
|
- else
|
|
|
|
- tmp &= ~BLM_PIPE_SELECT;
|
|
|
|
|
|
+static void i9xx_enable_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;
|
|
|
|
+ u32 ctl, freq;
|
|
|
|
|
|
- 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);
|
|
|
|
- }
|
|
|
|
|
|
+ ctl = I915_READ(BLC_PWM_CTL);
|
|
|
|
+ if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
|
|
|
|
+ WARN(1, "backlight already enabled\n");
|
|
|
|
+ I915_WRITE(BLC_PWM_CTL, 0);
|
|
}
|
|
}
|
|
|
|
|
|
-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.
|
|
|
|
- */
|
|
|
|
- dev_priv->backlight.enabled = true;
|
|
|
|
- intel_panel_actually_set_backlight(dev, dev_priv->backlight.level);
|
|
|
|
|
|
+ freq = panel->backlight.max;
|
|
|
|
+ if (panel->backlight.combination_mode)
|
|
|
|
+ freq /= 0xff;
|
|
|
|
+
|
|
|
|
+ ctl = freq << 17;
|
|
|
|
+ if (IS_GEN2(dev) && panel->backlight.combination_mode)
|
|
|
|
+ ctl |= BLM_LEGACY_MODE;
|
|
|
|
+ if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
|
|
|
|
+ ctl |= BLM_POLARITY_PNV;
|
|
|
|
|
|
- spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ I915_WRITE(BLC_PWM_CTL, ctl);
|
|
|
|
+ POSTING_READ(BLC_PWM_CTL);
|
|
|
|
+
|
|
|
|
+ /* XXX: combine this into above write? */
|
|
|
|
+ intel_panel_actually_set_backlight(connector, panel->backlight.level);
|
|
}
|
|
}
|
|
|
|
|
|
-/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */
|
|
|
|
-static void intel_panel_init_backlight_regs(struct drm_device *dev)
|
|
|
|
|
|
+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;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ enum pipe pipe = intel_get_pipe_from_connector(connector);
|
|
|
|
+ u32 ctl, ctl2, freq;
|
|
|
|
+
|
|
|
|
+ ctl2 = I915_READ(BLC_PWM_CTL2);
|
|
|
|
+ if (ctl2 & BLM_PWM_ENABLE) {
|
|
|
|
+ WARN(1, "backlight already enabled\n");
|
|
|
|
+ ctl2 &= ~BLM_PWM_ENABLE;
|
|
|
|
+ I915_WRITE(BLC_PWM_CTL2, ctl2);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ freq = panel->backlight.max;
|
|
|
|
+ if (panel->backlight.combination_mode)
|
|
|
|
+ freq /= 0xff;
|
|
|
|
+
|
|
|
|
+ ctl = freq << 16;
|
|
|
|
+ I915_WRITE(BLC_PWM_CTL, ctl);
|
|
|
|
|
|
- if (IS_VALLEYVIEW(dev)) {
|
|
|
|
- u32 cur_val = I915_READ(BLC_PWM_CTL) &
|
|
|
|
- BACKLIGHT_DUTY_CYCLE_MASK;
|
|
|
|
- I915_WRITE(BLC_PWM_CTL, (0xf42 << 16) | cur_val);
|
|
|
|
|
|
+ /* XXX: combine this into above write? */
|
|
|
|
+ intel_panel_actually_set_backlight(connector, panel->backlight.level);
|
|
|
|
+
|
|
|
|
+ ctl2 = BLM_PIPE(pipe);
|
|
|
|
+ if (panel->backlight.combination_mode)
|
|
|
|
+ ctl2 |= BLM_COMBINATION_MODE;
|
|
|
|
+ if (panel->backlight.active_low_pwm)
|
|
|
|
+ ctl2 |= BLM_POLARITY_I965;
|
|
|
|
+ I915_WRITE(BLC_PWM_CTL2, ctl2);
|
|
|
|
+ POSTING_READ(BLC_PWM_CTL2);
|
|
|
|
+ I915_WRITE(BLC_PWM_CTL2, ctl2 | 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;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ enum pipe pipe = intel_get_pipe_from_connector(connector);
|
|
|
|
+ u32 ctl, ctl2;
|
|
|
|
+
|
|
|
|
+ ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
|
|
|
|
+ if (ctl2 & BLM_PWM_ENABLE) {
|
|
|
|
+ WARN(1, "backlight already enabled\n");
|
|
|
|
+ ctl2 &= ~BLM_PWM_ENABLE;
|
|
|
|
+ I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ ctl = panel->backlight.max << 16;
|
|
|
|
+ I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
|
|
|
|
+
|
|
|
|
+ /* XXX: combine this into above write? */
|
|
|
|
+ intel_panel_actually_set_backlight(connector, panel->backlight.level);
|
|
|
|
+
|
|
|
|
+ ctl2 = 0;
|
|
|
|
+ if (panel->backlight.active_low_pwm)
|
|
|
|
+ ctl2 |= BLM_POLARITY_I965;
|
|
|
|
+ I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
|
|
|
|
+ POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
|
|
|
|
+ I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
|
|
}
|
|
}
|
|
|
|
|
|
-static void intel_panel_init_backlight(struct drm_device *dev)
|
|
|
|
|
|
+void intel_panel_enable_backlight(struct intel_connector *connector)
|
|
{
|
|
{
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ enum pipe pipe = intel_get_pipe_from_connector(connector);
|
|
|
|
+ unsigned long flags;
|
|
|
|
+
|
|
|
|
+ if (pipe == INVALID_PIPE)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dev_priv->backlight_lock, flags);
|
|
|
|
+
|
|
|
|
+ WARN_ON(panel->backlight.max == 0);
|
|
|
|
+
|
|
|
|
+ if (panel->backlight.level == 0) {
|
|
|
|
+ panel->backlight.level = panel->backlight.max;
|
|
|
|
+ if (panel->backlight.device)
|
|
|
|
+ panel->backlight.device->props.brightness =
|
|
|
|
+ panel->backlight.level;
|
|
|
|
+ }
|
|
|
|
|
|
- intel_panel_init_backlight_regs(dev);
|
|
|
|
|
|
+ dev_priv->display.enable_backlight(connector);
|
|
|
|
+ panel->backlight.enabled = true;
|
|
|
|
|
|
- dev_priv->backlight.level = intel_panel_get_backlight(dev);
|
|
|
|
- dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
enum drm_connector_status
|
|
enum drm_connector_status
|
|
@@ -679,85 +827,320 @@ intel_panel_detect(struct drm_device *dev)
|
|
}
|
|
}
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
|
|
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
|
|
-static int intel_panel_update_status(struct backlight_device *bd)
|
|
|
|
|
|
+static int intel_backlight_device_update_status(struct backlight_device *bd)
|
|
{
|
|
{
|
|
- struct drm_device *dev = bl_get_data(bd);
|
|
|
|
|
|
+ struct intel_connector *connector = bl_get_data(bd);
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&dev->mode_config.mutex);
|
|
DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
|
|
DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
|
|
bd->props.brightness, bd->props.max_brightness);
|
|
bd->props.brightness, bd->props.max_brightness);
|
|
- intel_panel_set_backlight(dev, bd->props.brightness,
|
|
|
|
|
|
+ intel_panel_set_backlight(connector, bd->props.brightness,
|
|
bd->props.max_brightness);
|
|
bd->props.max_brightness);
|
|
|
|
+ mutex_unlock(&dev->mode_config.mutex);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int intel_panel_get_brightness(struct backlight_device *bd)
|
|
|
|
|
|
+static int intel_backlight_device_get_brightness(struct backlight_device *bd)
|
|
{
|
|
{
|
|
- struct drm_device *dev = bl_get_data(bd);
|
|
|
|
- return intel_panel_get_backlight(dev);
|
|
|
|
|
|
+ struct intel_connector *connector = bl_get_data(bd);
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&dev->mode_config.mutex);
|
|
|
|
+ ret = intel_panel_get_backlight(connector);
|
|
|
|
+ mutex_unlock(&dev->mode_config.mutex);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static const struct backlight_ops intel_panel_bl_ops = {
|
|
|
|
- .update_status = intel_panel_update_status,
|
|
|
|
- .get_brightness = intel_panel_get_brightness,
|
|
|
|
|
|
+static const struct backlight_ops intel_backlight_device_ops = {
|
|
|
|
+ .update_status = intel_backlight_device_update_status,
|
|
|
|
+ .get_brightness = intel_backlight_device_get_brightness,
|
|
};
|
|
};
|
|
|
|
|
|
-int intel_panel_setup_backlight(struct drm_connector *connector)
|
|
|
|
|
|
+static int intel_backlight_device_register(struct intel_connector *connector)
|
|
{
|
|
{
|
|
- struct drm_device *dev = connector->dev;
|
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
struct backlight_properties props;
|
|
struct backlight_properties props;
|
|
- unsigned long flags;
|
|
|
|
|
|
|
|
- intel_panel_init_backlight(dev);
|
|
|
|
-
|
|
|
|
- if (WARN_ON(dev_priv->backlight.device))
|
|
|
|
|
|
+ if (WARN_ON(panel->backlight.device))
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ BUG_ON(panel->backlight.max == 0);
|
|
|
|
+
|
|
memset(&props, 0, sizeof(props));
|
|
memset(&props, 0, sizeof(props));
|
|
props.type = BACKLIGHT_RAW;
|
|
props.type = BACKLIGHT_RAW;
|
|
- props.brightness = dev_priv->backlight.level;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
|
|
|
- props.max_brightness = intel_panel_get_max_backlight(dev);
|
|
|
|
- spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
|
|
|
|
|
|
+ props.brightness = panel->backlight.level;
|
|
|
|
+ props.max_brightness = panel->backlight.max;
|
|
|
|
|
|
- if (props.max_brightness == 0) {
|
|
|
|
- DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
|
|
|
|
- return -ENODEV;
|
|
|
|
- }
|
|
|
|
- dev_priv->backlight.device =
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Note: using the same name independent of the connector prevents
|
|
|
|
+ * registration of multiple backlight devices in the driver.
|
|
|
|
+ */
|
|
|
|
+ panel->backlight.device =
|
|
backlight_device_register("intel_backlight",
|
|
backlight_device_register("intel_backlight",
|
|
- &connector->kdev, dev,
|
|
|
|
- &intel_panel_bl_ops, &props);
|
|
|
|
|
|
+ connector->base.kdev,
|
|
|
|
+ connector,
|
|
|
|
+ &intel_backlight_device_ops, &props);
|
|
|
|
|
|
- if (IS_ERR(dev_priv->backlight.device)) {
|
|
|
|
|
|
+ if (IS_ERR(panel->backlight.device)) {
|
|
DRM_ERROR("Failed to register backlight: %ld\n",
|
|
DRM_ERROR("Failed to register backlight: %ld\n",
|
|
- PTR_ERR(dev_priv->backlight.device));
|
|
|
|
- dev_priv->backlight.device = NULL;
|
|
|
|
|
|
+ PTR_ERR(panel->backlight.device));
|
|
|
|
+ panel->backlight.device = NULL;
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-void intel_panel_destroy_backlight(struct drm_device *dev)
|
|
|
|
|
|
+static void intel_backlight_device_unregister(struct intel_connector *connector)
|
|
{
|
|
{
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+
|
|
|
|
+ if (panel->backlight.device) {
|
|
|
|
+ backlight_device_unregister(panel->backlight.device);
|
|
|
|
+ panel->backlight.device = NULL;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
|
|
|
|
+static int intel_backlight_device_register(struct intel_connector *connector)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+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!
|
|
|
|
+ *
|
|
|
|
+ * XXX: Query mode clock or hardware clock and program PWM modulation frequency
|
|
|
|
+ * appropriately when it's 0. Use VBT and/or sane defaults.
|
|
|
|
+ */
|
|
|
|
+static int bdw_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;
|
|
|
|
+ u32 pch_ctl1, pch_ctl2, val;
|
|
|
|
+
|
|
|
|
+ pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
|
|
|
|
+ panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
|
|
|
|
+
|
|
|
|
+ pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
|
|
|
|
+ panel->backlight.max = pch_ctl2 >> 16;
|
|
|
|
+ if (!panel->backlight.max)
|
|
|
|
+ return -ENODEV;
|
|
|
|
+
|
|
|
|
+ val = bdw_get_backlight(connector);
|
|
|
|
+ panel->backlight.level = intel_panel_compute_brightness(connector, val);
|
|
|
|
+
|
|
|
|
+ panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
|
|
|
|
+ panel->backlight.level != 0;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pch_setup_backlight(struct intel_connector *connector)
|
|
|
|
+{
|
|
|
|
+ struct drm_device *dev = connector->base.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- if (dev_priv->backlight.device) {
|
|
|
|
- backlight_device_unregister(dev_priv->backlight.device);
|
|
|
|
- dev_priv->backlight.device = NULL;
|
|
|
|
|
|
+ struct intel_panel *panel = &connector->panel;
|
|
|
|
+ u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
|
|
|
|
+
|
|
|
|
+ pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
|
|
|
|
+ panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
|
|
|
|
+
|
|
|
|
+ pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
|
|
|
|
+ panel->backlight.max = pch_ctl2 >> 16;
|
|
|
|
+ if (!panel->backlight.max)
|
|
|
|
+ return -ENODEV;
|
|
|
|
+
|
|
|
|
+ val = pch_get_backlight(connector);
|
|
|
|
+ panel->backlight.level = intel_panel_compute_brightness(connector, val);
|
|
|
|
+
|
|
|
|
+ cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
|
|
|
|
+ panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
|
|
|
|
+ (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int i9xx_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;
|
|
|
|
+ u32 ctl, val;
|
|
|
|
+
|
|
|
|
+ ctl = I915_READ(BLC_PWM_CTL);
|
|
|
|
+
|
|
|
|
+ if (IS_GEN2(dev))
|
|
|
|
+ panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
|
|
|
|
+
|
|
|
|
+ if (IS_PINEVIEW(dev))
|
|
|
|
+ panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
|
|
|
|
+
|
|
|
|
+ panel->backlight.max = ctl >> 17;
|
|
|
|
+ if (panel->backlight.combination_mode)
|
|
|
|
+ panel->backlight.max *= 0xff;
|
|
|
|
+
|
|
|
|
+ if (!panel->backlight.max)
|
|
|
|
+ return -ENODEV;
|
|
|
|
+
|
|
|
|
+ val = i9xx_get_backlight(connector);
|
|
|
|
+ panel->backlight.level = intel_panel_compute_brightness(connector, val);
|
|
|
|
+
|
|
|
|
+ panel->backlight.enabled = panel->backlight.level != 0;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int i965_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;
|
|
|
|
+ u32 ctl, ctl2, val;
|
|
|
|
+
|
|
|
|
+ ctl2 = I915_READ(BLC_PWM_CTL2);
|
|
|
|
+ panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
|
|
|
|
+ panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
|
|
|
|
+
|
|
|
|
+ ctl = I915_READ(BLC_PWM_CTL);
|
|
|
|
+ panel->backlight.max = ctl >> 16;
|
|
|
|
+ if (panel->backlight.combination_mode)
|
|
|
|
+ panel->backlight.max *= 0xff;
|
|
|
|
+
|
|
|
|
+ if (!panel->backlight.max)
|
|
|
|
+ return -ENODEV;
|
|
|
|
+
|
|
|
|
+ val = i9xx_get_backlight(connector);
|
|
|
|
+ panel->backlight.level = intel_panel_compute_brightness(connector, val);
|
|
|
|
+
|
|
|
|
+ panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
|
|
|
|
+ panel->backlight.level != 0;
|
|
|
|
+
|
|
|
|
+ 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 ctl, ctl2, 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);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
|
|
|
|
+ panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
|
|
|
|
+
|
|
|
|
+ ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
|
|
|
|
+ panel->backlight.max = ctl >> 16;
|
|
|
|
+ if (!panel->backlight.max)
|
|
|
|
+ return -ENODEV;
|
|
|
|
+
|
|
|
|
+ val = _vlv_get_backlight(dev, PIPE_A);
|
|
|
|
+ panel->backlight.level = intel_panel_compute_brightness(connector, val);
|
|
|
|
+
|
|
|
|
+ panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
|
|
|
|
+ panel->backlight.level != 0;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
-#else
|
|
|
|
|
|
+
|
|
int intel_panel_setup_backlight(struct drm_connector *connector)
|
|
int intel_panel_setup_backlight(struct drm_connector *connector)
|
|
{
|
|
{
|
|
- intel_panel_init_backlight(connector->dev);
|
|
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ /* 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ intel_backlight_device_register(intel_connector);
|
|
|
|
+
|
|
|
|
+ panel->backlight.present = true;
|
|
|
|
+
|
|
|
|
+ DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
|
|
|
|
+ "sysfs interface %sregistered\n",
|
|
|
|
+ panel->backlight.enabled ? "enabled" : "disabled",
|
|
|
|
+ panel->backlight.level, panel->backlight.max,
|
|
|
|
+ panel->backlight.device ? "" : "not ");
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-void intel_panel_destroy_backlight(struct drm_device *dev)
|
|
|
|
|
|
+void intel_panel_destroy_backlight(struct drm_connector *connector)
|
|
{
|
|
{
|
|
- return;
|
|
|
|
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
|
|
+ struct intel_panel *panel = &intel_connector->panel;
|
|
|
|
+
|
|
|
|
+ panel->backlight.present = false;
|
|
|
|
+ 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 (IS_BROADWELL(dev)) {
|
|
|
|
+ dev_priv->display.setup_backlight = bdw_setup_backlight;
|
|
|
|
+ dev_priv->display.enable_backlight = bdw_enable_backlight;
|
|
|
|
+ dev_priv->display.disable_backlight = pch_disable_backlight;
|
|
|
|
+ dev_priv->display.set_backlight = bdw_set_backlight;
|
|
|
|
+ dev_priv->display.get_backlight = bdw_get_backlight;
|
|
|
|
+ } else 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;
|
|
|
|
+ } 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;
|
|
|
|
+ } 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;
|
|
|
|
+ } else {
|
|
|
|
+ dev_priv->display.setup_backlight = i9xx_setup_backlight;
|
|
|
|
+ dev_priv->display.enable_backlight = i9xx_enable_backlight;
|
|
|
|
+ dev_priv->display.disable_backlight = i9xx_disable_backlight;
|
|
|
|
+ dev_priv->display.set_backlight = i9xx_set_backlight;
|
|
|
|
+ dev_priv->display.get_backlight = i9xx_get_backlight;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-#endif
|
|
|
|
|
|
|
|
int intel_panel_init(struct intel_panel *panel,
|
|
int intel_panel_init(struct intel_panel *panel,
|
|
struct drm_display_mode *fixed_mode)
|
|
struct drm_display_mode *fixed_mode)
|