]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/i915/intel_panel.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / gpu / drm / i915 / intel_panel.c
index 92ff8f38527810657f94ad2f4439732e8dae8fa9..f8f86e57df2264c4578f10935b48f78370f49d4c 100644 (file)
@@ -125,15 +125,55 @@ static int is_backlight_combination_mode(struct drm_device *dev)
        return 0;
 }
 
+static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)
+{
+       u32 val;
+
+       /* 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->saveBLC_PWM_CTL2 == 0) {
+                       dev_priv->saveBLC_PWM_CTL2 = val;
+               } else if (val == 0) {
+                       I915_WRITE(BLC_PWM_PCH_CTL2,
+                                  dev_priv->saveBLC_PWM_CTL);
+                       val = dev_priv->saveBLC_PWM_CTL;
+               }
+       } else {
+               val = I915_READ(BLC_PWM_CTL);
+               if (dev_priv->saveBLC_PWM_CTL == 0) {
+                       dev_priv->saveBLC_PWM_CTL = val;
+                       dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+               } else if (val == 0) {
+                       I915_WRITE(BLC_PWM_CTL,
+                                  dev_priv->saveBLC_PWM_CTL);
+                       I915_WRITE(BLC_PWM_CTL2,
+                                  dev_priv->saveBLC_PWM_CTL2);
+                       val = dev_priv->saveBLC_PWM_CTL;
+               }
+       }
+
+       return val;
+}
+
 u32 intel_panel_get_max_backlight(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 max;
 
+       max = i915_read_blc_pwm_ctl(dev_priv);
+       if (max == 0) {
+               /* XXX add code here to query mode clock or hardware clock
+                * and program max PWM appropriately.
+                */
+               printk_once(KERN_WARNING "fixme: max PWM is zero.\n");
+               return 1;
+       }
+
        if (HAS_PCH_SPLIT(dev)) {
-               max = I915_READ(BLC_PWM_PCH_CTL2) >> 16;
+               max >>= 16;
        } else {
-               max = I915_READ(BLC_PWM_CTL);
                if (IS_PINEVIEW(dev)) {
                        max >>= 17;
                } else {
@@ -146,14 +186,6 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)
                        max *= 0xff;
        }
 
-       if (max == 0) {
-               /* XXX add code here to query mode clock or hardware clock
-                * and program max PWM appropriately.
-                */
-               DRM_ERROR("fixme: max PWM is zero.\n");
-               max = 1;
-       }
-
        DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
        return max;
 }
@@ -176,7 +208,6 @@ u32 intel_panel_get_backlight(struct drm_device *dev)
                        val &= ~1;
                        pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
                        val *= lbpc;
-                       val >>= 1;
                }
        }
 
@@ -203,11 +234,11 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level)
 
        if (is_backlight_combination_mode(dev)){
                u32 max = intel_panel_get_max_backlight(dev);
-               u8 lpbc;
+               u8 lbpc;
 
-               lpbc = level * 0xfe / max + 1;
-               level /= lpbc;
-               pci_write_config_byte(dev->pdev, PCI_LBPC, lpbc);
+               lbpc = level * 0xfe / max + 1;
+               level /= lbpc;
+               pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
        }
 
        tmp = I915_READ(BLC_PWM_CTL);
@@ -218,3 +249,34 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level)
                tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
        I915_WRITE(BLC_PWM_CTL, tmp | level);
 }
+
+void intel_panel_disable_backlight(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->backlight_enabled) {
+               dev_priv->backlight_level = intel_panel_get_backlight(dev);
+               dev_priv->backlight_enabled = false;
+       }
+
+       intel_panel_set_backlight(dev, 0);
+}
+
+void intel_panel_enable_backlight(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->backlight_level == 0)
+               dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
+
+       intel_panel_set_backlight(dev, dev_priv->backlight_level);
+       dev_priv->backlight_enabled = true;
+}
+
+void intel_panel_setup_backlight(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       dev_priv->backlight_level = intel_panel_get_backlight(dev);
+       dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
+}