All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 1/2] drm/i915: shuffle panel code
@ 2014-04-29 20:30 Jani Nikula
  2014-04-29 20:30 ` [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness Jani Nikula
  2014-05-20 19:00 ` [RFC PATCH 1/2] drm/i915: shuffle panel code Jesse Barnes
  0 siblings, 2 replies; 14+ messages in thread
From: Jani Nikula @ 2014-04-29 20:30 UTC (permalink / raw
  To: intel-gfx; +Cc: jani.nikula, Ben Widawsky

Somehow a few functions have been dropped in the middle of backlight
code. Move them around. No functional changes.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_panel.c | 150 ++++++++++++++++++-------------------
 1 file changed, 75 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 44ad415e3706..776249bab488 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -42,6 +42,59 @@ intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 }
 
+/**
+ * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
+ * @dev: drm device
+ * @fixed_mode : panel native mode
+ * @connector: LVDS/eDP connector
+ *
+ * Return downclock_avail
+ * Find the reduced downclock for LVDS/eDP in EDID.
+ */
+struct drm_display_mode *
+intel_find_panel_downclock(struct drm_device *dev,
+			struct drm_display_mode *fixed_mode,
+			struct drm_connector *connector)
+{
+	struct drm_display_mode *scan, *tmp_mode;
+	int temp_downclock;
+
+	temp_downclock = fixed_mode->clock;
+	tmp_mode = NULL;
+
+	list_for_each_entry(scan, &connector->probed_modes, head) {
+		/*
+		 * If one mode has the same resolution with the fixed_panel
+		 * mode while they have the different refresh rate, it means
+		 * that the reduced downclock is found. In such
+		 * case we can set the different FPx0/1 to dynamically select
+		 * between low and high frequency.
+		 */
+		if (scan->hdisplay == fixed_mode->hdisplay &&
+		    scan->hsync_start == fixed_mode->hsync_start &&
+		    scan->hsync_end == fixed_mode->hsync_end &&
+		    scan->htotal == fixed_mode->htotal &&
+		    scan->vdisplay == fixed_mode->vdisplay &&
+		    scan->vsync_start == fixed_mode->vsync_start &&
+		    scan->vsync_end == fixed_mode->vsync_end &&
+		    scan->vtotal == fixed_mode->vtotal) {
+			if (scan->clock < temp_downclock) {
+				/*
+				 * The downclock is already found. But we
+				 * expect to find the lower downclock.
+				 */
+				temp_downclock = scan->clock;
+				tmp_mode = scan;
+			}
+		}
+	}
+
+	if (temp_downclock < fixed_mode->clock)
+		return drm_mode_duplicate(dev, tmp_mode);
+	else
+		return NULL;
+}
+
 /* adjusted_mode has been preset to be the panel's fixed mode */
 void
 intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
@@ -323,6 +376,28 @@ out:
 	pipe_config->gmch_pfit.lvds_border_bits = border;
 }
 
+enum drm_connector_status
+intel_panel_detect(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* Assume that the BIOS does not lie through the OpRegion... */
+	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
+		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
+			connector_status_connected :
+			connector_status_disconnected;
+	}
+
+	switch (i915.panel_ignore_lid) {
+	case -2:
+		return connector_status_connected;
+	case -1:
+		return connector_status_disconnected;
+	default:
+		return connector_status_unknown;
+	}
+}
+
 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
 					  u32 val)
 {
@@ -795,28 +870,6 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
 	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 }
 
-enum drm_connector_status
-intel_panel_detect(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	/* Assume that the BIOS does not lie through the OpRegion... */
-	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
-		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
-			connector_status_connected :
-			connector_status_disconnected;
-	}
-
-	switch (i915.panel_ignore_lid) {
-	case -2:
-		return connector_status_connected;
-	case -1:
-		return connector_status_disconnected;
-	default:
-		return connector_status_unknown;
-	}
-}
-
 #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
 static int intel_backlight_device_update_status(struct backlight_device *bd)
 {
@@ -1103,59 +1156,6 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
 	intel_backlight_device_unregister(intel_connector);
 }
 
-/**
- * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
- * @dev: drm device
- * @fixed_mode : panel native mode
- * @connector: LVDS/eDP connector
- *
- * Return downclock_avail
- * Find the reduced downclock for LVDS/eDP in EDID.
- */
-struct drm_display_mode *
-intel_find_panel_downclock(struct drm_device *dev,
-			struct drm_display_mode *fixed_mode,
-			struct drm_connector *connector)
-{
-	struct drm_display_mode *scan, *tmp_mode;
-	int temp_downclock;
-
-	temp_downclock = fixed_mode->clock;
-	tmp_mode = NULL;
-
-	list_for_each_entry(scan, &connector->probed_modes, head) {
-		/*
-		 * If one mode has the same resolution with the fixed_panel
-		 * mode while they have the different refresh rate, it means
-		 * that the reduced downclock is found. In such
-		 * case we can set the different FPx0/1 to dynamically select
-		 * between low and high frequency.
-		 */
-		if (scan->hdisplay == fixed_mode->hdisplay &&
-		    scan->hsync_start == fixed_mode->hsync_start &&
-		    scan->hsync_end == fixed_mode->hsync_end &&
-		    scan->htotal == fixed_mode->htotal &&
-		    scan->vdisplay == fixed_mode->vdisplay &&
-		    scan->vsync_start == fixed_mode->vsync_start &&
-		    scan->vsync_end == fixed_mode->vsync_end &&
-		    scan->vtotal == fixed_mode->vtotal) {
-			if (scan->clock < temp_downclock) {
-				/*
-				 * The downclock is already found. But we
-				 * expect to find the lower downclock.
-				 */
-				temp_downclock = scan->clock;
-				tmp_mode = scan;
-			}
-		}
-	}
-
-	if (temp_downclock < fixed_mode->clock)
-		return drm_mode_duplicate(dev, tmp_mode);
-	else
-		return NULL;
-}
-
 /* Set up chip specific backlight functions */
 void intel_panel_init_backlight_funcs(struct drm_device *dev)
 {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-04-29 20:30 [RFC PATCH 1/2] drm/i915: shuffle panel code Jani Nikula
@ 2014-04-29 20:30 ` Jani Nikula
  2014-04-29 20:37   ` Jani Nikula
                     ` (2 more replies)
  2014-05-20 19:00 ` [RFC PATCH 1/2] drm/i915: shuffle panel code Jesse Barnes
  1 sibling, 3 replies; 14+ messages in thread
From: Jani Nikula @ 2014-04-29 20:30 UTC (permalink / raw
  To: intel-gfx; +Cc: jani.nikula, Ben Widawsky

Historically we've exposed the full backlight PWM duty cycle range to
the userspace, in the name of "mechanism, not policy". However, it turns
out there are both panels and board designs where there is a minimum
duty cycle that is required for proper operation. The minimum duty cycle
is available in the VBT.

The backlight class sysfs interface does not make any promises to the
userspace about the physical meaning of the range
0..max_brightness. Specifically there is no guarantee that 0 means off;
indeed for acpi_backlight 0 usually is not off, but the minimum
acceptable value.

Respect the minimum backlight, and expose the range acceptable to the
hardware as 0..max_brightness to the userspace via the backlight class
device; 0 means the minimum acceptable enabled value. To switch off the
backlight, the user must disable the encoder.

As a side effect, make the backlight class device max brightness and
physical PWM modulation frequency (i.e. max duty cycle) independent.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>

---

UNTESTED!
---
 drivers/gpu/drm/i915/i915_drv.h    |  1 +
 drivers/gpu/drm/i915/intel_bios.c  |  3 +-
 drivers/gpu/drm/i915/intel_drv.h   |  1 +
 drivers/gpu/drm/i915/intel_panel.c | 97 +++++++++++++++++++++++++++++++-------
 4 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 50dfc3a1a9d1..d9dad3498b87 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1164,6 +1164,7 @@ struct intel_vbt_data {
 		u16 pwm_freq_hz;
 		bool present;
 		bool active_low_pwm;
+		u8 min_brightness;	/* min_brightness/255 of max */
 	} backlight;
 
 	/* MIPI DSI */
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 2945f57c53ee..1a3e172029b3 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -339,11 +339,12 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 
 	dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
 	dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
+	dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
 	DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
 		      "active %s, min brightness %u, level %u\n",
 		      dev_priv->vbt.backlight.pwm_freq_hz,
 		      dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
-		      entry->min_brightness,
+		      dev_priv->vbt.backlight.min_brightness,
 		      backlight_data->level[panel_type]);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d8b540b891d1..2af74dd03e31 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -165,6 +165,7 @@ struct intel_panel {
 	struct {
 		bool present;
 		u32 level;
+		u32 min;
 		u32 max;
 		bool enabled;
 		bool combination_mode;	/* gen 2/4 only */
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 776249bab488..360ae203aacb 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -398,6 +398,30 @@ intel_panel_detect(struct drm_device *dev)
 	}
 }
 
+/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
+static u32 scale_user_to_hw(struct intel_connector *connector,
+			    u32 user_level, u32 user_max)
+{
+	struct intel_panel *panel = &connector->panel;
+
+	user_level = clamp(user_level, 0U, user_max);
+
+	return panel->backlight.min + user_level *
+		(panel->backlight.max - panel->backlight.min) / user_max;
+}
+
+/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
+static u32 scale_hw_to_user(struct intel_connector *connector,
+			    u32 hw_level, u32 user_max)
+{
+	struct intel_panel *panel = &connector->panel;
+
+	hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
+
+	return (hw_level - panel->backlight.min) * user_max /
+		(panel->backlight.max - panel->backlight.min);
+}
+
 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
 					  u32 val)
 {
@@ -558,14 +582,14 @@ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
 }
 
 /* set backlight brightness to level in range [0..max] */
