aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-legacy-oled-brightness.patch404
1 files changed, 234 insertions, 170 deletions
diff --git a/linux-legacy-oled-brightness.patch b/linux-legacy-oled-brightness.patch
index 4bd4982..b62d950 100644
--- a/linux-legacy-oled-brightness.patch
+++ b/linux-legacy-oled-brightness.patch
@@ -1,8 +1,8 @@
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index 3dda9f0eda82..ee413332a9ae 100644
+index ed05b131ed3a..65acc2170875 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
-@@ -328,6 +328,7 @@ i915-y += \
+@@ -329,6 +329,7 @@ i915-y += \
display/intel_dp.o \
display/intel_dp_aux.o \
display/intel_dp_aux_backlight.o \
@@ -11,7 +11,7 @@ index 3dda9f0eda82..ee413332a9ae 100644
display/intel_dp_link_training.o \
display/intel_dp_mst.o \
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
-index 8271e50e3644..de512541628f 100644
+index 99a6fd2900b9..92c56485e2b8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -50,6 +50,7 @@
@@ -22,7 +22,7 @@ index 8271e50e3644..de512541628f 100644
struct cec_notifier;
struct drm_printer;
-@@ -421,6 +422,9 @@ struct intel_panel {
+@@ -423,6 +424,9 @@ struct intel_panel {
bool supports_sdp_colorimetry;
bool supports_tone_mapping;
} intel_cap;
@@ -33,10 +33,10 @@ index 8271e50e3644..de512541628f 100644
struct backlight_device *device;
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 c846ef4acf5b..8a9eae55b362 100644
+index 8173de8aec63..2ddbf170cb1c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
-@@ -39,6 +39,7 @@
+@@ -41,6 +41,7 @@
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dp.h"
@@ -44,7 +44,7 @@ index c846ef4acf5b..8a9eae55b362 100644
#include "intel_dp_aux_backlight.h"
/*
-@@ -99,6 +100,7 @@ enum intel_dp_aux_backlight_modparam {
+@@ -101,6 +102,7 @@ enum intel_dp_aux_backlight_modparam {
INTEL_DP_AUX_BACKLIGHT_ON = 1,
INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2,
INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3,
@@ -52,8 +52,8 @@ index c846ef4acf5b..8a9eae55b362 100644
};
static bool is_intel_tcon_cap(const u8 tcon_cap[4])
-@@ -606,7 +608,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
- struct intel_display *display = to_intel_display(connector);
+@@ -702,7 +704,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = connector->base.dev;
struct intel_panel *panel = &connector->panel;
- bool try_intel_interface = false, try_vesa_interface = false;
@@ -61,7 +61,7 @@ index c846ef4acf5b..8a9eae55b362 100644
/* Check the VBT and user's module parameters to figure out which
* interfaces to probe
-@@ -638,6 +640,9 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
+@@ -734,6 +736,9 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
case INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL:
try_intel_interface = true;
break;
@@ -70,8 +70,8 @@ index c846ef4acf5b..8a9eae55b362 100644
+ break;
}
- /*
-@@ -667,5 +672,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
+ /* For eDP 1.5 and above we are supposed to use VESA interface for brightness control */
+@@ -768,5 +773,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
return 0;
}
@@ -84,32 +84,13 @@ index c846ef4acf5b..8a9eae55b362 100644
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_legacy_oled_brightness.c b/drivers/gpu/drm/i915/display/intel_dp_legacy_oled_brightness.c
new file mode 100644
-index 000000000000..e3df9b3338cb
+index 000000000000..3071f5b60940
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dp_legacy_oled_brightness.c
-@@ -0,0 +1,445 @@
+@@ -0,0 +1,509 @@
++// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Chris Xiong
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
+ */
+
+#include "intel_backlight.h"
@@ -121,20 +102,33 @@ index 000000000000..e3df9b3338cb
+#include "linux/slab.h"
+#include "linux/stdarg.h"
+
-+static bool intel_dp_aux_legacy_write_sequence(struct drm_dp_aux *aux, const u32 *address_seq, const u8 *value_seq, size_t length) {
-+ for (size_t p = 0; p < length; ++p) {
-+ drm_dbg_kms(aux->drm_dev, "intel_dp_aux_legacy_write_sequence: writing 0x%02x to 0x%x", value_seq[p], address_seq[p]);
-+ if (drm_dp_dpcd_writeb(aux, address_seq[p], value_seq[p]) < 1) {
++static bool intel_dp_aux_legacy_write_sequence(struct drm_dp_aux *aux,
++ const u32 *address_seq,
++ const u8 *value_seq,
++ size_t length)
++{
++ size_t p;
++
++ for (p = 0; p < length; ++p) {
++ drm_dbg_kms(aux->drm_dev, "%s: writing 0x%02x to 0x%x", __func__, value_seq[p],
++ address_seq[p]);
++ if (drm_dp_dpcd_writeb(aux, address_seq[p], value_seq[p]) < 1)
+ return false;
-+ }
+ }
+ return true;
+}
+
-+static bool intel_dp_aux_legacy_write_sequence_parameterized(struct drm_dp_aux *aux, const u32 *address_seq, const u8 *value_seq, size_t length, size_t nparameters, ...) {
++static bool intel_dp_aux_legacy_write_sequence_var(struct drm_dp_aux *aux,
++ const u32 *address_seq,
++ const u8 *value_seq,
++ size_t length,
++ size_t nparameters, ...)
++{
+ u8 *value_buf = NULL;
+ va_list args;
+ bool ret = false;
++ int pos, val;
++ size_t p;
+
+ if (!nparameters)
+ return intel_dp_aux_legacy_write_sequence(aux, address_seq, value_seq, length);
@@ -142,9 +136,9 @@ index 000000000000..e3df9b3338cb
+ memcpy(value_buf, value_seq, length);
+
+ va_start(args, nparameters);
-+ for (size_t p = 0; p < nparameters; ++p) {
-+ int pos = va_arg(args, int);
-+ int val = va_arg(args, int);
++ for (p = 0; p < nparameters; ++p) {
++ pos = va_arg(args, int);
++ val = va_arg(args, int);
+ if (pos >= 0 && pos < length)
+ value_buf[pos] = val;
+ }
@@ -155,109 +149,126 @@ index 000000000000..e3df9b3338cb
+ return ret;
+}
+
-+static bool intel_dp_aux_legacy_handshake(struct intel_connector *connector) {
++static bool intel_dp_aux_legacy_handshake(struct intel_connector *connector)
++{
+ struct intel_display *display = to_intel_display(connector);
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
+ struct drm_dp_aux *aux = &intel_dp->aux;
+ char *handshake_str = "PARAAUX-REG";
-+ u8 v;
++ u8 v, i, retries;
+ int ret;
+
+ ret = drm_dp_dpcd_readb(aux, 0x490, &v);
-+ if (ret < 1)
-+ drm_info(display->drm, "intel_dp_aux_legacy_handshake: read dpcd register 0x490 failed: %d", ret);
-+ else {
++ if (ret < 1) {
++ drm_info(display->drm, "%s: read dpcd register 0x490 failed: %d", __func__, ret);
++ } else {
+ if (v != 1) {
-+ for (int retries = 0; retries < 20; ++retries) {
-+ for (int p = 0; p < 11; ++p) {
-+ ret = drm_dp_dpcd_writeb(aux, 0x490, (u8)handshake_str[p]);
-+ if (ret < 1) break;
++ for (retries = 0; retries < 20; ++retries) {
++ for (i = 0; i < 11; ++i) {
++ ret = drm_dp_dpcd_writeb(aux, 0x490, (u8)handshake_str[i]);
++ if (ret < 1)
++ break;
+ }
+ ret = drm_dp_dpcd_readb(aux, 0x490, &v);
+ if (ret == 1 && v == 1)
+ return true;
+ }
-+ } else
++ } else {
+ return true;
++ }
+ }
-+ drm_err(display->drm, "intel_dp_aux_legacy_handshake: handshake failed");
++ drm_err(display->drm, "%s: handshake failed", __func__);
+ return false;
+}
+
-+static void intel_dp_aux_legacy_get_elvss_max_offset(struct intel_connector *connector) {
++static void intel_dp_aux_legacy_get_elvss_max_offset(struct intel_connector *connector)
++{
+ struct intel_display *display = to_intel_display(connector);
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
+ struct drm_dp_aux *aux = &intel_dp->aux;
-+ struct intel_legacy_panel_data *panel_data = &connector->panel.backlight.edp.legacy.panel_data;
-+ const u32 address_seq1[11] = {0x491, 0x492, 0x493, 0x491, 0x492, 0x493, 0x492, 0x493, 0x492, 0x493, 0x492};
-+ const u8 value_seq1[11] = { 0x02, 0x7f, 0x01, 0x07, 0xff, 0x04, 0x03, 0x04, 0x06, 0x26, 0x0a};
++ struct intel_panel *panel = &connector->panel;
++ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
++ const u32 address_seq1[11] = {0x491, 0x492, 0x493, 0x491, 0x492, 0x493, 0x492, 0x493,
++ 0x492, 0x493, 0x492};
++ const u8 value_seq1[11] = { 0x02, 0x7f, 0x01, 0x07, 0xff, 0x04, 0x03, 0x04,
++ 0x06, 0x26, 0x0a};
++
+ if (intel_dp_aux_legacy_handshake(connector)) {
+ if (!intel_dp_aux_legacy_write_sequence(aux, address_seq1, value_seq1, 11)) {
-+ drm_err(display->drm, "get_elvss_max_offset: write failed");
++ drm_err(display->drm, "%s: write failed", __func__);
+ return;
+ }
+ if (drm_dp_dpcd_readb(aux, 0x493, &panel_data->elvss_max_offset) < 1) {
-+ drm_err(display->drm, "get_elvss_max_offset: read failed");
++ drm_err(display->drm, "%s: read failed", __func__);
+ return;
+ }
-+ drm_dbg_kms(display->drm, "elvss_max_offset: %d", (int)panel_data->elvss_max_offset);
-+ } else
-+ drm_err(display->drm, "get_elvss_max_offset: handshake failed");
++ drm_dbg_kms(display->drm, "%s: ELVSS max offset: %d", __func__,
++ (int)panel_data->elvss_max_offset);
++ } else {
++ drm_err(display->drm, "%s: handshake failed", __func__);
++ }
+}
+
-+static bool intel_dp_aux_legacy_get_tcon_gamma(struct intel_connector *connector) {
++static bool intel_dp_aux_legacy_get_tcon_gamma(struct intel_connector *connector)
++{
+ struct intel_display *display = to_intel_display(connector);
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
+ struct drm_dp_aux *aux = &intel_dp->aux;
-+ struct intel_legacy_panel_data *panel_data = &connector->panel.backlight.edp.legacy.panel_data;
++ struct intel_panel *panel = &connector->panel;
++ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
+ struct intel_legacy_panel_data_intermediate *interm = panel_data->intermediates;
+
+ const u32 address_seq1[6] = {0x491, 0x492, 0x493, 0x491, 0x492, 0x493};
+ const u8 value_seq1[6] = { 0x2, 0x7f, 0x1, 0x7, 0xff, 0x4};
+ const u32 address_seq2[8] = {0x492, 0x493, 0x492, 0x493, 0x492, 0x493, 0x491, 0x492};
+ const u8 value_seq2[8] = { 0x0, 0, 0x1, 0, 0x2, 0, 0x7, 0xc};
++ u16 i, j, k;
+
+ if (!intel_dp_aux_legacy_handshake(connector)) {
-+ drm_err(display->drm, "get_tcon_gamma: handshake failed");
++ drm_err(display->drm, "%s: handshake failed", __func__);
+ return false;
+ }
+ if (!intel_dp_aux_legacy_write_sequence(aux, address_seq1, value_seq1, 6)) {
-+ drm_err(display->drm, "get_tcon_gamma: write failed");
++ drm_err(display->drm, "%s: write failed", __func__);
+ return false;
+ }
+ if (!interm) {
-+ drm_err(display->drm, "get_tcon_gamma: could not get hold of intermediate data");
++ drm_err(display->drm, "%s: could not get hold of intermediate data", __func__);
+ return false;
+ }
-+ for (u16 i = 0; i < 0x20; ++i) {
-+ u16 k = i * 0xb;
-+ for (u16 j = 0; j <= 0x20; ++j) {
-+ intel_dp_aux_legacy_write_sequence_parameterized(aux, address_seq2, value_seq2, 8, 3,
-+ 1, (j < 0xb ? 0x2 : (j < 0x16 ? 0x4 : 0x8)),
-+ 3, (u8)(k << 7),
-+ 5, (u8)(k >> 1));
-+ if (i == 0 && j == 0) udelay(100);
++ for (i = 0; i < 0x20; ++i) {
++ k = i * 0xb;
++ for (j = 0; j <= 0x20; ++j) {
++ intel_dp_aux_legacy_write_sequence_var(aux, address_seq2,
++ value_seq2, 8, 3,
++ 1, 1 << ((j / 11) + 1),
++ 3, (u8)(k << 7),
++ 5, (u8)(k >> 1));
++ if (i == 0 && j == 0)
++ udelay(100);
+ drm_dp_dpcd_readb(aux, 0x493, &interm->tcon_gamma[i][j]);
+ if (++k >= (i + 1) * 0xb)
+ k = i * 0xb;
+ }
+ }
++
+ u16 *vp = &interm->gamma_values[0][0];
+ u8 *gp = &interm->tcon_gamma[0][0];
-+ for (u16 i = 0; i < 0x20 ; ++i) {
-+ for (u16 j = 0; j <= 0x20; ++j) {
++
++ for (i = 0; i < 0x20 ; ++i) {
++ for (j = 0; j <= 0x20; ++j) {
+ switch (j) {
-+ case 0x7: case 0x12: case 0x1d:
-+ *vp = (u16)(*(gp + 2) & 0x80) * 2 | *gp;
-+ break;
-+ case 0x9: case 0x14: case 0x1f:
-+ *vp = *gp & 0x7f;
-+ break;
-+ case 0xa: case 0x15: case 0x20:
-+ *vp = *gp & 0xf;
-+ break;
-+ default:
-+ *vp = *gp;
++ case 0x7: case 0x12: case 0x1d:
++ *vp = (u16)(*(gp + 2) & 0x80) * 2 | *gp;
++ break;
++ case 0x9: case 0x14: case 0x1f:
++ *vp = *gp & 0x7f;
++ break;
++ case 0xa: case 0x15: case 0x20:
++ *vp = *gp & 0xf;
++ break;
++ default:
++ *vp = *gp;
+ }
+ ++vp;
+ ++gp;
@@ -266,11 +277,13 @@ index 000000000000..e3df9b3338cb
+ return true;
+}
+
-+static void intel_dp_aux_legacy_write_brightness(struct intel_connector *connector, u8 brightness) {
++static void intel_dp_aux_legacy_write_brightness(struct intel_connector *connector, u8 brightness)
++{
+ struct intel_display *display = to_intel_display(connector);
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
+ struct drm_dp_aux *aux = &intel_dp->aux;
-+ struct intel_legacy_panel_data *panel_data = &connector->panel.backlight.edp.legacy.panel_data;
++ struct intel_panel *panel = &connector->panel;
++ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
+ u8 *brightness_gamma = panel_data->interpolated_gamma[100 - brightness];
+ u32 *write_addr_buf = NULL;
+ u8 *write_val_buf = NULL;
@@ -282,42 +295,49 @@ index 000000000000..e3df9b3338cb
+ const u8 value_seq3[7] = { 0x0e, 0x80, 0, 0x90, 0, 0x91, 0};
+ const u32 address_seq4[6] = {0x491, 0x492, 0x493, 0x491, 0x492, 0x493};
+ const u8 value_seq4[6] = { 0x02, 0x7f, 0x01, 0x07, 0xff, 0x04};
-+ const u32 address_seq5[14] = {0x492, 0x493, 0x491, 0x492, 0x493, 0x491, 0x492, 0x493, 0x492, 0x493, 0x491, 0x492, 0x493, 0x491};
-+ const u8 value_seq5[14] = { 0x32, 0x01, 0x02, 0xeb, 0x91, 0x09, 0xf0, 0xef, 0xf9, 0, 0x02, 0xeb, 0x96, 0x0e};
++ const u32 address_seq5[14] = {0x492, 0x493, 0x491, 0x492, 0x493, 0x491, 0x492,
++ 0x493, 0x492, 0x493, 0x491, 0x492, 0x493, 0x491};
++ const u8 value_seq5[14] = { 0x32, 0x01, 0x02, 0xeb, 0x91, 0x09, 0xf0,
++ 0xef, 0xf9, 0, 0x02, 0xeb, 0x96, 0x0e};
++ u16 i, acl_data;
+
+ if (!intel_dp_aux_legacy_handshake(connector)) {
-+ drm_err(display->drm, "write_brightness: handshake failed");
++ drm_err(display->drm, "%s: handshake failed", __func__);
+ return;
+ }
-+ drm_dbg_kms(display->drm, "write_brightness %3d", brightness);
++ drm_dbg_kms(display->drm, "%s: new brightness: %3d", __func__, brightness);
+
-+ if (!intel_dp_aux_legacy_write_sequence_parameterized(aux, address_seq1, value_seq1, 7, 2,
-+ 4, panel_data->aor_buf[brightness * 2], //LSB of AOR[brightness]
-+ 6, panel_data->aor_buf[brightness * 2 + 1])) //MSB of AOR[brightness]
++ if (!intel_dp_aux_legacy_write_sequence_var(aux, address_seq1, value_seq1, 7, 2,
++ 4, panel_data->aor_buf[brightness * 2],
++ 6, panel_data->aor_buf[brightness * 2 + 1]))
+ goto fail;
+
-+ if (!intel_dp_aux_legacy_write_sequence_parameterized(aux, address_seq2, value_seq2, 7, 2,
-+ 4, panel_data->delvss[brightness],
-+ 6, panel_data->elvss_max_offset))
++ if (!intel_dp_aux_legacy_write_sequence_var(aux, address_seq2, value_seq2, 7, 2,
++ 4, panel_data->delvss[brightness],
++ 6, panel_data->elvss_max_offset))
+ goto fail;
+
+ if (brightness > panel_data->brightness_for_acl) {
-+ if (!intel_dp_aux_legacy_write_sequence_parameterized(aux, address_seq3, value_seq3, 7, 3,
-+ 2, 0x90,
-+ 4, panel_data->acl_cutoff_and_delta_buf[(brightness - panel_data->brightness_for_acl - 1) * 2], // LSB of ACLCutoffAndDelta[brightness - brightness_acl - 1]
-+ 6, panel_data->acl_cutoff_and_delta_buf[(brightness - panel_data->brightness_for_acl - 1) * 2 + 1])) // MSB of ACLCutoffAndDelta[brightness - brightness_acl - 1]
++ acl_data = __le16_to_cpu(((u16 *)panel_data->acl_cutoff_and_delta_buf)
++ [brightness - panel_data->brightness_for_acl - 1]);
++ if (!intel_dp_aux_legacy_write_sequence_var(aux, address_seq3, value_seq3, 7, 3,
++ 2, 0x90,
++ 4, acl_data & 0xff,
++ 6, acl_data >> 8))
+ goto fail;
+ } else {
-+ if (!intel_dp_aux_legacy_write_sequence_parameterized(aux, address_seq3, value_seq3, 3, 1,
-+ 2, 0x80))
++ if (!intel_dp_aux_legacy_write_sequence_var(aux, address_seq3, value_seq3,
++ 3, 1, 2, 0x80))
+ goto fail;
+ }
+
-+ if (!intel_dp_aux_legacy_write_sequence(aux, address_seq4, value_seq4, 6)) goto fail;
-+ drm_dbg_kms(display->drm, "brightness_gamma @ %d: %*ph\n", 100 - brightness, 33, brightness_gamma);
++ if (!intel_dp_aux_legacy_write_sequence(aux, address_seq4, value_seq4, 6))
++ goto fail;
++ drm_dbg_kms(display->drm, "brightness_gamma @ %d: %*ph\n", 100 - brightness, 33,
++ brightness_gamma);
+ write_addr_buf = kmalloc_array(0x21 * 2, 4, GFP_KERNEL);
+ write_val_buf = kmalloc_array(0x21 * 2, 1, GFP_KERNEL);
-+ for (int i = 0; i <= 0x20; ++i) {
++ for (i = 0; i <= 0x20; ++i) {
+ write_addr_buf[i * 2] = 0x492;
+ write_addr_buf[i * 2 + 1] = 0x493;
+ write_val_buf[i * 2] = i + 0x10;
@@ -329,10 +349,10 @@ index 000000000000..e3df9b3338cb
+ if (!intel_dp_aux_legacy_write_sequence(aux, write_addr_buf, write_val_buf, 0x21 * 2))
+ goto fail;
+ udelay(1000);
-+ if (!intel_dp_aux_legacy_write_sequence_parameterized(aux, address_seq5, value_seq5, 14, 1,
-+ 9, panel_data->SP[brightness]))
++ if (!intel_dp_aux_legacy_write_sequence_var(aux, address_seq5, value_seq5, 14, 1,
++ 9, panel_data->SP[brightness]))
+ goto fail;
-+ for (int i = 0; i < 9; ++i) {
++ for (i = 0; i < 9; ++i) {
+ //reuse current data in write_addr_buf
+ //as well as values written to 0x492
+ write_val_buf[i * 2 + 1] = panel_data->IRC[brightness][i];
@@ -343,74 +363,109 @@ index 000000000000..e3df9b3338cb
+ kfree(write_val_buf);
+ return;
+fail:
-+ if (write_addr_buf)
-+ kfree(write_addr_buf);
-+ if (write_val_buf)
-+ kfree(write_val_buf);
-+ drm_err(display->drm, "write_brightness: failed to write dpcd registers");
++ kfree(write_addr_buf);
++ kfree(write_val_buf);
++ drm_err(display->drm, "%s: failed to write dpcd registers", __func__);
+}
+
+inline s16 sign(s16 v) { return v < 0 ? -1 : 1; }
+
-+static void intel_dp_aux_legacy_calculate_interpolated_values(struct intel_connector *connector) {
++static void intel_dp_aux_legacy_calculate_interpolated_values(struct intel_connector *connector)
++{
+ struct intel_display *display = to_intel_display(connector);
-+ struct intel_legacy_panel_data *panel_data = &connector->panel.backlight.edp.legacy.panel_data;
++ struct intel_panel *panel = &connector->panel;
++ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
+ struct intel_legacy_panel_data_intermediate *interm = panel_data->intermediates;
+
+ s16 dv;
+ u8 old_d;
+ u8 base, delta, multiplier, bias, attenuation;
-+ for (int i = 0; i <= 0x20; ++i) {
++ u16 i, j, br;
++
++ for (i = 0; i <= 0x20; ++i) {
+ old_d = 0xff;
-+ for (int br = 0; br <= 100; ++br) {
++ for (br = 0; br <= 100; ++br) {
+ base = interm->interpolation[br][0];
+ delta = interm->interpolation[br][1];
+ multiplier = interm->interpolation[br][2];
+ bias = interm->interpolation[br][3];
+ attenuation = interm->interpolation[br][4];
+ if (old_d != delta) {
-+ dv = interm->gamma_values[delta][i] - interm->gamma_values[delta + 1][i];
++ dv = interm->gamma_values[delta][i] -
++ interm->gamma_values[delta + 1][i];
+ old_d = delta;
+ }
-+ if (unlikely(attenuation == 0)) attenuation = 1;
-+ interm->interpolated_values[br][i] = interm->gamma_values[base][i] + sign(dv) * (abs(dv * multiplier) + bias) / attenuation;
++ if (unlikely(attenuation == 0))
++ attenuation = 1;
++ interm->interpolated_values[br][i] =
++ interm->gamma_values[base][i] +
++ sign(dv) * (abs(dv * multiplier) + bias) / attenuation;
+ }
+ }
+
+ u8 *pint_gamma = &panel_data->interpolated_gamma[0][0];
+ u16 *pint_values = &interm->interpolated_values[0][0];
+
-+ for (int i = 0; i < 101; ++i) {
-+ for (int j = 0; j <= 32; ++j) {
++ for (i = 0; i < 101; ++i) {
++ for (j = 0; j <= 32; ++j) {
+ switch (j) {
-+ case 9: case 20: case 31:
-+ *pint_gamma = (((u8)*(pint_values - 2) >> 1 ^ (u8)*pint_values) & 0x7f) ^ (u8)(*(pint_values - 2) >> 1);
-+ break;
-+ case 10: case 21: case 32:
-+ *pint_gamma = (u8)*pint_values & 0xf;
-+ break;
-+ default:
-+ *pint_gamma = (u8)*pint_values;
++ case 9: case 20: case 31:
++ *pint_gamma =
++ (((u8)*(pint_values - 2) >> 1 ^ (u8)*pint_values) & 0x7f) ^
++ (u8)(*(pint_values - 2) >> 1);
++ break;
++ case 10: case 21: case 32:
++ *pint_gamma = (u8)*pint_values & 0xf;
++ break;
++ default:
++ *pint_gamma = (u8)*pint_values;
+ }
+ ++pint_gamma;
+ ++pint_values;
+ }
+ }
-+ for (int i = 0; i < 101; ++i) {
-+ drm_dbg_kms(display->drm, "interpolated gamma %3d %*phN", i, 33, panel_data->interpolated_gamma[i]);
-+ }
++ for (i = 0; i < 101; ++i)
++ drm_dbg_kms(display->drm, "interpolated gamma %3d %*phN",
++ i, 33, panel_data->interpolated_gamma[i]);
++}
++
++static bool fw_read_data(const struct firmware *fw,
++ const u8 **read_ptr,
++ void *output,
++ u32 expected_length)
++{
++ if (fw->size - (*read_ptr - fw->data) < expected_length)
++ return false;
++ memcpy(output, *read_ptr, expected_length);
++ *read_ptr += expected_length;
++ return true;
++}
++
++static bool fw_read_array(const struct firmware *fw,
++ const u8 **read_ptr,
++ void *output,
++ u32 max_length)
++{
++ u16 len;
++
++ if (!fw_read_data(fw, read_ptr, &len, 2))
++ return false;
++ len = __le16_to_cpu(len);
++ if (len > max_length)
++ return false;
++ return fw_read_data(fw, read_ptr, output, len);
+}
+
+static int intel_dp_aux_legacy_load_panel_properties(struct intel_connector *connector)
+{
+ struct intel_display *display = to_intel_display(connector);
+ struct device *dev = connector->encoder->base.dev->dev;
-+ struct intel_legacy_panel_data *panel_data = &connector->panel.backlight.edp.legacy.panel_data;
++ struct intel_panel *panel = &connector->panel;
++ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
+ struct intel_legacy_panel_data_intermediate *interm = panel_data->intermediates;
+ int ret;
+ const struct firmware *fw;
+ const u8 *pdata;
-+ u16 len;
+
+ ret = request_firmware(&fw, "intel_legacy_panel_data.bin", dev);
+ if (ret < 0)
@@ -418,28 +473,23 @@ index 000000000000..e3df9b3338cb
+ ret = 0;
+ pdata = fw->data;
+
-+#define load_array(arr, maxlen) \
-+ if (fw->size - (pdata - fw->data) < 2) goto fail_invalid_data; \
-+ memcpy(&len, pdata, 2); \
-+ pdata += 2; \
-+ len = __le16_to_cpu(len); \
-+ if (len > maxlen) goto fail_invalid_data; \
-+ if (fw->size - (pdata - fw->data) < len) goto fail_invalid_data; \
-+ memcpy(arr, pdata, len); \
-+ pdata += len;
-+
-+ load_array(panel_data->aor_buf, 202);
-+ load_array(panel_data->delvss, 101);
-+
-+ if (fw->size - (pdata - fw->data) < 2) goto fail_invalid_data;
-+ memcpy(&panel_data->brightness_for_acl, pdata, 2);
-+ pdata += 2;
++ if (!fw_read_array(fw, &pdata, panel_data->aor_buf, 202))
++ goto fail_invalid_data;
++ if (!fw_read_array(fw, &pdata, panel_data->delvss, 101))
++ goto fail_invalid_data;
++
++ if (!fw_read_data(fw, &pdata, &panel_data->brightness_for_acl, 2))
++ goto fail_invalid_data;
+ panel_data->brightness_for_acl = __le16_to_cpu(panel_data->brightness_for_acl);
+
-+ load_array(panel_data->acl_cutoff_and_delta_buf, 200);
-+ load_array(panel_data->IRC, 909);
-+ load_array(panel_data->SP, 101);
-+ load_array(interm->interpolation, 505);
++ if (!fw_read_array(fw, &pdata, panel_data->acl_cutoff_and_delta_buf, 200))
++ goto fail_invalid_data;
++ if (!fw_read_array(fw, &pdata, panel_data->IRC, 909))
++ goto fail_invalid_data;
++ if (!fw_read_array(fw, &pdata, panel_data->SP, 101))
++ goto fail_invalid_data;
++ if (!fw_read_array(fw, &pdata, interm->interpolation, 505))
++ goto fail_invalid_data;
+
+ release_firmware(fw);
+ return ret;
@@ -452,10 +502,15 @@ index 000000000000..e3df9b3338cb
+static int intel_dp_aux_legacy_setup_backlight(struct intel_connector *connector, enum pipe unused)
+{
+ struct intel_panel *panel = &connector->panel;
-+ struct intel_legacy_panel_data *panel_data = &connector->panel.backlight.edp.legacy.panel_data;
++ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
+ int ret;
+
-+ panel_data->intermediates = kzalloc(sizeof(struct intel_legacy_panel_data_intermediate), GFP_KERNEL);
++ panel_data->intermediates = kzalloc(sizeof(struct intel_legacy_panel_data_intermediate),
++ GFP_KERNEL);
++ if (!panel_data->intermediates) {
++ ret = -ENOMEM;
++ goto fail;
++ }
+ ret = intel_dp_aux_legacy_load_panel_properties(connector);
+ if (ret < 0)
+ goto fail;
@@ -483,7 +538,9 @@ index 000000000000..e3df9b3338cb
+ u32 level)
+{
+ struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
-+ struct intel_legacy_panel_data *panel_data = &connector->panel.backlight.edp.legacy.panel_data;
++ struct intel_panel *panel = &connector->panel;
++ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
++
+ if (!panel_data->values_initialized)
+ intel_dp_aux_legacy_setup_backlight(connector, PIPE_A);
+ intel_dp_aux_legacy_write_brightness(connector, 0);
@@ -495,7 +552,9 @@ index 000000000000..e3df9b3338cb
+ struct intel_connector *connector = to_intel_connector(conn_state->connector);
+ struct intel_panel *panel = &connector->panel;
+ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
-+ if (level > 100) level = 100;
++
++ if (level > 100)
++ level = 100;
+ panel->backlight.level = level;
+ if (!panel_data->values_initialized)
+ intel_dp_aux_legacy_setup_backlight(connector, PIPE_A);
@@ -504,6 +563,7 @@ index 000000000000..e3df9b3338cb
+static u32 intel_dp_aux_legacy_get_backlight(struct intel_connector *connector, enum pipe unused)
+{
+ struct intel_panel *panel = &connector->panel;
++
+ return panel->backlight.level;
+}
+static void
@@ -512,7 +572,9 @@ index 000000000000..e3df9b3338cb
+ struct intel_connector *connector = to_intel_connector(conn_state->connector);
+ struct intel_panel *panel = &connector->panel;
+ struct intel_legacy_panel_data *panel_data = &panel->backlight.edp.legacy.panel_data;
-+ if (level > 100) level = 100;
++
++ if (level > 100)
++ level = 100;
+ panel->backlight.level = level;
+ if (!panel_data->values_initialized)
+ intel_dp_aux_legacy_setup_backlight(connector, PIPE_A);
@@ -527,15 +589,17 @@ index 000000000000..e3df9b3338cb
+ .get = intel_dp_aux_legacy_get_backlight,
+};
+
-+const struct intel_panel_bl_funcs* intel_dp_aux_legacy_get_bl_funcs(void) {
++const struct intel_panel_bl_funcs *intel_dp_aux_legacy_get_bl_funcs(void)
++{
+ return &intel_dp_aux_legacy_bl_funcs;
+}
-+bool intel_dp_aux_legacy_brightness_supported(struct intel_connector *connector) {
++bool intel_dp_aux_legacy_brightness_supported(struct intel_connector *connector)
++{
+ return intel_dp_aux_legacy_handshake(connector);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_legacy_oled_brightness.h b/drivers/gpu/drm/i915/display/intel_dp_legacy_oled_brightness.h
new file mode 100644
-index 000000000000..785509e608c8
+index 000000000000..16f1f5185121
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dp_legacy_oled_brightness.h
@@ -0,0 +1,40 @@
@@ -572,10 +636,10 @@ index 000000000000..785509e608c8
+ u8 interpolated_gamma[101][33];
+ u8 elvss_max_offset;
+ bool values_initialized;
-+ struct intel_legacy_panel_data_intermediate* intermediates;
++ struct intel_legacy_panel_data_intermediate *intermediates;
+};
+
-+const struct intel_panel_bl_funcs* intel_dp_aux_legacy_get_bl_funcs(void);
++const struct intel_panel_bl_funcs *intel_dp_aux_legacy_get_bl_funcs(void);
+bool intel_dp_aux_legacy_brightness_supported(struct intel_connector *connector);
+
+#endif /* __INTEL_DP_LEGACY_OLED_BRIGHTNESS_H__ */