blob: 9c492978ac3050ef9108fbad8560b15d0bc7df30 [file] [log] [blame]
From f34383e25d63adcc9da38f3a476700a40555a232 Mon Sep 17 00:00:00 2001
From: Kevin Chowski <chowski@google.com>
Date: Sat, 8 Aug 2020 15:40:51 -0600
Subject: [PATCH] CHROMIUM: Changes needed for backlight control on Eve-5.4
#1: Port https://crrev.com/c/439873 to the 5.4 tree
#2: Port https://crrev.com/c/440445 to the 5.4 tree
#3: Port https://crrev.com/c/456118 to the 5.4 tree
The first two patches are needed to correctly enable the backlight for
Eve; they were submitted upstream in 2017 but were rolled back.
The third patch was not rolled back upstream, but the code related to it
changed quite a bit between 4.4 and 5.4: the write of
DP_EDP_PWMGEN_BIT_COUNT used to happen on every screen enable via
intel_dp_aux_set_pwm_freq (that's how it works in 4.4), but in 5.4 the
write was refactored into intel_dp_aux_calc_max_backlight and only
called once per screen setup. This patch brings back the old
functionality of intel_dp_aux_set_pwm_freq to ensure we set that
register on each screen enable, but this is at the cost of duplication
between intel_dp_aux_calc_max_backlight. Unfortunately, I don't see a
better way to do this without making the cros code diverge even further
from 4.4 and 5.4.
I'd like to submit this CL into the chromium tree, and use b/163412221
to track its upstreaming and the ultimate revert of this change.
Test:
* `emerge-eve-kernelnext sys-kernel/chromeos-kernel-5_4`
* `./update_kernel.sh --remote=192.168.0.22 --remote_bootarg`
* On DUT, set options `i915.enable_dpcd_backlight=1 i915.enable_dbc=1`
(using e.g. `/usr/share/vboot/bin/make_dev_ssd.sh`)
* reboot
* Change brightness on DUT
* Allow DUT screen to fall asleep
* Wake DUT screen, change brightness again
BUG=b:162255390
TEST=See above
Change-Id: I9eafa28226f1c6b8332fcf9730259bea05cf7975
Signed-off-by: Kevin Chowski <chowski@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2344844
Reviewed-by: Puthikorn Voravootivat <puthik@chromium.org>
Conflicts: drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
[rebase510(groeck): Picked code from continuous rebase project to resolve conflicts]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
---
drivers/gpu/drm/drm_dp_helper.c | 4 +
.../drm/i915/display/intel_dp_aux_backlight.c | 105 ++++++++++++++++++
drivers/gpu/drm/i915/i915_params.c | 3 +
drivers/gpu/drm/i915/i915_params.h | 3 +-
4 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -3301,6 +3301,10 @@ drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_inf
int ret;
u8 pn, pn_min, pn_max;
+ drm_dbg_kms(aux->drm_dev,
+ "VBT defined backlight frequency %u Hz\n",
+ driver_pwm_freq_hz);
+
ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT, &pn);
if (ret != 1) {
drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap: %d\n",
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -285,6 +285,26 @@ intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u3
drm_edp_backlight_set_level(&intel_dp->aux, &panel->backlight.edp.vesa.info, level);
}
+/*
+ * Set minimum / maximum dynamic brightness percentage. This value is expressed
+ * as the percentage of normal brightness in 5% increments.
+ */
+static bool
+intel_dp_aux_set_dynamic_backlight_percent(struct intel_dp *intel_dp,
+ u32 min, u32 max)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ u8 dbc[] = { DIV_ROUND_CLOSEST(min, 5), DIV_ROUND_CLOSEST(max, 5) };
+
+ if (drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET,
+ dbc, sizeof(dbc)) < 0) {
+ drm_dbg_kms(&i915->drm,
+ "Failed to write aux DBC brightness level\n");
+ return false;
+ }
+ return true;
+}
+
static void
intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state, u32 level)
@@ -292,6 +312,36 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state,
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct intel_panel *panel = &connector->panel;
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ u8 dpcd_buf, new_dpcd_buf;
+
+ if (drm_dp_dpcd_readb(&intel_dp->aux,
+ DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf) != 1) {
+ drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n",
+ DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
+ return;
+ }
+
+ new_dpcd_buf = dpcd_buf;
+
+ if (i915_modparams.enable_dbc &&
+ (intel_dp->edp_dpcd[2] & DP_EDP_DYNAMIC_BACKLIGHT_CAP)) {
+ if (intel_dp_aux_set_dynamic_backlight_percent(intel_dp,
+ 0, 100)) {
+ new_dpcd_buf |= DP_EDP_DYNAMIC_BACKLIGHT_ENABLE;
+ drm_dbg_kms(&i915->drm,
+ "Enable dynamic brightness.\n");
+ }
+ }
+
+ if (new_dpcd_buf != dpcd_buf) {
+ if (drm_dp_dpcd_writeb(&intel_dp->aux,
+ DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf) < 0) {
+ drm_dbg_kms(&i915->drm,
+ "Failed to write aux backlight mode\n");
+ }
+ }
+
drm_edp_backlight_enable(&intel_dp->aux, &panel->backlight.edp.vesa.info, level);
}
@@ -352,6 +402,59 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector)
return false;
}
+/*
+ * Heuristic function whether we should use AUX for backlight adjustment or not.
+ *
+ * We should use AUX for backlight brightness adjustment if panel doesn't this
+ * via PWM pin or using AUX is better than using PWM pin.
+ *
+ * The heuristic to determine that using AUX pin is better than using PWM pin is
+ * that the panel support any of the feature list here.
+ * - Regional backlight brightness adjustment
+ * - Backlight PWM frequency set
+ * - More than 8 bits resolution of brightness level
+ * - Backlight enablement via AUX and not by BL_ENABLE pin
+ *
+ * If all above are not true, assume that using PWM pin is better.
+ */
+static bool
+intel_dp_aux_display_control_heuristic(struct intel_connector *connector)
+{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ uint8_t reg_val;
+
+ /* Panel doesn't support adjusting backlight brightness via PWN pin */
+ if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP))
+ return true;
+
+ /* Panel supports regional backlight brightness adjustment */
+ if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_GENERAL_CAP_3,
+ &reg_val) != 1) {
+ drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n",
+ DP_EDP_GENERAL_CAP_3);
+ return false;
+ }
+ if (reg_val > 0)
+ return true;
+
+ /* Panel supports backlight PWM frequency set */
+ if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP)
+ return true;
+
+ /* Panel supports more than 8 bits resolution of brightness level */
+ if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
+ return true;
+
+ /* Panel supports enabling backlight via AUX but not by BL_ENABLE pin */
+ if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) &&
+ !(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_PIN_ENABLE_CAP))
+ return true;
+
+ return false;
+
+}
+
static const struct intel_panel_bl_funcs intel_dp_hdr_bl_funcs = {
.setup = intel_dp_aux_hdr_setup_backlight,
.enable = intel_dp_aux_hdr_enable_backlight,
@@ -401,6 +504,8 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
default:
return -ENODEV;
}
+ if (!intel_dp_aux_display_control_heuristic(connector))
+ return -ENODEV;
break;
case INTEL_DP_AUX_BACKLIGHT_ON:
if (i915->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE)
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -187,6 +187,9 @@ i915_param_named(enable_dpcd_backlight, int, 0400,
"Enable support for DPCD backlight control"
"(-1=use per-VBT LFP backlight type setting [default], 0=disabled, 1=enable, 2=force VESA interface, 3=force Intel interface)");
+i915_param_named(enable_dbc, bool, 0600,
+ "Enable support for dynamic backlight control (default:false)");
+
#if IS_ENABLED(CONFIG_DRM_I915_GVT)
i915_param_named(enable_gvt, bool, 0400,
"Enable support for Intel GVT-g graphics virtualization host support(default:false)");
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -82,7 +82,8 @@ struct drm_printer;
param(bool, verbose_state_checks, true, 0) \
param(bool, nuclear_pageflip, false, 0400) \
param(bool, enable_dp_mst, true, 0600) \
- param(bool, enable_gvt, false, IS_ENABLED(CONFIG_DRM_I915_GVT) ? 0400 : 0)
+ param(bool, enable_gvt, false, IS_ENABLED(CONFIG_DRM_I915_GVT) ? 0400 : 0) \
+ param(bool, enable_dbc, false, 0600)
#define MEMBER(T, member, ...) T member;
struct i915_params {
--
2.33.0.685.g46640cef36-goog