-void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
-			       u32 max)
+void intel_panel_set_backlight(struct intel_connector *connector,
+			       u32 user_level, u32 user_max)
 {
 	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 freq;
+	u32 hw_level;
 	unsigned long flags;
 
 	if (!panel->backlight.present || pipe == INVALID_PIPE)
@@ -575,19 +599,25 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 
 	WARN_ON(panel->backlight.max == 0);
 
-	/* scale to hardware max, but be careful to not overflow */
-	freq = panel->backlight.max;
-	if (freq < max)
-		level = level * freq / max;
-	else
-		level = freq / max * level;
+	hw_level = scale_user_to_hw(connector, user_level, user_max);
+	panel->backlight.level = hw_level;
 
-	panel->backlight.level = level;
-	if (panel->backlight.device)
-		panel->backlight.device->props.brightness = level;
+	if (panel->backlight.device) {
+		/*
+		 * Update backlight device brightness. In most cases, the
+		 * request comes from the backlight device sysfs, user_max ==
+		 * props.max_brightness, and this is redundant. However, this
+		 * serves to sync ACPI opregion backlight requests to the
+		 * backlight device.
+		 */
+		panel->backlight.device->props.brightness =
+			user_level *
+			panel->backlight.device->props.max_brightness /
+			user_max;
+	}
 
 	if (panel->backlight.enabled)
-		intel_panel_actually_set_backlight(connector, level);
+		intel_panel_actually_set_backlight(connector, hw_level);
 
 	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 }
@@ -861,7 +891,9 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
 		panel->backlight.level = panel->backlight.max;
 		if (panel->backlight.device)
 			panel->backlight.device->props.brightness =
-				panel->backlight.level;
+				scale_hw_to_user(connector,
+						 panel->backlight.level,
+						 panel->backlight.device->props.max_brightness);
 	}
 
 	dev_priv->display.enable_backlight(connector);
@@ -890,11 +922,15 @@ 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;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 hw_level;
 	int ret;
 
 	intel_runtime_pm_get(dev_priv);
 	mutex_lock(&dev->mode_config.mutex);
-	ret = intel_panel_get_backlight(connector);
+
+	hw_level = intel_panel_get_backlight(connector);
+	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
+
 	mutex_unlock(&dev->mode_config.mutex);
 	intel_runtime_pm_put(dev_priv);
 
@@ -918,8 +954,15 @@ static int intel_backlight_device_register(struct intel_connector *connector)
 
 	memset(&props, 0, sizeof(props));
 	props.type = BACKLIGHT_RAW;
-	props.brightness = panel->backlight.level;
+
+	/*
+	 * Note: Everything should work even if the backlight device max
+	 * presented to the userspace is arbitrarily chosen.
+	 */
 	props.max_brightness = panel->backlight.max;
+	props.brightness = scale_hw_to_user(connector,
+					    panel->backlight.level,
+					    props.max_brightness);
 
 	/*
 	 * Note: using the same name independent of the connector prevents
@@ -965,6 +1008,18 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
  * XXX: Query mode clock or hardware clock and program PWM modulation frequency
  * appropriately when it's 0. Use VBT and/or sane defaults.
  */
