>From d957b0a6ca265797cce4296dfc3cfda625dfd96f Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 18 May 2011 17:15:48 -0400 Subject: [PATCH 2/2] i915: Add GPU backlight interface Not all systems provide a firmware or platform interface to backlight control. We should expose a gpu-level backlight interface to handle that case. Signed-off-by: Matthew Garrett --- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/intel_display.c | 2 - drivers/gpu/drm/i915/intel_dp.c | 6 +++ drivers/gpu/drm/i915/intel_drv.h | 3 +- drivers/gpu/drm/i915/intel_lvds.c | 6 +++ drivers/gpu/drm/i915/intel_panel.c | 78 ++++++++++++++++++++++++++++++---- 6 files changed, 86 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9b2b94a..68e8869 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -33,6 +33,7 @@ #include "i915_reg.h" #include "intel_bios.h" #include "intel_ringbuffer.h" +#include #include #include #include @@ -667,6 +668,7 @@ typedef struct drm_i915_private { int child_dev_num; struct child_device_config *child_dev; struct drm_connector *int_lvds_connector; + struct backlight_device *backlight; bool mchbar_need_disable; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 03726a5..7ffb851 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6752,8 +6752,6 @@ static void intel_setup_outputs(struct drm_device *dev) intel_encoder_clones(dev, encoder->clone_mask); } - intel_panel_setup_backlight(dev); - /* disable all the possible outputs/crtcs before entering KMS mode */ drm_helper_disable_unused_functions(dev); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a4d8031..c262378 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1747,6 +1747,11 @@ done: static void intel_dp_destroy (struct drm_connector *connector) { + struct intel_dp *intel_dp = intel_attached_dp(connector); + + if (is_edp(intel_dp)) + intel_panel_destroy_backlight(connector); + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); @@ -1989,6 +1994,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) DRM_MODE_TYPE_PREFERRED; } } + intel_panel_setup_backlight(connector); } intel_dp_add_properties(intel_dp, connector); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 831d7a4..c2b5c11 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -265,7 +265,8 @@ extern void intel_pch_panel_fitting(struct drm_device *dev, 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 void intel_panel_setup_backlight(struct drm_device *dev); +extern int intel_panel_setup_backlight(struct drm_connector *dev); +extern void intel_panel_destroy_backlight(struct drm_connector *dev); extern void intel_panel_enable_backlight(struct drm_device *dev); extern void intel_panel_disable_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 3b90e68..38047b6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -584,6 +584,9 @@ static void intel_lvds_destroy(struct drm_connector *connector) if (dev_priv->lid_notifier.notifier_call) acpi_lid_notifier_unregister(&dev_priv->lid_notifier); + + intel_panel_destroy_backlight(connector); + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); @@ -1033,6 +1036,9 @@ out: /* keep the LVDS connector */ dev_priv->int_lvds_connector = connector; drm_sysfs_connector_add(connector); + + intel_panel_setup_backlight(connector); + return true; failed: diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f893ff0..1be17b5 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -250,6 +250,76 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level) I915_WRITE(BLC_PWM_CTL, tmp | level); } +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +static int intel_panel_update_brightness(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + + intel_panel_set_backlight(dev, bd->props.brightness); + return 0; +} + +static int intel_panel_get_brightness(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + + return intel_panel_get_backlight(dev); +} + +static const struct backlight_ops intel_panel_bl_ops = { + .update_status = intel_panel_update_brightness, + .get_brightness = intel_panel_get_brightness, +}; + +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 backlight_properties props; + + dev_priv->backlight_level = intel_panel_get_backlight(dev); + dev_priv->backlight_enabled = dev_priv->backlight_level != 0; + + props.max_brightness = intel_panel_get_max_backlight(dev); + props.type = BACKLIGHT_RAW; + dev_priv->backlight = backlight_device_register("intel_backlight", + &connector->kdev, dev, &intel_panel_bl_ops, &props); + + if (IS_ERR(dev_priv->backlight)) { + DRM_ERROR("Failed to register backlight: %ld\n", + PTR_ERR(dev_priv->backlight)); + dev_priv->backlight = NULL; + return -ENODEV; + } + + dev_priv->backlight->props.brightness = intel_panel_get_backlight(dev); + return 0; +} + +void intel_panel_destroy_backlight(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->backlight) + backlight_device_unregister(dev_priv->backlight); +} +#else +int intel_panel_setup_backlight(struct drm_connector *connector) +{ + struct drm_device *dev = connector->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; +} + +void intel_panel_destroy_backlight(struct drm_connector *connector) +{ + return; +} +#endif + void intel_panel_disable_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -273,14 +343,6 @@ void intel_panel_enable_backlight(struct drm_device *dev) 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; -} - enum drm_connector_status intel_panel_detect(struct drm_device *dev) { -- 1.7.5