diff options
author | Alyssa Ross <hi@alyssa.is> | 2021-04-25 10:11:11 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2021-06-13 14:04:58 +0000 |
commit | bc6c46ea887b71c87c282c33deea4f55fb80efd1 (patch) | |
tree | 7f4a215047af054807f0b2d50ae60d8162bfdaf9 | |
parent | b7553992caa1001bd098855a033d3a2a74159c70 (diff) | |
download | nixlib-bc6c46ea887b71c87c282c33deea4f55fb80efd1.tar nixlib-bc6c46ea887b71c87c282c33deea4f55fb80efd1.tar.gz nixlib-bc6c46ea887b71c87c282c33deea4f55fb80efd1.tar.bz2 nixlib-bc6c46ea887b71c87c282c33deea4f55fb80efd1.tar.lz nixlib-bc6c46ea887b71c87c282c33deea4f55fb80efd1.tar.xz nixlib-bc6c46ea887b71c87c282c33deea4f55fb80efd1.tar.zst nixlib-bc6c46ea887b71c87c282c33deea4f55fb80efd1.zip |
sys/eve: fix backlight adjustment
-rw-r--r-- | overlays/patches/default.nix | 2 | ||||
-rw-r--r-- | overlays/patches/linux/eve-backlight.patch | 392 | ||||
-rw-r--r-- | overlays/patches/linux/patches.nix | 5 | ||||
-rw-r--r-- | sys/eve.nix | 5 |
4 files changed, 403 insertions, 1 deletions
diff --git a/overlays/patches/default.nix b/overlays/patches/default.nix index b7c2f7b7f6bd..63f5e53441e4 100644 --- a/overlays/patches/default.nix +++ b/overlays/patches/default.nix @@ -20,6 +20,8 @@ self: super: { gnupg = self.callPackage ./gnupg { inherit (super) gnupg; }; + kernelPatches = self.callPackage ./linux/patches.nix { inherit (super) kernelPatches; }; + public-inbox = self.callPackage ./public-inbox { inherit (super) public-inbox; }; diff --git a/overlays/patches/linux/eve-backlight.patch b/overlays/patches/linux/eve-backlight.patch new file mode 100644 index 000000000000..dcf1cc5505ea --- /dev/null +++ b/overlays/patches/linux/eve-backlight.patch @@ -0,0 +1,392 @@ +From 0154de6abf4f81c5d81b8391e931dc1f7071182f Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Sun, 25 Apr 2021 08:19:45 +0000 +Subject: [PATCH 1/2] Revert "drm/i915/vbt: Fix backlight parsing for VBT 234+" + +This reverts commit d381baad29b43511a7fc34c64402ef65029ab281. +--- + drivers/gpu/drm/i915/display/intel_bios.c | 30 ++----------------- + drivers/gpu/drm/i915/display/intel_vbt_defs.h | 12 ++------ + 2 files changed, 4 insertions(+), 38 deletions(-) + +diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c +index 4cc949b228f2d..f12975ef92428 100644 +--- a/drivers/gpu/drm/i915/display/intel_bios.c ++++ b/drivers/gpu/drm/i915/display/intel_bios.c +@@ -425,7 +425,6 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, + const struct bdb_lfp_backlight_data *backlight_data; + const struct lfp_backlight_data_entry *entry; + int panel_type = dev_priv->vbt.panel_type; +- u16 level; + + backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); + if (!backlight_data) +@@ -460,39 +459,14 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, + + dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; + dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; +- +- if (bdb->version >= 234) { +- u16 min_level; +- bool scale; +- +- level = backlight_data->brightness_level[panel_type].level; +- min_level = backlight_data->brightness_min_level[panel_type].level; +- +- if (bdb->version >= 236) +- scale = backlight_data->brightness_precision_bits[panel_type] == 16; +- else +- scale = level > 255; +- +- if (scale) +- min_level = min_level / 255; +- +- if (min_level > 255) { +- drm_warn(&dev_priv->drm, "Brightness min level > 255\n"); +- level = 255; +- } +- dev_priv->vbt.backlight.min_brightness = min_level; +- } else { +- level = backlight_data->level[panel_type]; +- dev_priv->vbt.backlight.min_brightness = entry->min_brightness; +- } +- ++ dev_priv->vbt.backlight.min_brightness = entry->min_brightness; + drm_dbg_kms(&dev_priv->drm, + "VBT backlight PWM modulation frequency %u Hz, " + "active %s, min brightness %u, level %u, controller %u\n", + dev_priv->vbt.backlight.pwm_freq_hz, + dev_priv->vbt.backlight.active_low_pwm ? "low" : "high", + dev_priv->vbt.backlight.min_brightness, +- level, ++ backlight_data->level[panel_type], + dev_priv->vbt.backlight.controller); + } + +diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h +index 49b4b5fca9411..9abdde1e68dc4 100644 +--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h ++++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h +@@ -782,7 +782,7 @@ struct lfp_backlight_data_entry { + u8 active_low_pwm:1; + u8 obsolete1:5; + u16 pwm_freq_hz; +- u8 min_brightness; /* Obsolete from 234+ */ ++ u8 min_brightness; + u8 obsolete2; + u8 obsolete3; + } __packed; +@@ -792,19 +792,11 @@ struct lfp_backlight_control_method { + u8 controller:4; + } __packed; + +-struct lfp_brightness_level { +- u16 level; +- u16 reserved; +-} __packed; +- + struct bdb_lfp_backlight_data { + u8 entry_size; + struct lfp_backlight_data_entry data[16]; +- u8 level[16]; /* Obsolete from 234+ */ ++ u8 level[16]; + struct lfp_backlight_control_method backlight_control[16]; +- struct lfp_brightness_level brightness_level[16]; /* 234+ */ +- struct lfp_brightness_level brightness_min_level[16]; /* 234+ */ +- u8 brightness_precision_bits[16]; /* 236+ */ + } __packed; + + /* +-- +2.31.0 + +From 280a1737103195768814b62e0b0b3d646a961c4a Mon Sep 17 00:00:00 2001 +From: Kevin Chowski <chowski@google.com> +Date: Sat, 8 Aug 2020 15:40:51 -0600 +Subject: [PATCH 2/2] 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> +(cherry picked from commit 37af4b996c1e25b7be4a00e5c5bcf29bc37cd51a) +--- + .../drm/i915/display/intel_dp_aux_backlight.c | 143 ++++++++++++++++-- + drivers/gpu/drm/i915/i915_params.c | 3 + + drivers/gpu/drm/i915/i915_params.h | 3 +- + 3 files changed, 139 insertions(+), 10 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 51d27fc98d483..d76888863e7cf 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c ++++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +@@ -141,10 +141,16 @@ 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 = intel_attached_dp(connector); +- const u8 pn = connector->panel.backlight.pwmgen_bit_count; +- int freq, fxp, f, fxp_actual, fxp_min, fxp_max; ++ int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1; ++ u8 pn, pn_min, pn_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_dbg_kms(&dev_priv->drm, ++ "VBT defined backlight frequency %u Hz\n", freq); + if (!freq) { + drm_dbg_kms(&dev_priv->drm, + "Use panel default backlight frequency\n"); +@@ -152,18 +158,50 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector) + } + + 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; + +- /* Ensure frequency is within 25% of desired value */ ++ /* 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_dbg_kms(&dev_priv->drm, ++ "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_dbg_kms(&dev_priv->drm, ++ "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; ++ + fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); + fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); +- +- if (fxp_min > fxp_actual || fxp_actual > fxp_max) { +- drm_dbg_kms(&dev_priv->drm, "Actual frequency out of range\n"); ++ if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) { ++ drm_dbg_kms(&dev_priv->drm, ++ "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_dbg_kms(&dev_priv->drm, ++ "Failed to write aux pwmgen bit count\n"); ++ return false; ++ } + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) { + drm_dbg_kms(&dev_priv->drm, +@@ -173,6 +211,26 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector) + return true; + } + ++/* ++ * 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_enable_backlight(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) + { +@@ -213,6 +271,16 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st + break; + } + ++ 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 (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP) + if (intel_dp_aux_set_pwm_freq(connector)) + new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; +@@ -342,7 +410,7 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector) + /* Check the eDP Display control capabilities registers to determine if + * the panel can support backlight control over the aux channel + */ +- if (intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP && ++ if ((intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP) && + (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) { + drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n"); + return true; +@@ -350,6 +418,59 @@ intel_dp_aux_display_control_capable(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, ++ ®_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; ++ ++} ++ + int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) + { + struct intel_panel *panel = &intel_connector->panel; +@@ -379,6 +500,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) + return -ENODEV; + } + ++ if (i915_modparams.enable_dpcd_backlight == -1 && ++ !intel_dp_aux_display_control_heuristic(intel_connector)) ++ return -ENODEV; ++ + panel->backlight.setup = intel_dp_aux_setup_backlight; + panel->backlight.enable = intel_dp_aux_enable_backlight; + panel->backlight.disable = intel_dp_aux_disable_backlight; +diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c +index 7f139ea4a90b2..378fc905f2b78 100644 +--- 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=enabled)"); + ++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 +index 330c03e2b4f70..2340889d87834 100644 +--- a/drivers/gpu/drm/i915/i915_params.h ++++ b/drivers/gpu/drm/i915/i915_params.h +@@ -80,7 +80,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, 0400) ++ param(bool, enable_gvt, false, 0400) \ ++ param(bool, enable_dbc, false, 0600) + + #define MEMBER(T, member, ...) T member; + struct i915_params { +-- +2.31.0 + diff --git a/overlays/patches/linux/patches.nix b/overlays/patches/linux/patches.nix new file mode 100644 index 000000000000..e7a7320f1e6c --- /dev/null +++ b/overlays/patches/linux/patches.nix @@ -0,0 +1,5 @@ +{ kernelPatches, ... } @ args: + +(kernelPatches.override (builtins.removeAttrs args [ "kernelPatches" ])) // { + eve-backlight = { name = "eve-backlight"; patch = ./eve-backlight.patch; }; +} diff --git a/sys/eve.nix b/sys/eve.nix index 9f0c8cc5cc1f..86b8c9c08045 100644 --- a/sys/eve.nix +++ b/sys/eve.nix @@ -8,7 +8,10 @@ hardware.enableRedistributableFirmware = true; - boot.kernelPackages = pkgs.linuxPackages_latest; + boot.kernelPackages = with pkgs; linuxPackagesFor (linux_latest.override { + kernelPatches = + linux_latest.kernelPatches ++ (with kernelPatches; [ eve-backlight ]); + }); boot.initrd.availableKernelModules = [ "nvme" "usb_storage" "sdhci_pci" ]; boot.kernelModules = [ "kvm-intel" ]; |