+static inline u32 get_backlight_min(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;
+
+	BUG_ON(panel->backlight.max == 0);
+
+	return dev_priv->vbt.backlight.min_brightness *
+		panel->backlight.max / 255;
+}
+
 static int bdw_setup_backlight(struct intel_connector *connector)
 {
 	struct drm_device *dev = connector->base.dev;
@@ -980,6 +1035,8 @@ static int bdw_setup_backlight(struct intel_connector *connector)
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min(connector);
+
 	val = bdw_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1004,6 +1061,8 @@ static int pch_setup_backlight(struct intel_connector *connector)
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min(connector);
+
 	val = pch_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1036,6 +1095,8 @@ static int i9xx_setup_backlight(struct intel_connector *connector)
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min(connector);
+
 	val = i9xx_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1063,6 +1124,8 @@ static int i965_setup_backlight(struct intel_connector *connector)
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min(connector);
+
 	val = i9xx_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1100,6 +1163,8 @@ static int vlv_setup_backlight(struct intel_connector *connector)
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min(connector);
+
 	val = _vlv_get_backlight(dev, PIPE_A);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-04-29 20:30 ` [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness Jani Nikula
@ 2014-04-29 20:37   ` Jani Nikula
  2014-05-20 19:08   ` Jesse Barnes
  2014-06-03 16:40   ` Stéphane Marchesin
  2 siblings, 0 replies; 14+ messages in thread
From: Jani Nikula @ 2014-04-29 20:37 UTC (permalink / raw
  To: intel-gfx; +Cc: Ben Widawsky

On Tue, 29 Apr 2014, Jani Nikula <jani.nikula@intel.com> wrote:
> Historically we've exposed the full backlight PWM duty cycle range to
> the userspace, in the name of "mechanism, not policy". However, it turns
> out there are both panels and board designs where there is a minimum
> duty cycle that is required for proper operation. The minimum duty cycle
> is available in the VBT.
>
> The backlight class sysfs interface does not make any promises to the
> userspace about the physical meaning of the range
> 0..max_brightness. Specifically there is no guarantee that 0 means off;
> indeed for acpi_backlight 0 usually is not off, but the minimum
> acceptable value.
>
> Respect the minimum backlight, and expose the range acceptable to the
> hardware as 0..max_brightness to the userspace via the backlight class
> device; 0 means the minimum acceptable enabled value. To switch off the
> backlight, the user must disable the encoder.
>
> As a side effect, make the backlight class device max brightness and
> physical PWM modulation frequency (i.e. max duty cycle) independent.
>
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>

Acknowledgement that I meant to include: this is based on both Jesse's
and Ben's earlier work.



>
> ---
>
> UNTESTED!
> ---
>  drivers/gpu/drm/i915/i915_drv.h    |  1 +
>  drivers/gpu/drm/i915/intel_bios.c  |  3 +-
>  drivers/gpu/drm/i915/intel_drv.h   |  1 +
>  drivers/gpu/drm/i915/intel_panel.c | 97 +++++++++++++++++++++++++++++++-------
>  4 files changed, 85 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 50dfc3a1a9d1..d9dad3498b87 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1164,6 +1164,7 @@ struct intel_vbt_data {
>  		u16 pwm_freq_hz;
>  		bool present;
>  		bool active_low_pwm;
> +		u8 min_brightness;	/* min_brightness/255 of max */
>  	} backlight;
>  
>  	/* MIPI DSI */
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 2945f57c53ee..1a3e172029b3 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -339,11 +339,12 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
>  
>  	dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
>  	dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
> +	dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
>  	DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
>  		      "active %s, min brightness %u, level %u\n",
>  		      dev_priv->vbt.backlight.pwm_freq_hz,
>  		      dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
> -		      entry->min_brightness,
> +		      dev_priv->vbt.backlight.min_brightness,
>  		      backlight_data->level[panel_type]);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d8b540b891d1..2af74dd03e31 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -165,6 +165,7 @@ struct intel_panel {
>  	struct {
>  		bool present;
>  		u32 level;
> +		u32 min;
>  		u32 max;
>  		bool enabled;
>  		bool combination_mode;	/* gen 2/4 only */
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 776249bab488..360ae203aacb 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -398,6 +398,30 @@ intel_panel_detect(struct drm_device *dev)
>  	}
>  }
>  
> +/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
> +static u32 scale_user_to_hw(struct intel_connector *connector,
> +			    u32 user_level, u32 user_max)
> +{
> +	struct intel_panel *panel = &connector->panel;
> +
> +	user_level = clamp(user_level, 0U, user_max);
> +
> +	return panel->backlight.min + user_level *
> +		(panel->backlight.max - panel->backlight.min) / user_max;
> +}
> +
> +/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
> +static u32 scale_hw_to_user(struct intel_connector *connector,
> +			    u32 hw_level, u32 user_max)
> +{
> +	struct intel_panel *panel = &connector->panel;
> +
> +	hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
> +
> +	return (hw_level - panel->backlight.min) * user_max /
> +		(panel->backlight.max - panel->backlight.min);
> +}
> +
>  static u32 intel_panel_compute_brightness(struct intel_connector *connector,
>  					  u32 val)
>  {
> @@ -558,14 +582,14 @@ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
>  }
>  
>  /* set backlight brightness to level in range [0..max] */
> -void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
> -			       u32 max)
> +void intel_panel_set_backlight(struct intel_connector *connector,
> +			       u32 user_level, u32 user_max)
>  {
>  	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 freq;
> +	u32 hw_level;
>  	unsigned long flags;
>  
>  	if (!panel->backlight.present || pipe == INVALID_PIPE)
> @@ -575,19 +599,25 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
>  
>  	WARN_ON(panel->backlight.max == 0);
>  
> -	/* scale to hardware max, but be careful to not overflow */
> -	freq = panel->backlight.max;
> -	if (freq < max)
> -		level = level * freq / max;
> -	else
> -		level = freq / max * level;
> +	hw_level = scale_user_to_hw(connector, user_level, user_max);
> +	panel->backlight.level = hw_level;
>  
> -	panel->backlight.level = level;
> -	if (panel->backlight.device)
> -		panel->backlight.device->props.brightness = level;
> +	if (panel->backlight.device) {
> +		/*
> +		 * Update backlight device brightness. In most cases, the
> +		 * request comes from the backlight device sysfs, user_max ==
> +		 * props.max_brightness, and this is redundant. However, this
> +		 * serves to sync ACPI opregion backlight requests to the
> +		 * backlight device.
> +		 */
> +		panel->backlight.device->props.brightness =
> +			user_level *
> +			panel->backlight.device->props.max_brightness /
> +			user_max;
> +	}
>  
>  	if (panel->backlight.enabled)
> -		intel_panel_actually_set_backlight(connector, level);
> +		intel_panel_actually_set_backlight(connector, hw_level);
>  
>  	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
>  }
> @@ -861,7 +891,9 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
>  		panel->backlight.level = panel->backlight.max;
>  		if (panel->backlight.device)
>  			panel->backlight.device->props.brightness =
> -				panel->backlight.level;
> +				scale_hw_to_user(connector,
> +						 panel->backlight.level,
> +						 panel->backlight.device->props.max_brightness);
>  	}
>  
>  	dev_priv->display.enable_backlight(connector);
> @@ -890,11 +922,15 @@ 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;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 hw_level;
>  	int ret;
>  
>  	intel_runtime_pm_get(dev_priv);
>  	mutex_lock(&dev->mode_config.mutex);
> -	ret = intel_panel_get_backlight(connector);
> +
> +	hw_level = intel_panel_get_backlight(connector);
> +	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
> +
>  	mutex_unlock(&dev->mode_config.mutex);
>  	intel_runtime_pm_put(dev_priv);
>  
> @@ -918,8 +954,15 @@ static int intel_backlight_device_register(struct intel_connector *connector)
>  
>  	memset(&props, 0, sizeof(props));
>  	props.type = BACKLIGHT_RAW;
> -	props.brightness = panel->backlight.level;
> +
> +	/*
> +	 * Note: Everything should work even if the backlight device max
> +	 * presented to the userspace is arbitrarily chosen.
> +	 */
>  	props.max_brightness = panel->backlight.max;
> +	props.brightness = scale_hw_to_user(connector,
> +					    panel->backlight.level,
> +					    props.max_brightness);
>  
>  	/*
>  	 * Note: using the same name independent of the connector prevents
> @@ -965,6 +1008,18 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
>   * XXX: Query mode clock or hardware clock and program PWM modulation frequency
>   * appropriately when it's 0. Use VBT and/or sane defaults.
>   */
> +static inline u32 get_backlight_min(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;
> +
> +	BUG_ON(panel->backlight.max == 0);
> +
> +	return dev_priv->vbt.backlight.min_brightness *
> +		panel->backlight.max / 255;
> +}
> +
>  static int bdw_setup_backlight(struct intel_connector *connector)
>  {
>  	struct drm_device *dev = connector->base.dev;
> @@ -980,6 +1035,8 @@ static int bdw_setup_backlight(struct intel_connector *connector)
>  	if (!panel->backlight.max)
>  		return -ENODEV;
>  
> +	panel->backlight.min = get_backlight_min(connector);
> +
>  	val = bdw_get_backlight(connector);
>  	panel->backlight.level = intel_panel_compute_brightness(connector, val);
>  
> @@ -1004,6 +1061,8 @@ static int pch_setup_backlight(struct intel_connector *connector)
>  	if (!panel->backlight.max)
>  		return -ENODEV;
>  
> +	panel->backlight.min = get_backlight_min(connector);
> +
>  	val = pch_get_backlight(connector);
>  	panel->backlight.level = intel_panel_compute_brightness(connector, val);
>  
> @@ -1036,6 +1095,8 @@ static int i9xx_setup_backlight(struct intel_connector *connector)
>  	if (!panel->backlight.max)
>  		return -ENODEV;
>  
> +	panel->backlight.min = get_backlight_min(connector);
> +
>  	val = i9xx_get_backlight(connector);
>  	panel->backlight.level = intel_panel_compute_brightness(connector, val);
>  
> @@ -1063,6 +1124,8 @@ static int i965_setup_backlight(struct intel_connector *connector)
>  	if (!panel->backlight.max)
>  		return -ENODEV;
>  
> +	panel->backlight.min = get_backlight_min(connector);
> +
>  	val = i9xx_get_backlight(connector);
>  	panel->backlight.level = intel_panel_compute_brightness(connector, val);
>  
> @@ -1100,6 +1163,8 @@ static int vlv_setup_backlight(struct intel_connector *connector)
>  	if (!panel->backlight.max)
>  		return -ENODEV;
>  
> +	panel->backlight.min = get_backlight_min(connector);
> +
>  	val = _vlv_get_backlight(dev, PIPE_A);
>  	panel->backlight.level = intel_panel_compute_brightness(connector, val);
>  
> -- 
> 1.9.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 1/2] drm/i915: shuffle panel code
  2014-04-29 20:30 [RFC PATCH 1/2] drm/i915: shuffle panel code Jani Nikula
  2014-04-29 20:30 ` [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness Jani Nikula
@ 2014-05-20 19:00 ` Jesse Barnes
  2014-05-20 19:08   ` Daniel Vetter
  1 sibling, 1 reply; 14+ messages in thread
From: Jesse Barnes @ 2014-05-20 19:00 UTC (permalink / raw
  To: Jani Nikula; +Cc: intel-gfx, Ben Widawsky

On Tue, 29 Apr 2014 23:30:48 +0300
Jani Nikula <jani.nikula@intel.com> wrote:

> Somehow a few functions have been dropped in the middle of backlight
> code. Move them around. No functional changes.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_panel.c | 150 ++++++++++++++++++-------------------
>  1 file changed, 75 insertions(+), 75 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 44ad415e3706..776249bab488 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -42,6 +42,59 @@ intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
>  	drm_mode_set_crtcinfo(adjusted_mode, 0);
>  }
>  
> +/**
> + * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
> + * @dev: drm device
> + * @fixed_mode : panel native mode
> + * @connector: LVDS/eDP connector
> + *
> + * Return downclock_avail
> + * Find the reduced downclock for LVDS/eDP in EDID.
> + */
> +struct drm_display_mode *
> +intel_find_panel_downclock(struct drm_device *dev,
> +			struct drm_display_mode *fixed_mode,
> +			struct drm_connector *connector)
> +{
> +	struct drm_display_mode *scan, *tmp_mode;
> +	int temp_downclock;
> +
> +	temp_downclock = fixed_mode->clock;
> +	tmp_mode = NULL;
> +
> +	list_for_each_entry(scan, &connector->probed_modes, head) {
> +		/*
> +		 * If one mode has the same resolution with the fixed_panel
> +		 * mode while they have the different refresh rate, it means
> +		 * that the reduced downclock is found. In such
> +		 * case we can set the different FPx0/1 to dynamically select
> +		 * between low and high frequency.
> +		 */
> +		if (scan->hdisplay == fixed_mode->hdisplay &&
> +		    scan->hsync_start == fixed_mode->hsync_start &&
> +		    scan->hsync_end == fixed_mode->hsync_end &&
> +		    scan->htotal == fixed_mode->htotal &&
> +		    scan->vdisplay == fixed_mode->vdisplay &&
> +		    scan->vsync_start == fixed_mode->vsync_start &&
> +		    scan->vsync_end == fixed_mode->vsync_end &&
> +		    scan->vtotal == fixed_mode->vtotal) {
> +			if (scan->clock < temp_downclock) {
> +				/*
> +				 * The downclock is already found. But we
> +				 * expect to find the lower downclock.
> +				 */
> +				temp_downclock = scan->clock;
> +				tmp_mode = scan;
> +			}
> +		}
> +	}
> +
> +	if (temp_downclock < fixed_mode->clock)
> +		return drm_mode_duplicate(dev, tmp_mode);
> +	else
> +		return NULL;
> +}
> +
>  /* adjusted_mode has been preset to be the panel's fixed mode */
>  void
>  intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
> @@ -323,6 +376,28 @@ out:
>  	pipe_config->gmch_pfit.lvds_border_bits = border;
>  }
>  
> +enum drm_connector_status
> +intel_panel_detect(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	/* Assume that the BIOS does not lie through the OpRegion... */
> +	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
> +		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
> +			connector_status_connected :
> +			connector_status_disconnected;
> +	}
> +
> +	switch (i915.panel_ignore_lid) {
> +	case -2:
> +		return connector_status_connected;
> +	case -1:
> +		return connector_status_disconnected;
> +	default:
> +		return connector_status_unknown;
> +	}
> +}
> +
>  static u32 intel_panel_compute_brightness(struct intel_connector *connector,
>  					  u32 val)
>  {
> @@ -795,28 +870,6 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
>  	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
>  }
>  
> -enum drm_connector_status
> -intel_panel_detect(struct drm_device *dev)
> -{
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
> -	/* Assume that the BIOS does not lie through the OpRegion... */
> -	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
> -		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
> -			connector_status_connected :
> -			connector_status_disconnected;
> -	}
> -
> -	switch (i915.panel_ignore_lid) {
> -	case -2:
> -		return connector_status_connected;
> -	case -1:
> -		return connector_status_disconnected;
> -	default:
> -		return connector_status_unknown;
> -	}
> -}
> -
>  #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
>  static int intel_backlight_device_update_status(struct backlight_device *bd)
>  {
> @@ -1103,59 +1156,6 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
>  	intel_backlight_device_unregister(intel_connector);
>  }
>  
> -/**
> - * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
> - * @dev: drm device
> - * @fixed_mode : panel native mode
> - * @connector: LVDS/eDP connector
> - *
> - * Return downclock_avail
> - * Find the reduced downclock for LVDS/eDP in EDID.
> - */
> -struct drm_display_mode *
> -intel_find_panel_downclock(struct drm_device *dev,
> -			struct drm_display_mode *fixed_mode,
> -			struct drm_connector *connector)
> -{
> -	struct drm_display_mode *scan, *tmp_mode;
> -	int temp_downclock;
> -
> -	temp_downclock = fixed_mode->clock;
> -	tmp_mode = NULL;
> -
> -	list_for_each_entry(scan, &connector->probed_modes, head) {
> -		/*
> -		 * If one mode has the same resolution with the fixed_panel
> -		 * mode while they have the different refresh rate, it means
> -		 * that the reduced downclock is found. In such
> -		 * case we can set the different FPx0/1 to dynamically select
> -		 * between low and high frequency.
> -		 */
> -		if (scan->hdisplay == fixed_mode->hdisplay &&
> -		    scan->hsync_start == fixed_mode->hsync_start &&
> -		    scan->hsync_end == fixed_mode->hsync_end &&
> -		    scan->htotal == fixed_mode->htotal &&
> -		    scan->vdisplay == fixed_mode->vdisplay &&
> -		    scan->vsync_start == fixed_mode->vsync_start &&
> -		    scan->vsync_end == fixed_mode->vsync_end &&
> -		    scan->vtotal == fixed_mode->vtotal) {
> -			if (scan->clock < temp_downclock) {
> -				/*
> -				 * The downclock is already found. But we
> -				 * expect to find the lower downclock.
> -				 */
> -				temp_downclock = scan->clock;
> -				tmp_mode = scan;
> -			}
> -		}
> -	}
> -
> -	if (temp_downclock < fixed_mode->clock)
> -		return drm_mode_duplicate(dev, tmp_mode);
> -	else
> -		return NULL;
> -}
> -
>  /* Set up chip specific backlight functions */
>  void intel_panel_init_backlight_funcs(struct drm_device *dev)
>  {

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-04-29 20:30 ` [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness Jani Nikula
  2014-04-29 20:37   ` Jani Nikula
@ 2014-05-20 19:08   ` Jesse Barnes
  2014-06-06 13:40     ` Jani Nikula
  2014-06-03 16:40   ` Stéphane Marchesin
  2 siblings, 1 reply; 14+ messages in thread
From: Jesse Barnes @ 2014-05-20 19:08 UTC (permalink / raw
  To: Jani Nikula; +Cc: intel-gfx, Ben Widawsky

On Tue, 29 Apr 2014 23:30:49 +0300
Jani Nikula <jani.nikula@intel.com> wrote:

> Historically we've exposed the full backlight PWM duty cycle range to
> the userspace, in the name of "mechanism, not policy". However, it turns
> out there are both panels and board designs where there is a minimum
> duty cycle that is required for proper operation. The minimum duty cycle
> is available in the VBT.
> 
> The backlight class sysfs interface does not make any promises to the
> userspace about the physical meaning of the range
> 0..max_brightness. Specifically there is no guarantee that 0 means off;
> indeed for acpi_backlight 0 usually is not off, but the minimum
> acceptable value.
> 
> Respect the minimum backlight, and expose the range acceptable to the
> hardware as 0..max_brightness to the userspace via the backlight class
> device; 0 means the minimum acceptable enabled value. To switch off the
> backlight, the user must disable the encoder.
> 
> As a side effect, make the backlight class device max brightness and
> physical PWM modulation frequency (i.e. max duty cycle) independent.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>

I like the direction here... I wonder if we should always virtualize
the max too, and just always expose 0-2047 or something.

> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 50dfc3a1a9d1..d9dad3498b87 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1164,6 +1164,7 @@ struct intel_vbt_data {
>  		u16 pwm_freq_hz;
>  		bool present;
>  		bool active_low_pwm;
> +		u8 min_brightness;	/* min_brightness/255 of max */
>  	} backlight;
>  
>  	/* MIPI DSI */
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 2945f57c53ee..1a3e172029b3 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -339,11 +339,12 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
>  
>  	dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
>  	dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
> +	dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
>  	DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
>  		      "active %s, min brightness %u, level %u\n",
>  		      dev_priv->vbt.backlight.pwm_freq_hz,
>  		      dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
> -		      entry->min_brightness,
> +		      dev_priv->vbt.backlight.min_brightness,
>  		      backlight_data->level[panel_type]);
>  }

