drm/i915: add some framework for backlight bl_power support
authorJani Nikula <jani.nikula@intel.com>
Wed, 13 Aug 2014 09:10:12 +0000 (12:10 +0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 3 Sep 2014 08:54:18 +0000 (10:54 +0200)
Make backlight class sysfs bl_power a sub-state of backlight enabled, if
a backlight power connector callback is defined. It's up to the
connector callback to handle the sub-state, typically in a way that
respects panel power sequencing.

v2: Post the version that does not oops. *facepalm*.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed_by: Clinton Taylor <Clinton.A.Taylor@intel.com>
Tested_by: Clinton Taylor <Clinton.A.Taylor@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_panel.c

index 2466b2bc9099bb08e3c80c30ad0f074ab4582b46..a35d8a22bf870b8a5513038ef485b3b88e6acc0c 100644 (file)
@@ -179,6 +179,8 @@ struct intel_panel {
                bool active_low_pwm;
                struct backlight_device *device;
        } backlight;
+
+       void (*backlight_power)(struct intel_connector *, bool enable);
 };
 
 struct intel_connector {
index 59b028f0b1e8c7a652cc174c17373b90a4782077..af54356349291ab5f4f7a15a6a468bbe85c529ba 100644 (file)
@@ -751,6 +751,8 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
 
        spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
+       if (panel->backlight.device)
+               panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
        panel->backlight.enabled = false;
        dev_priv->display.disable_backlight(connector);
 
@@ -957,6 +959,8 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
 
        dev_priv->display.enable_backlight(connector);
        panel->backlight.enabled = true;
+       if (panel->backlight.device)
+               panel->backlight.device->props.power = FB_BLANK_UNBLANK;
 
        spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 }
@@ -965,6 +969,7 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
 static int intel_backlight_device_update_status(struct backlight_device *bd)
 {
        struct intel_connector *connector = bl_get_data(bd);
+       struct intel_panel *panel = &connector->panel;
        struct drm_device *dev = connector->base.dev;
 
        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
@@ -972,6 +977,22 @@ static int intel_backlight_device_update_status(struct backlight_device *bd)
                      bd->props.brightness, bd->props.max_brightness);
        intel_panel_set_backlight(connector, bd->props.brightness,
                                  bd->props.max_brightness);
+
+       /*
+        * Allow flipping bl_power as a sub-state of enabled. Sadly the
+        * backlight class device does not make it easy to to differentiate
+        * between callbacks for brightness and bl_power, so our backlight_power
+        * callback needs to take this into account.
+        */
+       if (panel->backlight.enabled) {
+               if (panel->backlight_power) {
+                       bool enable = bd->props.power == FB_BLANK_UNBLANK;
+                       panel->backlight_power(connector, enable);
+               }
+       } else {
+               bd->props.power = FB_BLANK_POWERDOWN;
+       }
+
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
        return 0;
 }
@@ -1023,6 +1044,11 @@ static int intel_backlight_device_register(struct intel_connector *connector)
                                            panel->backlight.level,
                                            props.max_brightness);
 
+       if (panel->backlight.enabled)
+               props.power = FB_BLANK_UNBLANK;
+       else
+               props.power = FB_BLANK_POWERDOWN;
+
        /*
         * Note: using the same name independent of the connector prevents
         * registration of multiple backlight devices in the driver.