I recently got a ThinkPad X1 Extreme 2nd Generation for fixing some issues on, and noticed that out of the box the backlight doesn't work. Along the way of fixing that, I found a few issues with how i915 handles DPCD AUX backlight control and fixed them. Now I've got working backlight controls, hooray!
Note that this patch series enables DPCD backlight controls by default. This time however, we ignore the backlight type advertised in the VBT (unless it's a custom backlight interface that doesn't use the standard VESA interface over AUX) and just trust the DPCD.
Lyude Paul (5): drm/i915: Fix eDP DPCD aux max backlight calculations drm/i915: Assume 100% brightness when not in DPCD control mode drm/i915: Fix DPCD register order in intel_dp_aux_enable_backlight() drm/i915: Don't use VBT for detecting DPCD backlight controls drm/i915: Auto detect DPCD backlight support by default
.../drm/i915/display/intel_display_types.h | 3 + .../drm/i915/display/intel_dp_aux_backlight.c | 175 ++++++++++++------ drivers/gpu/drm/i915/i915_params.c | 2 +- drivers/gpu/drm/i915/i915_params.h | 2 +- 4 files changed, 126 insertions(+), 56 deletions(-)
Max backlight value for the panel was being calculated using byte count i.e. 0xffff if 2 bytes are supported for backlight brightness and 0xff if 1 byte is supported. However, EDP_PWMGEN_BIT_COUNT determines the number of active control bits used for the brightness setting. Thus, even if the panel uses 2 byte setting, it might not use all the control bits. Thus, max backlight should be set based on the value of EDP_PWMGEN_BIT_COUNT instead of assuming 65535 or 255.
Additionally, EDP_PWMGEN_BIT_COUNT was being updated based on the VBT frequency which results in a different max backlight value. Thus, setting of EDP_PWMGEN_BIT_COUNT is moved to setup phase instead of enable so that max backlight can be calculated correctly. Only the frequency divider is set during the enable phase using the value of EDP_PWMGEN_BIT_COUNT.
This is based off the original patch series from Furquan Shaikh furquan@google.com:
https://patchwork.freedesktop.org/patch/317255/?series=62326&rev=3
Changes since original patch: * Remove unused intel_dp variable in intel_dp_aux_setup_backlight() * Fix checkpatch issues * Make sure that we rewrite the pwmgen bit count whenever we bring the panel out of D3 mode
v2 by Jani: * rebase * fix readb return value check
Cc: Furquan Shaikh furquan@google.com Tested-by: AceLan Kao acelan.kao@canonical.com Tested-by: Perry Yuan pyuan@redhat.com Signed-off-by: Lyude Paul lyude@redhat.com Signed-off-by: Jani Nikula jani.nikula@intel.com --- .../drm/i915/display/intel_display_types.h | 3 + .../drm/i915/display/intel_dp_aux_backlight.c | 139 ++++++++++++------ 2 files changed, 95 insertions(+), 47 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index fdd943a17de3..155ce49ae764 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -214,6 +214,9 @@ struct intel_panel { u8 controller; /* bxt+ only */ struct pwm_device *pwm;
+ /* DPCD backlight */ + u8 pwmgen_bit_count; + struct backlight_device *device;
/* Connector and platform specific backlight functions */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 7c653f8c307f..345eed641455 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -111,61 +111,28 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); - int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1; - u8 pn, pn_min, pn_max; + const u8 pn = connector->panel.backlight.pwmgen_bit_count; + int freq, fxp, f, fxp_actual, fxp_min, fxp_max;
- /* Find desired value of (F x P) - * Note that, if F x P is out of supported range, the maximum value or - * minimum value will applied automatically. So no need to check that. - */ freq = dev_priv->vbt.backlight.pwm_freq_hz; - DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq); if (!freq) { DRM_DEBUG_KMS("Use panel default backlight frequency\n"); return false; }
fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); + f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); + fxp_actual = f << pn;
- /* Use highest possible value of Pn for more granularity of brightness - * adjustment while satifying the conditions below. - * - Pn is in the range of Pn_min and Pn_max - * - F is in the range of 1 and 255 - * - FxP is within 25% of desired value. - * Note: 25% is arbitrary value and may need some tweak. - */ - if (drm_dp_dpcd_readb(&intel_dp->aux, - DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) { - DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n"); - return false; - } - if (drm_dp_dpcd_readb(&intel_dp->aux, - DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) { - DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n"); - return false; - } - pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; - pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; - + /* Ensure frequency is within 25% of desired value */ fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); - if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) { - DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n"); - return false; - }
- for (pn = pn_max; pn >= pn_min; pn--) { - f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); - fxp_actual = f << pn; - if (fxp_min <= fxp_actual && fxp_actual <= fxp_max) - break; - } - - if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) { - DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n"); + if (fxp_min > fxp_actual || fxp_actual > fxp_max) { + DRM_DEBUG_KMS("Actual frequency out of range\n"); return false; } + if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) { DRM_DEBUG_KMS("Failed to write aux backlight freq\n"); @@ -179,6 +146,7 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct intel_panel *panel = &connector->panel; u8 dpcd_buf, new_dpcd_buf, edp_backlight_mode;
if (drm_dp_dpcd_readb(&intel_dp->aux, @@ -197,6 +165,12 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT: new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; + + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT, + panel->backlight.pwmgen_bit_count) < 0) + DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n"); + break;
/* Do nothing when it is already DPCD mode */ @@ -226,20 +200,91 @@ static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old false); }
+static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct intel_panel *panel = &connector->panel; + u32 max_backlight = 0; + int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1; + u8 pn, pn_min, pn_max; + + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, &pn) == 1) { + pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + max_backlight = (1 << pn) - 1; + } + + /* Find desired value of (F x P) + * Note that, if F x P is out of supported range, the maximum value or + * minimum value will applied automatically. So no need to check that. + */ + freq = i915->vbt.backlight.pwm_freq_hz; + DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq); + if (!freq) { + DRM_DEBUG_KMS("Use panel default backlight frequency\n"); + return max_backlight; + } + + fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); + + /* Use highest possible value of Pn for more granularity of brightness + * adjustment while satifying the conditions below. + * - Pn is in the range of Pn_min and Pn_max + * - F is in the range of 1 and 255 + * - FxP is within 25% of desired value. + * Note: 25% is arbitrary value and may need some tweak. + */ + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) { + DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n"); + return max_backlight; + } + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) { + DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n"); + return max_backlight; + } + pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + + fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); + fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); + if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) { + DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n"); + return max_backlight; + } + + for (pn = pn_max; pn >= pn_min; pn--) { + f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); + fxp_actual = f << pn; + if (fxp_min <= fxp_actual && fxp_actual <= fxp_max) + break; + } + + DRM_DEBUG_KMS("Using eDP pwmgen bit count of %d\n", pn); + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) { + DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n"); + return max_backlight; + } + panel->backlight.pwmgen_bit_count = pn; + + max_backlight = (1 << pn) - 1; + + return max_backlight; +} + static int intel_dp_aux_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); struct intel_panel *panel = &connector->panel;
- if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) - panel->backlight.max = 0xFFFF; - else - panel->backlight.max = 0xFF; + panel->backlight.max = intel_dp_aux_calc_max_backlight(connector); + if (!panel->backlight.max) + return -ENODEV;
panel->backlight.min = 0; panel->backlight.level = intel_dp_aux_get_backlight(connector); - panel->backlight.enabled = panel->backlight.level != 0;
return 0;
Currently we always determine the initial panel brightness level by simply reading the value from DP_EDP_BACKLIGHT_BRIGHTNESS_MSB/LSB. This seems wrong though, because if the panel is not currently in DPCD control mode there's not really any reason why there would be any brightness value programmed in the first place.
This appears to be the case on the Lenovo ThinkPad X1 Extreme 2nd Generation, where the default value in these registers is always 0 on boot despite the fact the panel runs at max brightness by default. Getting the initial brightness value correct here is important as well, since the panel on this laptop doesn't behave well if it's ever put into DPCD control mode while the brightness level is programmed to 0.
So, let's fix this by checking what the current backlight control mode is before reading the brightness level. If it's in DPCD control mode, we return the programmed brightness level. Otherwise we assume 100% brightness and return the highest possible brightness level. This also prevents us from accidentally programming a brightness level of 0.
This is one of the many fixes that gets backlight controls working on the ThinkPad X1 Extreme 2nd Generation with optional 4K AMOLED screen.
Changes since v1: * s/DP_EDP_DISPLAY_CONTROL_REGISTER/DP_EDP_BACKLIGHT_MODE_SET_REGISTER/ - Jani
Tested-by: AceLan Kao acelan.kao@canonical.com Tested-by: Perry Yuan pyuan@redhat.com Signed-off-by: Lyude Paul lyude@redhat.com Signed-off-by: Jani Nikula jani.nikula@intel.com --- .../drm/i915/display/intel_dp_aux_backlight.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 345eed641455..5d4db5f8a165 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -59,8 +59,25 @@ static u32 intel_dp_aux_get_backlight(struct intel_connector *connector) { struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); u8 read_val[2] = { 0x0 }; + u8 mode_reg; u16 level = 0;
+ if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_EDP_BACKLIGHT_MODE_SET_REGISTER, + &mode_reg) != 1) { + DRM_DEBUG_KMS("Failed to read the DPCD register 0x%x\n", + DP_EDP_BACKLIGHT_MODE_SET_REGISTER); + return 0; + } + + /* + * If we're not in DPCD control mode yet, the programmed brightness + * value is meaningless and we should assume max brightness + */ + if ((mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) != + DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) + return connector->panel.backlight.max; + if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB, &read_val, sizeof(read_val)) < 0) { DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
For eDP panels, it appears it's expected that so long as the panel is in DPCD control mode that the brightness value is never set to 0. Instead, if the desired effect is to set the panel's backlight to 0 we're expected to simply turn off the backlight through the DP_EDP_DISPLAY_CONTROL_REGISTER.
We already do the latter correctly in intel_dp_aux_disable_backlight(). But, we make the mistake of writing the DPCD registers in the wrong order when enabling the backlight in intel_dp_aux_enable_backlight() since we currently enable the backlight through DP_EDP_DISPLAY_CONTROL_REGISTER before writing the brightness level. On the X1 Extreme 2nd Generation, this appears to have the potential of confusing the panel in such a way that further attempts to set the brightness don't actually change the backlight as expected and leave it off. Presumably, this happens because the incorrect register writing order briefly leaves the panel with DPCD mode enabled and a 0 brightness level set.
So, reverse the order we write the DPCD registers when enabling the panel backlight so that we write the brightness value first, and enable the backlight second. This fix appears to be the final bit needed to get the backlight on the ThinkPad X1 Extreme 2nd Generation's AMOLED screen working.
Tested-by: AceLan Kao acelan.kao@canonical.com Tested-by: Perry Yuan pyuan@redhat.com Signed-off-by: Lyude Paul lyude@redhat.com Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 5d4db5f8a165..77a759361c5c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -207,8 +207,9 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st } }
+ intel_dp_aux_set_backlight(conn_state, + connector->panel.backlight.level); set_aux_backlight_enable(intel_dp, true); - intel_dp_aux_set_backlight(conn_state, connector->panel.backlight.level); }
static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old_conn_state)
Despite the fact that the VBT appears to have a field for specifying that a system is equipped with a panel that supports standard VESA backlight controls over the DP AUX channel, so far every system we've spotted DPCD backlight control support on doesn't actually set this field correctly and all have it set to INTEL_BACKLIGHT_DISPLAY_DDI.
While we don't know the exact reason for this VBT misuse, talking with some vendors indicated that there's a good number of laptop panels out there that supposedly support both PWM backlight controls and DPCD backlight controls as a workaround until Intel supports DPCD backlight controls across platforms universally. This being said, the X1 Extreme 2nd Gen that I have here (note that Lenovo is not the hardware vendor that informed us of this) PWM backlight controls are advertised, but only DPCD controls actually function. I'm going to make an educated guess here and say that on systems like this one, it's likely that PWM backlight controls might have been intended to work but were never really tested by QA.
Since we really need backlights to work without any extra module parameters, let's take the risk here and rely on the standard DPCD caps to tell us whether AUX backlight controls are supported or not. We still check the VBT, but only to make sure that we don't enable DPCD backlight controls on a panel that uses something other then the standard VESA interfaces over AUX. Since panels using such non-standard interfaces should probably have support added to i915, we'll print a warning when seeing this in the VBT. We can remove this warning later if we end up adding support for any custom backlight interfaces.
Signed-off-by: Lyude Paul lyude@redhat.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112376 Cc: Jani Nikula jani.nikula@intel.com Cc: Perry Yuan pyuan@redhat.com Cc: AceLan Kao acelan.kao@canonical.com --- .../drm/i915/display/intel_dp_aux_backlight.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 77a759361c5c..3002b600635f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -330,13 +330,17 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) struct intel_panel *panel = &intel_connector->panel; struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
- if (i915_modparams.enable_dpcd_backlight == 0 || - (i915_modparams.enable_dpcd_backlight == -1 && - dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE)) - return -ENODEV; - - if (!intel_dp_aux_display_control_capable(intel_connector)) + if (i915_modparams.enable_dpcd_backlight == 0) return -ENODEV; + if (i915_modparams.enable_dpcd_backlight == -1) { + if (dev_priv->vbt.backlight.type + == INTEL_BACKLIGHT_PANEL_DRIVER_INTERFACE) { + DRM_WARN("VBT says panel uses custom panel driver interface, not using DPCD backlight controls\n"); + return -ENODEV; + } + if (!intel_dp_aux_display_control_capable(intel_connector)) + return -ENODEV; + }
panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.enable = intel_dp_aux_enable_backlight;
On Thu, 16 Jan 2020, Lyude Paul lyude@redhat.com wrote:
Despite the fact that the VBT appears to have a field for specifying that a system is equipped with a panel that supports standard VESA backlight controls over the DP AUX channel, so far every system we've spotted DPCD backlight control support on doesn't actually set this field correctly and all have it set to INTEL_BACKLIGHT_DISPLAY_DDI.
While we don't know the exact reason for this VBT misuse, talking with some vendors indicated that there's a good number of laptop panels out there that supposedly support both PWM backlight controls and DPCD backlight controls as a workaround until Intel supports DPCD backlight controls across platforms universally. This being said, the X1 Extreme 2nd Gen that I have here (note that Lenovo is not the hardware vendor that informed us of this) PWM backlight controls are advertised, but only DPCD controls actually function. I'm going to make an educated guess here and say that on systems like this one, it's likely that PWM backlight controls might have been intended to work but were never really tested by QA.
Since we really need backlights to work without any extra module parameters, let's take the risk here and rely on the standard DPCD caps to tell us whether AUX backlight controls are supported or not. We still check the VBT, but only to make sure that we don't enable DPCD backlight controls on a panel that uses something other then the standard VESA interfaces over AUX. Since panels using such non-standard interfaces should probably have support added to i915, we'll print a warning when seeing this in the VBT. We can remove this warning later if we end up adding support for any custom backlight interfaces.
Signed-off-by: Lyude Paul lyude@redhat.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112376 Cc: Jani Nikula jani.nikula@intel.com Cc: Perry Yuan pyuan@redhat.com Cc: AceLan Kao acelan.kao@canonical.com
.../drm/i915/display/intel_dp_aux_backlight.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 77a759361c5c..3002b600635f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -330,13 +330,17 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) struct intel_panel *panel = &intel_connector->panel; struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
- if (i915_modparams.enable_dpcd_backlight == 0 ||
(i915_modparams.enable_dpcd_backlight == -1 &&
dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
return -ENODEV;
- if (!intel_dp_aux_display_control_capable(intel_connector))
- if (i915_modparams.enable_dpcd_backlight == 0) return -ENODEV;
- if (i915_modparams.enable_dpcd_backlight == -1) {
if (dev_priv->vbt.backlight.type
== INTEL_BACKLIGHT_PANEL_DRIVER_INTERFACE) {
DRM_WARN("VBT says panel uses custom panel driver interface, not using DPCD backlight controls\n");
return -ENODEV;
}
if (!intel_dp_aux_display_control_capable(intel_connector))
return -ENODEV;
Functionally, I'm fine with trying this. But perhaps we should check aux and early return first, and then check what vbt says, to reduce the dmesg noise.
I'll probably want to see a debug message if we're enabling aux backlight even if dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE. It's the kind of debug trace you'll really want to get first.
BR, Jani.
}
panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.enable = intel_dp_aux_enable_backlight;
On Fri, 17 Jan 2020, Jani Nikula jani.nikula@intel.com wrote:
On Thu, 16 Jan 2020, Lyude Paul lyude@redhat.com wrote:
Despite the fact that the VBT appears to have a field for specifying that a system is equipped with a panel that supports standard VESA backlight controls over the DP AUX channel, so far every system we've spotted DPCD backlight control support on doesn't actually set this field correctly and all have it set to INTEL_BACKLIGHT_DISPLAY_DDI.
While we don't know the exact reason for this VBT misuse, talking with some vendors indicated that there's a good number of laptop panels out there that supposedly support both PWM backlight controls and DPCD backlight controls as a workaround until Intel supports DPCD backlight controls across platforms universally. This being said, the X1 Extreme 2nd Gen that I have here (note that Lenovo is not the hardware vendor that informed us of this) PWM backlight controls are advertised, but only DPCD controls actually function. I'm going to make an educated guess here and say that on systems like this one, it's likely that PWM backlight controls might have been intended to work but were never really tested by QA.
Since we really need backlights to work without any extra module parameters, let's take the risk here and rely on the standard DPCD caps to tell us whether AUX backlight controls are supported or not. We still check the VBT, but only to make sure that we don't enable DPCD backlight controls on a panel that uses something other then the standard VESA interfaces over AUX. Since panels using such non-standard interfaces should probably have support added to i915, we'll print a warning when seeing this in the VBT. We can remove this warning later if we end up adding support for any custom backlight interfaces.
Signed-off-by: Lyude Paul lyude@redhat.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112376 Cc: Jani Nikula jani.nikula@intel.com Cc: Perry Yuan pyuan@redhat.com Cc: AceLan Kao acelan.kao@canonical.com
.../drm/i915/display/intel_dp_aux_backlight.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 77a759361c5c..3002b600635f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -330,13 +330,17 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) struct intel_panel *panel = &intel_connector->panel; struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
- if (i915_modparams.enable_dpcd_backlight == 0 ||
(i915_modparams.enable_dpcd_backlight == -1 &&
dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
return -ENODEV;
- if (!intel_dp_aux_display_control_capable(intel_connector))
- if (i915_modparams.enable_dpcd_backlight == 0) return -ENODEV;
- if (i915_modparams.enable_dpcd_backlight == -1) {
if (dev_priv->vbt.backlight.type
== INTEL_BACKLIGHT_PANEL_DRIVER_INTERFACE) {
DRM_WARN("VBT says panel uses custom panel driver interface, not using DPCD backlight controls\n");
return -ENODEV;
}
if (!intel_dp_aux_display_control_capable(intel_connector))
return -ENODEV;
Functionally, I'm fine with trying this. But perhaps we should check aux and early return first, and then check what vbt says, to reduce the dmesg noise.
I'll probably want to see a debug message if we're enabling aux backlight even if dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE. It's the kind of debug trace you'll really want to get first.
So I've gone ahead and pushed patches 1-3 and 5 in this series, as they were tested as part of the series I posted.
BR, Jani.
BR, Jani.
}
panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.enable = intel_dp_aux_enable_backlight;
On Fri, 2020-01-17 at 13:36 +0200, Jani Nikula wrote:
On Thu, 16 Jan 2020, Lyude Paul lyude@redhat.com wrote:
Despite the fact that the VBT appears to have a field for specifying that a system is equipped with a panel that supports standard VESA backlight controls over the DP AUX channel, so far every system we've spotted DPCD backlight control support on doesn't actually set this field correctly and all have it set to INTEL_BACKLIGHT_DISPLAY_DDI.
While we don't know the exact reason for this VBT misuse, talking with some vendors indicated that there's a good number of laptop panels out there that supposedly support both PWM backlight controls and DPCD backlight controls as a workaround until Intel supports DPCD backlight controls across platforms universally. This being said, the X1 Extreme 2nd Gen that I have here (note that Lenovo is not the hardware vendor that informed us of this) PWM backlight controls are advertised, but only DPCD controls actually function. I'm going to make an educated guess here and say that on systems like this one, it's likely that PWM backlight controls might have been intended to work but were never really tested by QA.
Since we really need backlights to work without any extra module parameters, let's take the risk here and rely on the standard DPCD caps to tell us whether AUX backlight controls are supported or not. We still check the VBT, but only to make sure that we don't enable DPCD backlight controls on a panel that uses something other then the standard VESA interfaces over AUX. Since panels using such non-standard interfaces should probably have support added to i915, we'll print a warning when seeing this in the VBT. We can remove this warning later if we end up adding support for any custom backlight interfaces.
Signed-off-by: Lyude Paul lyude@redhat.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112376 Cc: Jani Nikula jani.nikula@intel.com Cc: Perry Yuan pyuan@redhat.com Cc: AceLan Kao acelan.kao@canonical.com
.../drm/i915/display/intel_dp_aux_backlight.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 77a759361c5c..3002b600635f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -330,13 +330,17 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) struct intel_panel *panel = &intel_connector->panel; struct drm_i915_private *dev_priv = to_i915(intel_connector-
base.dev);
- if (i915_modparams.enable_dpcd_backlight == 0 ||
(i915_modparams.enable_dpcd_backlight == -1 &&
dev_priv->vbt.backlight.type !=
INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
return -ENODEV;
- if (!intel_dp_aux_display_control_capable(intel_connector))
- if (i915_modparams.enable_dpcd_backlight == 0) return -ENODEV;
- if (i915_modparams.enable_dpcd_backlight == -1) {
if (dev_priv->vbt.backlight.type
== INTEL_BACKLIGHT_PANEL_DRIVER_INTERFACE) {
DRM_WARN("VBT says panel uses custom panel driver
interface, not using DPCD backlight controls\n");
return -ENODEV;
}
if (!intel_dp_aux_display_control_capable(intel_connector))
return -ENODEV;
Functionally, I'm fine with trying this. But perhaps we should check aux and early return first, and then check what vbt says, to reduce the dmesg noise.
I'll probably want to see a debug message if we're enabling aux backlight even if dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE. It's the kind of debug trace you'll really want to get first.
Good point, I'll send a respin of this patch with those changes
BR, Jani.
}
panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.enable = intel_dp_aux_enable_backlight;
Despite the fact that the VBT appears to have a field for specifying that a system is equipped with a panel that supports standard VESA backlight controls over the DP AUX channel, so far every system we've spotted DPCD backlight control support on doesn't actually set this field correctly and all have it set to INTEL_BACKLIGHT_DISPLAY_DDI.
While we don't know the exact reason for this VBT misuse, talking with some vendors indicated that there's a good number of laptop panels out there that supposedly support both PWM backlight controls and DPCD backlight controls as a workaround until Intel supports DPCD backlight controls across platforms universally. This being said, the X1 Extreme 2nd Gen that I have here (note that Lenovo is not the hardware vendor that informed us of this) PWM backlight controls are advertised, but only DPCD controls actually function. I'm going to make an educated guess here and say that on systems like this one, it's likely that PWM backlight controls might have been intended to work but were never really tested by QA.
Since we really need backlights to work without any extra module parameters, let's take the risk here and rely on the standard DPCD caps to tell us whether AUX backlight controls are supported or not. We still check the VBT, just so we can print a debugging message on systems that advertise DPCD backlight support on the panel but not in the VBT.
Changes since v3: * Print a debugging message if we enable DPCD backlight control on a device which doesn't report DPCD backlight controls in it's VBT, instead of warning on custom panel backlight interfaces.
Signed-off-by: Lyude Paul lyude@redhat.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112376 Cc: Jani Nikula jani.nikula@intel.com Cc: Perry Yuan pyuan@redhat.com Cc: AceLan Kao acelan.kao@canonical.com --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 77a759361c5c..0f8edc775375 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -328,15 +328,16 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector) int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) { struct intel_panel *panel = &intel_connector->panel; - struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev); + enum intel_backlight_type type = + to_i915(intel_connector->base.dev)->vbt.backlight.type;
if (i915_modparams.enable_dpcd_backlight == 0 || (i915_modparams.enable_dpcd_backlight == -1 && - dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE)) + !intel_dp_aux_display_control_capable(intel_connector))) return -ENODEV;
- if (!intel_dp_aux_display_control_capable(intel_connector)) - return -ENODEV; + if (type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE) + DRM_DEBUG_DRIVER("Ignoring VBT backlight type\n");
panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.enable = intel_dp_aux_enable_backlight;
On Fri, 17 Jan 2020, Lyude Paul lyude@redhat.com wrote:
Despite the fact that the VBT appears to have a field for specifying that a system is equipped with a panel that supports standard VESA backlight controls over the DP AUX channel, so far every system we've spotted DPCD backlight control support on doesn't actually set this field correctly and all have it set to INTEL_BACKLIGHT_DISPLAY_DDI.
While we don't know the exact reason for this VBT misuse, talking with some vendors indicated that there's a good number of laptop panels out there that supposedly support both PWM backlight controls and DPCD backlight controls as a workaround until Intel supports DPCD backlight controls across platforms universally. This being said, the X1 Extreme 2nd Gen that I have here (note that Lenovo is not the hardware vendor that informed us of this) PWM backlight controls are advertised, but only DPCD controls actually function. I'm going to make an educated guess here and say that on systems like this one, it's likely that PWM backlight controls might have been intended to work but were never really tested by QA.
Since we really need backlights to work without any extra module parameters, let's take the risk here and rely on the standard DPCD caps to tell us whether AUX backlight controls are supported or not. We still check the VBT, just so we can print a debugging message on systems that advertise DPCD backlight support on the panel but not in the VBT.
Changes since v3:
- Print a debugging message if we enable DPCD backlight control on a device which doesn't report DPCD backlight controls in it's VBT, instead of warning on custom panel backlight interfaces.
Signed-off-by: Lyude Paul lyude@redhat.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112376 Cc: Jani Nikula jani.nikula@intel.com Cc: Perry Yuan pyuan@redhat.com Cc: AceLan Kao acelan.kao@canonical.com
Thanks for the patch, pushed to dinq, fingers crossed! ;)
BR, Jani.
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 77a759361c5c..0f8edc775375 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -328,15 +328,16 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector) int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) { struct intel_panel *panel = &intel_connector->panel;
- struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
enum intel_backlight_type type =
to_i915(intel_connector->base.dev)->vbt.backlight.type;
if (i915_modparams.enable_dpcd_backlight == 0 || (i915_modparams.enable_dpcd_backlight == -1 &&
dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
return -ENODEV;!intel_dp_aux_display_control_capable(intel_connector)))
- if (!intel_dp_aux_display_control_capable(intel_connector))
return -ENODEV;
if (type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE)
DRM_DEBUG_DRIVER("Ignoring VBT backlight type\n");
panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.enable = intel_dp_aux_enable_backlight;
Turns out we actually already have some companies, such as Lenovo, shipping machines with AMOLED screens that don't allow controlling the backlight through the usual PWM interface and only allow controlling it through the standard EDP DPCD interface. One example of one of these laptops is the X1 Extreme 2nd Generation.
Since we've got systems that need this turned on by default now to have backlight controls working out of the box, let's start auto-detecting it for systems by default based on what the VBT tells us. We do this by changing the default value for the enable_dpcd_backlight module param from 0 to -1.
Tested-by: AceLan Kao acelan.kao@canonical.com Tested-by: Perry Yuan pyuan@redhat.com Signed-off-by: Lyude Paul lyude@redhat.com Signed-off-by: Jani Nikula jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_params.c | 2 +- drivers/gpu/drm/i915/i915_params.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 64009e99073d..905decc36e53 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -172,7 +172,7 @@ i915_param_named_unsafe(inject_probe_failure, uint, 0400,
i915_param_named(enable_dpcd_backlight, int, 0600, "Enable support for DPCD backlight control" - "(-1=use per-VBT LFP backlight type setting, 0=disabled [default], 1=enabled)"); + "(-1=use per-VBT LFP backlight type setting [default], 0=disabled, 1=enabled)");
#if IS_ENABLED(CONFIG_DRM_I915_GVT) i915_param_named(enable_gvt, bool, 0400, diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index be6089e4f9e6..947d0a38fa3c 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -66,7 +66,7 @@ struct drm_printer; param(int, reset, 3, 0600) \ param(unsigned int, inject_probe_failure, 0, 0600) \ param(int, fastboot, -1, 0600) \ - param(int, enable_dpcd_backlight, 0, 0600) \ + param(int, enable_dpcd_backlight, -1, 0600) \ param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE, 0400) \ param(unsigned long, fake_lmem_start, 0, 0400) \ /* leave bools at the end to not create holes */ \
dri-devel@lists.freedesktop.org