This should probably just be a standalone patch.  You can add my r-b
for that.

>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d8b540b891d1..2af74dd03e31 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -165,6 +165,7 @@ struct intel_panel {
>  	struct {
>  		bool present;
>  		u32 level;
> +		u32 min;
>  		u32 max;
>  		bool enabled;
>  		bool combination_mode;	/* gen 2/4 only */
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 776249bab488..360ae203aacb 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -398,6 +398,30 @@ intel_panel_detect(struct drm_device *dev)
>  	}
>  }
>  
> +/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
> +static u32 scale_user_to_hw(struct intel_connector *connector,
> +			    u32 user_level, u32 user_max)
> +{
> +	struct intel_panel *panel = &connector->panel;
> +
> +	user_level = clamp(user_level, 0U, user_max);
> +
> +	return panel->backlight.min + user_level *
> +		(panel->backlight.max - panel->backlight.min) / user_max;
> +}
> +
> +/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
> +static u32 scale_hw_to_user(struct intel_connector *connector,
> +			    u32 hw_level, u32 user_max)
> +{
> +	struct intel_panel *panel = &connector->panel;
> +
> +	hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
> +
> +	return (hw_level - panel->backlight.min) * user_max /
> +		(panel->backlight.max - panel->backlight.min);
> +}
> +
>  static u32 intel_panel_compute_brightness(struct intel_connector *connector,
>  					  u32 val)
>  {
> @@ -558,14 +582,14 @@ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
>  }
>  
>  /* set backlight brightness to level in range [0..max] */
> -void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
> -			       u32 max)
> +void intel_panel_set_backlight(struct intel_connector *connector,
> +			       u32 user_level, u32 user_max)
>  {
>  	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 freq;
> +	u32 hw_level;
>  	unsigned long flags;
>  
>  	if (!panel->backlight.present || pipe == INVALID_PIPE)
> @@ -575,19 +599,25 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
>  
>  	WARN_ON(panel->backlight.max == 0);
>  
> -	/* scale to hardware max, but be careful to not overflow */
> -	freq = panel->backlight.max;
> -	if (freq < max)
> -		level = level * freq / max;
> -	else
> -		level = freq / max * level;
> +	hw_level = scale_user_to_hw(connector, user_level, user_max);
> +	panel->backlight.level = hw_level;
>  
> -	panel->backlight.level = level;
> -	if (panel->backlight.device)
> -		panel->backlight.device->props.brightness = level;
> +	if (panel->backlight.device) {
> +		/*
> +		 * Update backlight device brightness. In most cases, the
> +		 * request comes from the backlight device sysfs, user_max ==
> +		 * props.max_brightness, and this is redundant. However, this
> +		 * serves to sync ACPI opregion backlight requests to the
> +		 * backlight device.
> +		 */
> +		panel->backlight.device->props.brightness =
> +			user_level *
> +			panel->backlight.device->props.max_brightness /
> +			user_max;
> +	}
>  
>  	if (panel->backlight.enabled)
> -		intel_panel_actually_set_backlight(connector, level);
> +		intel_panel_actually_set_backlight(connector, hw_level);
>  
>  	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
>  }
> @@ -861,7 +891,9 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
>  		panel->backlight.level = panel->backlight.max;
>  		if (panel->backlight.device)
>  			panel->backlight.device->props.brightness =
> -				panel->backlight.level;
> +				scale_hw_to_user(connector,
> +						 panel->backlight.level,
> +						 panel->backlight.device->props.max_brightness);
>  	}
>  
>  	dev_priv->display.enable_backlight(connector);
> @@ -890,11 +922,15 @@ 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;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 hw_level;
>  	int ret;
>  
>  	intel_runtime_pm_get(dev_priv);
>  	mutex_lock(&dev->mode_config.mutex);
> -	ret = intel_panel_get_backlight(connector);
> +
> +	hw_level = intel_panel_get_backlight(connector);
> +	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
> +
>  	mutex_unlock(&dev->mode_config.mutex);
>  	intel_runtime_pm_put(dev_priv);
>  
> @@ -918,8 +954,15 @@ static int intel_backlight_device_register(struct intel_connector *connector)
>  
>  	memset(&props, 0, sizeof(props));
>  	props.type = BACKLIGHT_RAW;
> -	props.brightness = panel->backlight.level;
> +
> +	/*
> +	 * Note: Everything should work even if the backlight device max
> +	 * presented to the userspace is arbitrarily chosen.
> +	 */
>  	props.max_brightness = panel->backlight.max;
> +	props.brightness = scale_hw_to_user(connector,
> +					    panel->backlight.level,
> +					    props.max_brightness);
>  
>  	/*
>  	 * Note: using the same name independent of the connector prevents
> @@ -965,6 +1008,18 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
>   * XXX: Query mode clock or hardware clock and program PWM modulation frequency
>   * appropriately when it's 0. Use VBT and/or sane defaults.
>   */
> +static inline u32 get_backlight_min(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;
> +
> +	BUG_ON(panel->backlight.max == 0);
> +
> +	return dev_priv->vbt.backlight.min_brightness *
> +		panel->backlight.max / 255;
> +}

Is this the user version or the hw version?  If hw, why not just use
min_brightness directly?

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 1/2] drm/i915: shuffle panel code
  2014-05-20 19:00 ` [RFC PATCH 1/2] drm/i915: shuffle panel code Jesse Barnes
@ 2014-05-20 19:08   ` Daniel Vetter
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Vetter @ 2014-05-20 19:08 UTC (permalink / raw
  To: Jesse Barnes; +Cc: Jani Nikula, intel-gfx, Ben Widawsky

On Tue, May 20, 2014 at 12:00:27PM -0700, Jesse Barnes wrote:
> On Tue, 29 Apr 2014 23:30:48 +0300
> Jani Nikula <jani.nikula@intel.com> wrote:
> 
> > Somehow a few functions have been dropped in the middle of backlight
> > code. Move them around. No functional changes.
> > 
> > Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_panel.c | 150 ++++++++++++++++++-------------------
> >  1 file changed, 75 insertions(+), 75 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > index 44ad415e3706..776249bab488 100644
> > --- a/drivers/gpu/drm/i915/intel_panel.c
> > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > @@ -42,6 +42,59 @@ intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
> >  	drm_mode_set_crtcinfo(adjusted_mode, 0);
> >  }
> >  
> > +/**
> > + * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
> > + * @dev: drm device
> > + * @fixed_mode : panel native mode
> > + * @connector: LVDS/eDP connector
> > + *
> > + * Return downclock_avail
> > + * Find the reduced downclock for LVDS/eDP in EDID.
> > + */
> > +struct drm_display_mode *
> > +intel_find_panel_downclock(struct drm_device *dev,
> > +			struct drm_display_mode *fixed_mode,
> > +			struct drm_connector *connector)
> > +{
> > +	struct drm_display_mode *scan, *tmp_mode;
> > +	int temp_downclock;
> > +
> > +	temp_downclock = fixed_mode->clock;
> > +	tmp_mode = NULL;
> > +
> > +	list_for_each_entry(scan, &connector->probed_modes, head) {
> > +		/*
> > +		 * If one mode has the same resolution with the fixed_panel
> > +		 * mode while they have the different refresh rate, it means
> > +		 * that the reduced downclock is found. In such
> > +		 * case we can set the different FPx0/1 to dynamically select
> > +		 * between low and high frequency.
> > +		 */
> > +		if (scan->hdisplay == fixed_mode->hdisplay &&
> > +		    scan->hsync_start == fixed_mode->hsync_start &&
> > +		    scan->hsync_end == fixed_mode->hsync_end &&
> > +		    scan->htotal == fixed_mode->htotal &&
> > +		    scan->vdisplay == fixed_mode->vdisplay &&
> > +		    scan->vsync_start == fixed_mode->vsync_start &&
> > +		    scan->vsync_end == fixed_mode->vsync_end &&
> > +		    scan->vtotal == fixed_mode->vtotal) {
> > +			if (scan->clock < temp_downclock) {
> > +				/*
> > +				 * The downclock is already found. But we
> > +				 * expect to find the lower downclock.
> > +				 */
> > +				temp_downclock = scan->clock;
> > +				tmp_mode = scan;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (temp_downclock < fixed_mode->clock)
> > +		return drm_mode_duplicate(dev, tmp_mode);
> > +	else
> > +		return NULL;
> > +}
> > +
> >  /* adjusted_mode has been preset to be the panel's fixed mode */
> >  void
> >  intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
> > @@ -323,6 +376,28 @@ out:
> >  	pipe_config->gmch_pfit.lvds_border_bits = border;
> >  }
> >  
> > +enum drm_connector_status
> > +intel_panel_detect(struct drm_device *dev)
> > +{
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +
> > +	/* Assume that the BIOS does not lie through the OpRegion... */
> > +	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
> > +		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
> > +			connector_status_connected :
> > +			connector_status_disconnected;
> > +	}
> > +
> > +	switch (i915.panel_ignore_lid) {
> > +	case -2:
> > +		return connector_status_connected;
> > +	case -1:
> > +		return connector_status_disconnected;
> > +	default:
> > +		return connector_status_unknown;
> > +	}
> > +}
> > +
> >  static u32 intel_panel_compute_brightness(struct intel_connector *connector,
> >  					  u32 val)
> >  {
> > @@ -795,28 +870,6 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
> >  	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
> >  }
> >  
> > -enum drm_connector_status
> > -intel_panel_detect(struct drm_device *dev)
> > -{
> > -	struct drm_i915_private *dev_priv = dev->dev_private;
> > -
> > -	/* Assume that the BIOS does not lie through the OpRegion... */
> > -	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
> > -		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
> > -			connector_status_connected :
> > -			connector_status_disconnected;
> > -	}
> > -
> > -	switch (i915.panel_ignore_lid) {
> > -	case -2:
> > -		return connector_status_connected;
> > -	case -1:
> > -		return connector_status_disconnected;
> > -	default:
> > -		return connector_status_unknown;
> > -	}
> > -}
> > -
> >  #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
> >  static int intel_backlight_device_update_status(struct backlight_device *bd)
> >  {
> > @@ -1103,59 +1156,6 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
> >  	intel_backlight_device_unregister(intel_connector);
> >  }
> >  
> > -/**
> > - * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
> > - * @dev: drm device
> > - * @fixed_mode : panel native mode
> > - * @connector: LVDS/eDP connector
> > - *
> > - * Return downclock_avail
> > - * Find the reduced downclock for LVDS/eDP in EDID.
> > - */
> > -struct drm_display_mode *
> > -intel_find_panel_downclock(struct drm_device *dev,
> > -			struct drm_display_mode *fixed_mode,
> > -			struct drm_connector *connector)
> > -{
> > -	struct drm_display_mode *scan, *tmp_mode;
> > -	int temp_downclock;
> > -
> > -	temp_downclock = fixed_mode->clock;
> > -	tmp_mode = NULL;
> > -
> > -	list_for_each_entry(scan, &connector->probed_modes, head) {
> > -		/*
> > -		 * If one mode has the same resolution with the fixed_panel
> > -		 * mode while they have the different refresh rate, it means
> > -		 * that the reduced downclock is found. In such
> > -		 * case we can set the different FPx0/1 to dynamically select
> > -		 * between low and high frequency.
> > -		 */
> > -		if (scan->hdisplay == fixed_mode->hdisplay &&
> > -		    scan->hsync_start == fixed_mode->hsync_start &&
> > -		    scan->hsync_end == fixed_mode->hsync_end &&
> > -		    scan->htotal == fixed_mode->htotal &&
> > -		    scan->vdisplay == fixed_mode->vdisplay &&
> > -		    scan->vsync_start == fixed_mode->vsync_start &&
> > -		    scan->vsync_end == fixed_mode->vsync_end &&
> > -		    scan->vtotal == fixed_mode->vtotal) {
> > -			if (scan->clock < temp_downclock) {
> > -				/*
> > -				 * The downclock is already found. But we
> > -				 * expect to find the lower downclock.
> > -				 */
> > -				temp_downclock = scan->clock;
> > -				tmp_mode = scan;
> > -			}
> > -		}
> > -	}
> > -
> > -	if (temp_downclock < fixed_mode->clock)
> > -		return drm_mode_duplicate(dev, tmp_mode);
> > -	else
> > -		return NULL;
> > -}
> > -
> >  /* Set up chip specific backlight functions */
> >  void intel_panel_init_backlight_funcs(struct drm_device *dev)
> >  {
> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Queued for -next, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-04-29 20:30 ` [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness Jani Nikula
  2014-04-29 20:37   ` Jani Nikula
  2014-05-20 19:08   ` Jesse Barnes
@ 2014-06-03 16:40   ` Stéphane Marchesin
  2014-06-03 20:26     ` Daniel Vetter
  2 siblings, 1 reply; 14+ messages in thread
From: Stéphane Marchesin @ 2014-06-03 16:40 UTC (permalink / raw
  To: Jani Nikula; +Cc: intel-gfx, Ben Widawsky

On Tue, Apr 29, 2014 at 1:30 PM, Jani Nikula <jani.nikula@intel.com> wrote:
> Historically we've exposed the full backlight PWM duty cycle range to
> the userspace, in the name of "mechanism, not policy". However, it turns
> out there are both panels and board designs where there is a minimum
> duty cycle that is required for proper operation. The minimum duty cycle
> is available in the VBT.
>
> The backlight class sysfs interface does not make any promises to the
> userspace about the physical meaning of the range
> 0..max_brightness. Specifically there is no guarantee that 0 means off;
> indeed for acpi_backlight 0 usually is not off, but the minimum
> acceptable value.

This is the part we've been relying on in Chrome OS (we assume that 0
means off). It seems to me that i915 would be the first, or one of the
first drivers to violate this rule (in particular you can find a lot
of backlight drivers trying hard to ensure that 0 means off in the
backlight drivers directory).

For context, we use backlight = 0 as a quick "turn the panel off"
function where possible. This allows us to avoid the panel off delay
where possible. Breaking this assumption means that we'd pay the panel
off delay penalty everywhere, not just with BYT.

Stéphane

>
> Respect the minimum backlight, and expose the range acceptable to the
> hardware as 0..max_brightness to the userspace via the backlight class
> device; 0 means the minimum acceptable enabled value. To switch off the
> backlight, the user must disable the encoder.
>
> As a side effect, make the backlight class device max brightness and
> physical PWM modulation frequency (i.e. max duty cycle) independent.
>
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>
> ---
>
> UNTESTED!
> ---
>  drivers/gpu/drm/i915/i915_drv.h    |  1 +
>  drivers/gpu/drm/i915/intel_bios.c  |  3 +-
>  drivers/gpu/drm/i915/intel_drv.h   |  1 +
>  drivers/gpu/drm/i915/intel_panel.c | 97 +++++++++++++++++++++++++++++++-------
>  4 files changed, 85 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 50dfc3a1a9d1..d9dad3498b87 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1164,6 +1164,7 @@ struct intel_vbt_data {
>                 u16 pwm_freq_hz;
>                 bool present;
>                 bool active_low_pwm;
> +               u8 min_brightness;      /* min_brightness/255 of max */
>         } backlight;
>
>         /* MIPI DSI */
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 2945f57c53ee..1a3e172029b3 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -339,11 +339,12 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
>
>         dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
>         dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
> +       dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
>         DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
>                       "active %s, min brightness %u, level %u\n",
>                       dev_priv->vbt.backlight.pwm_freq_hz,
>                       dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
> -                     entry->min_brightness,
> +                     dev_priv->vbt.backlight.min_brightness,
>                       backlight_data->level[panel_type]);
>  }
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d8b540b891d1..2af74dd03e31 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -165,6 +165,7 @@ struct intel_panel {
>         struct {
>                 bool present;
>                 u32 level;
> +               u32 min;
>                 u32 max;
>                 bool enabled;
>                 bool combination_mode;  /* gen 2/4 only */
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 776249bab488..360ae203aacb 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -398,6 +398,30 @@ intel_panel_detect(struct drm_device *dev)
>         }
>  }
>
> +/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
> +static u32 scale_user_to_hw(struct intel_connector *connector,
> +                           u32 user_level, u32 user_max)
> +{
> +       struct intel_panel *panel = &connector->panel;
> +
> +       user_level = clamp(user_level, 0U, user_max);
> +
> +       return panel->backlight.min + user_level *
> +               (panel->backlight.max - panel->backlight.min) / user_max;
> +}
> +
> +/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
> +static u32 scale_hw_to_user(struct intel_connector *connector,
> +                           u32 hw_level, u32 user_max)
> +{
> +       struct intel_panel *panel = &connector->panel;
> +
> +       hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
> +
> +       return (hw_level - panel->backlight.min) * user_max /
> +               (panel->backlight.max - panel->backlight.min);
> +}
> +
>  static u32 intel_panel_compute_brightness(struct intel_connector *connector,
>                                           u32 val)
>  {
> @@ -558,14 +582,14 @@ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
>  }
>
>  /* set backlight brightness to level in range [0..max] */
> -void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
> -                              u32 max)
> +void intel_panel_set_backlight(struct intel_connector *connector,
> +                              u32 user_level, u32 user_max)
>  {
>         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 freq;
> +       u32 hw_level;
>         unsigned long flags;
>
>         if (!panel->backlight.present || pipe == INVALID_PIPE)
> @@ -575,19 +599,25 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
>
>         WARN_ON(panel->backlight.max == 0);
>
> -       /* scale to hardware max, but be careful to not overflow */
> -       freq = panel->backlight.max;
> -       if (freq < max)
> -               level = level * freq / max;
> -       else
> -               level = freq / max * level;
> +       hw_level = scale_user_to_hw(connector, user_level, user_max);
> +       panel->backlight.level = hw_level;
>
> -       panel->backlight.level = level;
> -       if (panel->backlight.device)
> -               panel->backlight.device->props.brightness = level;
> +       if (panel->backlight.device) {
> +               /*
> +                * Update backlight device brightness. In most cases, the
> +                * request comes from the backlight device sysfs, user_max ==
> +                * props.max_brightness, and this is redundant. However, this
> +                * serves to sync ACPI opregion backlight requests to the
> +                * backlight device.
> +                */
> +               panel->backlight.device->props.brightness =
> +                       user_level *
> +                       panel->backlight.device->props.max_brightness /
> +                       user_max;
> +       }
>
>         if (panel->backlight.enabled)
> -               intel_panel_actually_set_backlight(connector, level);
> +               intel_panel_actually_set_backlight(connector, hw_level);
>
>         spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
>  }
> @@ -861,7 +891,9 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
>                 panel->backlight.level = panel->backlight.max;
>                 if (panel->backlight.device)
>                         panel->backlight.device->props.brightness =
> -                               panel->backlight.level;
> +                               scale_hw_to_user(connector,
> +                                                panel->backlight.level,
> +                                                panel->backlight.device->props.max_brightness);
>         }
>
>         dev_priv->display.enable_backlight(connector);
> @@ -890,11 +922,15 @@ 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;
>         struct drm_i915_private *dev_priv = dev->dev_private;
> +       u32 hw_level;
>         int ret;
>
>         intel_runtime_pm_get(dev_priv);
>         mutex_lock(&dev->mode_config.mutex);
> -       ret = intel_panel_get_backlight(connector);
> +
> +       hw_level = intel_panel_get_backlight(connector);
> +       ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
> +
>         mutex_unlock(&dev->mode_config.mutex);
>         intel_runtime_pm_put(dev_priv);
>
> @@ -918,8 +954,15 @@ static int intel_backlight_device_register(struct intel_connector *connector)
>
>         memset(&props, 0, sizeof(props));
>         props.type = BACKLIGHT_RAW;
> -       props.brightness = panel->backlight.level;
> +
> +       /*
> +        * Note: Everything should work even if the backlight device max
> +        * presented to the userspace is arbitrarily chosen.
> +        */
>         props.max_brightness = panel->backlight.max;
> +       props.brightness = scale_hw_to_user(connector,
> +                                           panel->backlight.level,
> +                                           props.max_brightness);
>
>         /*
>          * Note: using the same name independent of the connector prevents
> @@ -965,6 +1008,18 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
>   * XXX: Query mode clock or hardware clock and program PWM modulation frequency
>   * appropriately when it's 0. Use VBT and/or sane defaults.
>   */
> +static inline u32 get_backlight_min(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;
> +
> +       BUG_ON(panel->backlight.max == 0);
> +
> +       return dev_priv->vbt.backlight.min_brightness *
> +               panel->backlight.max / 255;
> +}
> +
>  static int bdw_setup_backlight(struct intel_connector *connector)
>  {
>         struct drm_device *dev = connector->base.dev;
> @@ -980,6 +1035,8 @@ static int bdw_setup_backlight(struct intel_connector *connector)
>         if (!panel->backlight.max)
>                 return -ENODEV;
>
> +       panel->backlight.min = get_backlight_min(connector);
> +
>         val = bdw_get_backlight(connector);
>         panel->backlight.level = intel_panel_compute_brightness(connector, val);
>
> @@ -1004,6 +1061,8 @@ static int pch_setup_backlight(struct intel_connector *connector)
>         if (!panel->backlight.max)
>                 return -ENODEV;
>
> +       panel->backlight.min = get_backlight_min(connector);
> +
>         val = pch_get_backlight(connector);
>         panel->backlight.level = intel_panel_compute_brightness(connector, val);
>
> @@ -1036,6 +1095,8 @@ static int i9xx_setup_backlight(struct intel_connector *connector)
>         if (!panel->backlight.max)
>                 return -ENODEV;
>
> +       panel->backlight.min = get_backlight_min(connector);
> +
>         val = i9xx_get_backlight(connector);
>         panel->backlight.level = intel_panel_compute_brightness(connector, val);
>
> @@ -1063,6 +1124,8 @@ static int i965_setup_backlight(struct intel_connector *connector)
>         if (!panel->backlight.max)
>                 return -ENODEV;
>
> +       panel->backlight.min = get_backlight_min(connector);
> +
>         val = i9xx_get_backlight(connector);
>         panel->backlight.level = intel_panel_compute_brightness(connector, val);
>
> @@ -1100,6 +1163,8 @@ static int vlv_setup_backlight(struct intel_connector *connector)
>         if (!panel->backlight.max)
>                 return -ENODEV;
>
> +       panel->backlight.min = get_backlight_min(connector);
> +
>         val = _vlv_get_backlight(dev, PIPE_A);
>         panel->backlight.level = intel_panel_compute_brightness(connector, val);
>
> --
> 1.9.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-06-03 16:40   ` Stéphane Marchesin
@ 2014-06-03 20:26     ` Daniel Vetter
  2014-06-04  8:25       ` Stéphane Marchesin
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Vetter @ 2014-06-03 20:26 UTC (permalink / raw
  To: Stéphane Marchesin; +Cc: Jani Nikula, intel-gfx, Ben Widawsky

On Tue, Jun 3, 2014 at 6:40 PM, Stéphane Marchesin <marcheu@chromium.org> wrote:
> On Tue, Apr 29, 2014 at 1:30 PM, Jani Nikula <jani.nikula@intel.com> wrote:
>> Historically we've exposed the full backlight PWM duty cycle range to
>> the userspace, in the name of "mechanism, not policy". However, it turns
>> out there are both panels and board designs where there is a minimum
>> duty cycle that is required for proper operation. The minimum duty cycle
>> is available in the VBT.
>>
>> The backlight class sysfs interface does not make any promises to the
>> userspace about the physical meaning of the range
>> 0..max_brightness. Specifically there is no guarantee that 0 means off;
>> indeed for acpi_backlight 0 usually is not off, but the minimum
>> acceptable value.
>
> This is the part we've been relying on in Chrome OS (we assume that 0
> means off). It seems to me that i915 would be the first, or one of the
> first drivers to violate this rule (in particular you can find a lot
> of backlight drivers trying hard to ensure that 0 means off in the
> backlight drivers directory).
>
> For context, we use backlight = 0 as a quick "turn the panel off"
> function where possible. This allows us to avoid the panel off delay
> where possible. Breaking this assumption means that we'd pay the panel
> off delay penalty everywhere, not just with BYT.

Well kde is the opposite and I've had users yelling at me that they
can't use their system, since acpi pretty much always leaves the
backlight on when set to 0. And acpi kinda rules on intel platforms.
So I think I'll merge this one since black screens trumps a slight
functional degration and we didn't duct-tape over the kde assumptions
either. Essentially you can't assume anything about backlight values
besides that bigger values tends to mean brigther. Linearity, absolute
values and endpoints are kinda all off.

If we want to specifically expose an intermediate "panel off" level
because the full link training is too expensive we imo should do this
as an intermediate dpms level, e.g. dpms standby.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-06-03 20:26     ` Daniel Vetter
@ 2014-06-04  8:25       ` Stéphane Marchesin
  2014-06-04  9:11         ` Jani Nikula
  0 siblings, 1 reply; 14+ messages in thread
From: Stéphane Marchesin @ 2014-06-04  8:25 UTC (permalink / raw
  To: Daniel Vetter; +Cc: Jani Nikula, intel-gfx, Ben Widawsky

On Tue, Jun 3, 2014 at 1:26 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Tue, Jun 3, 2014 at 6:40 PM, Stéphane Marchesin <marcheu@chromium.org> wrote:
>> On Tue, Apr 29, 2014 at 1:30 PM, Jani Nikula <jani.nikula@intel.com> wrote:
>>> Historically we've exposed the full backlight PWM duty cycle range to
>>> the userspace, in the name of "mechanism, not policy". However, it turns
>>> out there are both panels and board designs where there is a minimum
>>> duty cycle that is required for proper operation. The minimum duty cycle
>>> is available in the VBT.
>>>
>>> The backlight class sysfs interface does not make any promises to the
>>> userspace about the physical meaning of the range
>>> 0..max_brightness. Specifically there is no guarantee that 0 means off;
>>> indeed for acpi_backlight 0 usually is not off, but the minimum
>>> acceptable value.
>>
>> This is the part we've been relying on in Chrome OS (we assume that 0
>> means off). It seems to me that i915 would be the first, or one of the
>> first drivers to violate this rule (in particular you can find a lot
>> of backlight drivers trying hard to ensure that 0 means off in the
>> backlight drivers directory).
>>
>> For context, we use backlight = 0 as a quick "turn the panel off"
>> function where possible. This allows us to avoid the panel off delay
>> where possible. Breaking this assumption means that we'd pay the panel
>> off delay penalty everywhere, not just with BYT.
>
> Well kde is the opposite and I've had users yelling at me that they
> can't use their system, since acpi pretty much always leaves the
> backlight on when set to 0. And acpi kinda rules on intel platforms.
> So I think I'll merge this one since black screens trumps a slight
> functional degration and we didn't duct-tape over the kde assumptions
> either. Essentially you can't assume anything about backlight values
> besides that bigger values tends to mean brigther. Linearity, absolute
> values and endpoints are kinda all off.

It seems fairly wrong to model the backlight behavior after the only
thing everyone agrees is broken (ACPI). If you go through the
backlight drivers, (at least all the ones I've looked at) ensure that
0 really means off.

>
> If we want to specifically expose an intermediate "panel off" level
> because the full link training is too expensive we imo should do this
> as an intermediate dpms level, e.g. dpms standby.

Training isn't the problem, the panel delays are the problem here (and
not something we can work around because it's part of the panel
specifications which we have to follow). Using dpms wouldn't solve
anything.

Stéphane
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-06-04  8:25       ` Stéphane Marchesin
@ 2014-06-04  9:11         ` Jani Nikula
  2014-06-04 15:04           ` Stéphane Marchesin
  0 siblings, 1 reply; 14+ messages in thread
From: Jani Nikula @ 2014-06-04  9:11 UTC (permalink / raw
  To: Stéphane Marchesin, Daniel Vetter
  Cc: Matthew Garrett, intel-gfx, Ben Widawsky

On Wed, 04 Jun 2014, Stéphane Marchesin <marcheu@chromium.org> wrote:
> On Tue, Jun 3, 2014 at 1:26 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> On Tue, Jun 3, 2014 at 6:40 PM, Stéphane Marchesin <marcheu@chromium.org> wrote:
>>> On Tue, Apr 29, 2014 at 1:30 PM, Jani Nikula <jani.nikula@intel.com> wrote:
>>>> Historically we've exposed the full backlight PWM duty cycle range to
>>>> the userspace, in the name of "mechanism, not policy". However, it turns
>>>> out there are both panels and board designs where there is a minimum
>>>> duty cycle that is required for proper operation. The minimum duty cycle
>>>> is available in the VBT.
>>>>
>>>> The backlight class sysfs interface does not make any promises to the
>>>> userspace about the physical meaning of the range
>>>> 0..max_brightness. Specifically there is no guarantee that 0 means off;
>>>> indeed for acpi_backlight 0 usually is not off, but the minimum
>>>> acceptable value.
>>>
>>> This is the part we've been relying on in Chrome OS (we assume that 0
>>> means off). It seems to me that i915 would be the first, or one of the
>>> first drivers to violate this rule (in particular you can find a lot
>>> of backlight drivers trying hard to ensure that 0 means off in the
>>> backlight drivers directory).
>>>
>>> For context, we use backlight = 0 as a quick "turn the panel off"
>>> function where possible. This allows us to avoid the panel off delay
>>> where possible. Breaking this assumption means that we'd pay the panel
>>> off delay penalty everywhere, not just with BYT.
>>
>> Well kde is the opposite and I've had users yelling at me that they
>> can't use their system, since acpi pretty much always leaves the
>> backlight on when set to 0. And acpi kinda rules on intel platforms.
>> So I think I'll merge this one since black screens trumps a slight
>> functional degration and we didn't duct-tape over the kde assumptions
>> either. Essentially you can't assume anything about backlight values
>> besides that bigger values tends to mean brigther. Linearity, absolute
>> values and endpoints are kinda all off.
>
> It seems fairly wrong to model the backlight behavior after the only
> thing everyone agrees is broken (ACPI).

Please don't put words into everyone's mouth.

Talking to folks on IRC, Dave Airlie said, "I think its been disagreed
over the years to be implementation dependent." and Matthew Garrett
said, "It's currently implementation dependent. It can never mean off
under all circumstances (not all interfaces offer a way to turn it
off)."

I don't know whether they think ACPI is broken, but clearly there's no
one true answer, and I think it's not the correct approach for userspace
to assume 0 means off.

> If you go through the backlight drivers, (at least all the ones I've
> looked at) ensure that 0 really means off.

And systemd goes out of it's way to not switch backlight off on those
interfaces... and it's obvious they can't assume anything about the
meaning of 0 either:

http://cgit.freedesktop.org/systemd/systemd/commit/?id=7b909d7407965c03caaba30daae7aee113627a83

>> If we want to specifically expose an intermediate "panel off" level
>> because the full link training is too expensive we imo should do this
>> as an intermediate dpms level, e.g. dpms standby.
>
> Training isn't the problem, the panel delays are the problem here (and
> not something we can work around because it's part of the panel
> specifications which we have to follow). Using dpms wouldn't solve
> anything.

We could have dpms standby mean backlight off, everything else on,
similarly to what you want by 0 backlight meaning off. So you could
switch between dpms on/standby more quickly. The point in that is that
it's the right API for doing panel power sequencing.

You see, even with defining backlight 0 = off, we'd have to respect the
panel sequencing and delays for backlight (admittedly we currently don't
do that, which is why it's fast - and broken). Doing the panel
sequencing properly from the backlight interface gets *much* harder
because it's all backwards in the stack then.

BR,
Jani.



>
> Stéphane
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-06-04  9:11         ` Jani Nikula
@ 2014-06-04 15:04           ` Stéphane Marchesin
  2014-06-05 16:30             ` Jesse Barnes
  2014-06-05 16:34             ` Matthew Garrett
  0 siblings, 2 replies; 14+ messages in thread
From: Stéphane Marchesin @ 2014-06-04 15:04 UTC (permalink / raw
  To: Jani Nikula; +Cc: Matthew Garrett, intel-gfx, Ben Widawsky

On Wed, Jun 4, 2014 at 2:11 AM, Jani Nikula <jani.nikula@intel.com> wrote:
> On Wed, 04 Jun 2014, Stéphane Marchesin <marcheu@chromium.org> wrote:
>> On Tue, Jun 3, 2014 at 1:26 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>>> On Tue, Jun 3, 2014 at 6:40 PM, Stéphane Marchesin <marcheu@chromium.org> wrote:
>>>> On Tue, Apr 29, 2014 at 1:30 PM, Jani Nikula <jani.nikula@intel.com> wrote:
>>>>> Historically we've exposed the full backlight PWM duty cycle range to
>>>>> the userspace, in the name of "mechanism, not policy". However, it turns
>>>>> out there are both panels and board designs where there is a minimum
>>>>> duty cycle that is required for proper operation. The minimum duty cycle
>>>>> is available in the VBT.
>>>>>
>>>>> The backlight class sysfs interface does not make any promises to the
>>>>> userspace about the physical meaning of the range
>>>>> 0..max_brightness. Specifically there is no guarantee that 0 means off;
>>>>> indeed for acpi_backlight 0 usually is not off, but the minimum
>>>>> acceptable value.
>>>>
>>>> This is the part we've been relying on in Chrome OS (we assume that 0
>>>> means off). It seems to me that i915 would be the first, or one of the
>>>> first drivers to violate this rule (in particular you can find a lot
>>>> of backlight drivers trying hard to ensure that 0 means off in the
>>>> backlight drivers directory).
>>>>
>>>> For context, we use backlight = 0 as a quick "turn the panel off"
>>>> function where possible. This allows us to avoid the panel off delay
>>>> where possible. Breaking this assumption means that we'd pay the panel
>>>> off delay penalty everywhere, not just with BYT.
>>>
>>> Well kde is the opposite and I've had users yelling at me that they
>>> can't use their system, since acpi pretty much always leaves the
>>> backlight on when set to 0. And acpi kinda rules on intel platforms.
>>> So I think I'll merge this one since black screens trumps a slight
>>> functional degration and we didn't duct-tape over the kde assumptions
>>> either. Essentially you can't assume anything about backlight values
>>> besides that bigger values tends to mean brigther. Linearity, absolute
>>> values and endpoints are kinda all off.
>>
>> It seems fairly wrong to model the backlight behavior after the only
>> thing everyone agrees is broken (ACPI).
>
> Please don't put words into everyone's mouth.
>
> Talking to folks on IRC, Dave Airlie said, "I think its been disagreed
> over the years to be implementation dependent." and Matthew Garrett
> said, "It's currently implementation dependent. It can never mean off
> under all circumstances (not all interfaces offer a way to turn it
> off)."
>
> I don't know whether they think ACPI is broken, but clearly there's no
> one true answer, and I think it's not the correct approach for userspace
> to assume 0 means off.

Well, for example ACPI backlight isn't the default on intel, instead
i915 implements its own backlight. ACPI backlight doesn't support as
many backlight levels as the native backlight for example. So I do
think that ACPI backlight is inferior.

>
>> If you go through the backlight drivers, (at least all the ones I've
>> looked at) ensure that 0 really means off.
>
> And systemd goes out of it's way to not switch backlight off on those
> interfaces... and it's obvious they can't assume anything about the
> meaning of 0 either:
>
> http://cgit.freedesktop.org/systemd/systemd/commit/?id=7b909d7407965c03caaba30daae7aee113627a83

This seems unrelated, they just turn the backlight to non-zero to make
things visible?

>
>>> If we want to specifically expose an intermediate "panel off" level
>>> because the full link training is too expensive we imo should do this
>>> as an intermediate dpms level, e.g. dpms standby.
>>
>> Training isn't the problem, the panel delays are the problem here (and
>> not something we can work around because it's part of the panel
>> specifications which we have to follow). Using dpms wouldn't solve
>> anything.
>
> We could have dpms standby mean backlight off, everything else on,
> similarly to what you want by 0 backlight meaning off. So you could
> switch between dpms on/standby more quickly. The point in that is that
> it's the right API for doing panel power sequencing.
>
> You see, even with defining backlight 0 = off, we'd have to respect the
> panel sequencing and delays for backlight (admittedly we currently don't
> do that, which is why it's fast - and broken).

There are multiple delays at play here, and typically the longest
panel delays have nothing to do with the backlight but they are the
delays for turning the panel on/off (usually the panel on/off delays
are much bigger, up to 500ms on some panels). These are the delays I'm
trying to avoid.

> Doing the panel
> sequencing properly from the backlight interface gets *much* harder
> because it's all backwards in the stack then.

If you implement some interface which does "set backlight to 0 on
platforms which support it, and do panel off on other platforms",
that's fine by me; however I don't want to regress all the other
platforms just because BYT has issues. In the current state of things,
the functionality set which is made available to user space happens to
shrink with your patch.

Stéphane
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-06-04 15:04           ` Stéphane Marchesin
@ 2014-06-05 16:30             ` Jesse Barnes
  2014-06-05 16:34             ` Matthew Garrett
  1 sibling, 0 replies; 14+ messages in thread
From: Jesse Barnes @ 2014-06-05 16:30 UTC (permalink / raw
  To: Stéphane Marchesin
  Cc: Jani Nikula, Matthew Garrett, intel-gfx, Ben Widawsky

On Wed, 4 Jun 2014 08:04:53 -0700
Stéphane Marchesin <marcheu@chromium.org> wrote:

> > We could have dpms standby mean backlight off, everything else on,
> > similarly to what you want by 0 backlight meaning off. So you could
> > switch between dpms on/standby more quickly. The point in that is that
> > it's the right API for doing panel power sequencing.
> >
> > You see, even with defining backlight 0 = off, we'd have to respect the
> > panel sequencing and delays for backlight (admittedly we currently don't
> > do that, which is why it's fast - and broken).  
> 
> There are multiple delays at play here, and typically the longest
> panel delays have nothing to do with the backlight but they are the
> delays for turning the panel on/off (usually the panel on/off delays
> are much bigger, up to 500ms on some panels). These are the delays I'm
> trying to avoid.
> 
> > Doing the panel
> > sequencing properly from the backlight interface gets *much* harder
> > because it's all backwards in the stack then.  
> 
> If you implement some interface which does "set backlight to 0 on
> platforms which support it, and do panel off on other platforms",
> that's fine by me; however I don't want to regress all the other
> platforms just because BYT has issues. In the current state of things,
> the functionality set which is made available to user space happens to
> shrink with your patch.

According to the LVDS and eDP timing specs, we *ought* to be able to
disable the backlight and then the PWM source and leave everything else
alone, as long as we apply the appropriate delays between backlight off
and PWM off, and then again when we turn them back on (PWM first,
delay, then backlight on).

IIRC the issue on BYT was that we saw the panel power line go down when
we disabled the backlight and PWM which would obviously cause all
sorts of problems.  But that could have been user error on the scope,
so we should confirm that before baking a full DPMS cycle into the BYT
implementation or the interface in general.

-- 
Jesse Barnes, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-06-04 15:04           ` Stéphane Marchesin
  2014-06-05 16:30             ` Jesse Barnes
@ 2014-06-05 16:34             ` Matthew Garrett
  1 sibling, 0 replies; 14+ messages in thread
From: Matthew Garrett @ 2014-06-05 16:34 UTC (permalink / raw
  To: marcheu@chromium.org
  Cc: jani.nikula@intel.com, intel-gfx@lists.freedesktop.org,
	ben@bwidawsk.net

On Wed, 2014-06-04 at 08:04 -0700, Stéphane Marchesin wrote:

> Well, for example ACPI backlight isn't the default on intel, instead
> i915 implements its own backlight. ACPI backlight doesn't support as
> many backlight levels as the native backlight for example. So I do
> think that ACPI backlight is inferior.

ACPI backlight is the default on most pre-Windows 8 i915 systems.
Userspace which assumes that backlight value 0 has any specific meaning
is broken userspace. Adding an additional interface that allows
disabling the backlight without powering down the panel seems like a
completely reasonable thing to do, though.

-- 
Matthew Garrett <matthew.garrett@nebula.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness
  2014-05-20 19:08   ` Jesse Barnes
@ 2014-06-06 13:40     ` Jani Nikula
  0 siblings, 0 replies; 14+ messages in thread
From: Jani Nikula @ 2014-06-06 13:40 UTC (permalink / raw
  To: Jesse Barnes; +Cc: intel-gfx, Ben Widawsky

On Tue, 20 May 2014, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Tue, 29 Apr 2014 23:30:49 +0300
> Jani Nikula <jani.nikula@intel.com> wrote:
>
>> Historically we've exposed the full backlight PWM duty cycle range to
>> the userspace, in the name of "mechanism, not policy". However, it turns
>> out there are both panels and board designs where there is a minimum
>> duty cycle that is required for proper operation. The minimum duty cycle
>> is available in the VBT.
>> 
>> The backlight class sysfs interface does not make any promises to the
>> userspace about the physical meaning of the range
>> 0..max_brightness. Specifically there is no guarantee that 0 means off;
>> indeed for acpi_backlight 0 usually is not off, but the minimum
>> acceptable value.
>> 
>> Respect the minimum backlight, and expose the range acceptable to the
>> hardware as 0..max_brightness to the userspace via the backlight class
>> device; 0 means the minimum acceptable enabled value. To switch off the
>> backlight, the user must disable the encoder.
>> 
>> As a side effect, make the backlight class device max brightness and
>> physical PWM modulation frequency (i.e. max duty cycle) independent.
>> 
>> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>
> I like the direction here... I wonder if we should always virtualize
> the max too, and just always expose 0-2047 or something.

IIUC Windows 8 assumes 101 levels, 0..100 inclusive. (Curiously I didn't
find mention what 0 means there.)

The higher the backlight modulation frequency, the less flicker, and the
higher the range we expose - but, as far as I've understood, fewer
perceivable physical brightness levels. The panel just won't follow the
signal fast enough. So we could just as well expose a smaller range, and
it shouldn't make a difference.

But I'd like that to be a follow-up later on when the dust has settled.

>> @@ -965,6 +1008,18 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
>>   * XXX: Query mode clock or hardware clock and program PWM modulation frequency
>>   * appropriately when it's 0. Use VBT and/or sane defaults.
>>   */
>> +static inline u32 get_backlight_min(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;
>> +
>> +	BUG_ON(panel->backlight.max == 0);
>> +
>> +	return dev_priv->vbt.backlight.min_brightness *
>> +		panel->backlight.max / 255;
>> +}
>
> Is this the user version or the hw version?  If hw, why not just use
> min_brightness directly?

My understanding is that the VBT value is a coefficient
(min_brightness/255) of the hw max to get the hw value. I may be wrong
as the spec sucks. 255 as the biggest absolute hw min value sounds
awfully small to me though.

BR,
Jani.


>
> -- 
> Jesse Barnes, Intel Open Source Technology Center

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-06-06 13:40 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-29 20:30 [RFC PATCH 1/2] drm/i915: shuffle panel code Jani Nikula
2014-04-29 20:30 ` [RFC PATCH 2/2] drm/i915: respect the VBT minimum backlight brightness Jani Nikula
2014-04-29 20:37   ` Jani Nikula
2014-05-20 19:08   ` Jesse Barnes
2014-06-06 13:40     ` Jani Nikula
2014-06-03 16:40   ` Stéphane Marchesin
2014-06-03 20:26     ` Daniel Vetter
2014-06-04  8:25       ` Stéphane Marchesin
2014-06-04  9:11         ` Jani Nikula
2014-06-04 15:04           ` Stéphane Marchesin
2014-06-05 16:30             ` Jesse Barnes
2014-06-05 16:34             ` Matthew Garrett
2014-05-20 19:00 ` [RFC PATCH 1/2] drm/i915: shuffle panel code Jesse Barnes
2014-05-20 19:08   ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.