--- /dev/null
+From 69741d9ccc7222e6b6f138db67b012ecc0d72542 Mon Sep 17 00:00:00 2001
+From: Ray Wu <ray.wu@amd.com>
+Date: Fri, 28 Nov 2025 08:58:13 +0800
+Subject: drm/amd/display: Fix scratch registers offsets for DCN35
+
+From: Ray Wu <ray.wu@amd.com>
+
+commit 69741d9ccc7222e6b6f138db67b012ecc0d72542 upstream.
+
+[Why]
+Different platforms use differnet NBIO header files,
+causing display code to use differnt offset and read
+wrong accelerated status.
+
+[How]
+- Unified NBIO offset header file across platform.
+- Correct scratch registers offsets to proper locations.
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4667
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 49a63bc8eda0304ba307f5ba68305f936174f72d)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+@@ -203,12 +203,12 @@ enum dcn35_clk_src_array_id {
+ NBIO_BASE_INNER(seg)
+
+ #define NBIO_SR(reg_name)\
+- REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
+- regBIF_BX2_ ## reg_name
++ REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
++ regBIF_BX1_ ## reg_name
+
+ #define NBIO_SR_ARR(reg_name, id)\
+- REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
+- regBIF_BX2_ ## reg_name
++ REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
++ regBIF_BX1_ ## reg_name
+
+ #define bios_regs_init() \
+ ( \
--- /dev/null
+From fd62aa13d3ee0f21c756a40a7c2f900f98992d6a Mon Sep 17 00:00:00 2001
+From: Ray Wu <ray.wu@amd.com>
+Date: Fri, 28 Nov 2025 09:14:09 +0800
+Subject: drm/amd/display: Fix scratch registers offsets for DCN351
+
+From: Ray Wu <ray.wu@amd.com>
+
+commit fd62aa13d3ee0f21c756a40a7c2f900f98992d6a upstream.
+
+[Why]
+Different platforms use different NBIO header files,
+causing display code to use differnt offset and read
+wrong accelerated status.
+
+[How]
+- Unified NBIO offset header file across platform.
+- Correct scratch registers offsets to proper locations.
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4667
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 576e032e909c8a6bb3d907b4ef5f6abe0f644199)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+@@ -183,12 +183,12 @@ enum dcn351_clk_src_array_id {
+ NBIO_BASE_INNER(seg)
+
+ #define NBIO_SR(reg_name)\
+- REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
+- regBIF_BX2_ ## reg_name
++ REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
++ regBIF_BX1_ ## reg_name
+
+ #define NBIO_SR_ARR(reg_name, id)\
+- REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
+- regBIF_BX2_ ## reg_name
++ REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
++ regBIF_BX1_ ## reg_name
+
+ #define bios_regs_init() \
+ ( \
--- /dev/null
+From 3c41114dcdabb7b25f5bc33273c6db9c7af7f4a7 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 11 Nov 2025 11:17:22 -0500
+Subject: drm/amd/display: Use GFP_ATOMIC in dc_create_plane_state()
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 3c41114dcdabb7b25f5bc33273c6db9c7af7f4a7 upstream.
+
+This can get called from an atomic context.
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4470
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 8acdad9344cc7b4e7bc01f0dfea80093eb3768db)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+@@ -86,7 +86,7 @@ uint8_t dc_plane_get_pipe_mask(struct d
+ struct dc_plane_state *dc_create_plane_state(const struct dc *dc)
+ {
+ struct dc_plane_state *plane_state = kvzalloc(sizeof(*plane_state),
+- GFP_KERNEL);
++ GFP_ATOMIC);
+
+ if (NULL == plane_state)
+ return NULL;
--- /dev/null
+From 520f37c30992fd0c212a34fbe99c062b7a3dc52e Mon Sep 17 00:00:00 2001
+From: Jani Nikula <jani.nikula@intel.com>
+Date: Tue, 28 Oct 2025 22:07:25 +0200
+Subject: drm/displayid: pass iter to drm_find_displayid_extension()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+commit 520f37c30992fd0c212a34fbe99c062b7a3dc52e upstream.
+
+It's more convenient to pass iter than a handful of its members to
+drm_find_displayid_extension(), especially as we're about to add another
+member.
+
+Rename the function find_next_displayid_extension() while at it, to be
+more descriptive.
+
+Cc: Tiago Martins Araújo <tiago.martins.araujo@gmail.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Tested-by: Tiago Martins Araújo <tiago.martins.araujo@gmail.com>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/3837ae7f095e77a082ac2422ce2fac96c4f9373d.1761681968.git.jani.nikula@intel.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_displayid.c | 19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+--- a/drivers/gpu/drm/drm_displayid.c
++++ b/drivers/gpu/drm/drm_displayid.c
+@@ -48,26 +48,24 @@ validate_displayid(const u8 *displayid,
+ return base;
+ }
+
+-static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid,
+- int *length, int *idx,
+- int *ext_index)
++static const u8 *find_next_displayid_extension(struct displayid_iter *iter)
+ {
+ const struct displayid_header *base;
+ const u8 *displayid;
+
+- displayid = drm_edid_find_extension(drm_edid, DISPLAYID_EXT, ext_index);
++ displayid = drm_edid_find_extension(iter->drm_edid, DISPLAYID_EXT, &iter->ext_index);
+ if (!displayid)
+ return NULL;
+
+ /* EDID extensions block checksum isn't for us */
+- *length = EDID_LENGTH - 1;
+- *idx = 1;
++ iter->length = EDID_LENGTH - 1;
++ iter->idx = 1;
+
+- base = validate_displayid(displayid, *length, *idx);
++ base = validate_displayid(displayid, iter->length, iter->idx);
+ if (IS_ERR(base))
+ return NULL;
+
+- *length = *idx + sizeof(*base) + base->bytes;
++ iter->length = iter->idx + sizeof(*base) + base->bytes;
+
+ return displayid;
+ }
+@@ -126,10 +124,7 @@ __displayid_iter_next(struct displayid_i
+ /* The first section we encounter is the base section */
+ bool base_section = !iter->section;
+
+- iter->section = drm_find_displayid_extension(iter->drm_edid,
+- &iter->length,
+- &iter->idx,
+- &iter->ext_index);
++ iter->section = find_next_displayid_extension(iter);
+ if (!iter->section) {
+ iter->drm_edid = NULL;
+ return NULL;
--- /dev/null
+From 72e24456a54fe04710d89626cc5a88703e2f6202 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Tue, 9 Dec 2025 11:14:47 -0600
+Subject: Revert "drm/amd/display: Fix pbn to kbps Conversion"
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+commit 72e24456a54fe04710d89626cc5a88703e2f6202 upstream.
+
+Deeply daisy chained DP/MST displays are no longer able to light
+up. This reverts commit e0dec00f3d05 ("drm/amd/display: Fix pbn
+to kbps Conversion")
+
+Cc: Jerry Zuo <jerry.zuo@amd.com>
+Reported-by: nat@nullable.se
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4756
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit e1c94109c76e8a77a21531bd53f6c63356c81158)
+Cc: stable@vger.kernel.org # 6.17+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 59 +++++++-----
+ 1 file changed, 36 insertions(+), 23 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -884,28 +884,26 @@ struct dsc_mst_fairness_params {
+ };
+
+ #if defined(CONFIG_DRM_AMD_DC_FP)
+-static uint64_t kbps_to_pbn(int kbps, bool is_peak_pbn)
++static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link)
+ {
+- uint64_t effective_kbps = (uint64_t)kbps;
++ u8 link_coding_cap;
++ uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B;
+
+- if (is_peak_pbn) { // add 0.6% (1006/1000) overhead into effective kbps
+- effective_kbps *= 1006;
+- effective_kbps = div_u64(effective_kbps, 1000);
+- }
++ link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link);
++ if (link_coding_cap == DP_128b_132b_ENCODING)
++ fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B;
+
+- return (uint64_t) DIV64_U64_ROUND_UP(effective_kbps * 64, (54 * 8 * 1000));
++ return fec_overhead_multiplier_x1000;
+ }
+
+-static uint32_t pbn_to_kbps(unsigned int pbn, bool with_margin)
++static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000)
+ {
+- uint64_t pbn_effective = (uint64_t)pbn;
+-
+- if (with_margin) // deduct 0.6% (994/1000) overhead from effective pbn
+- pbn_effective *= (1000000 / PEAK_FACTOR_X1000);
+- else
+- pbn_effective *= 1000;
++ u64 peak_kbps = kbps;
+
+- return DIV_U64_ROUND_UP(pbn_effective * 8 * 54, 64);
++ peak_kbps *= 1006;
++ peak_kbps *= fec_overhead_multiplier_x1000;
++ peak_kbps = div_u64(peak_kbps, 1000 * 1000);
++ return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000));
+ }
+
+ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *params,
+@@ -976,7 +974,7 @@ static int bpp_x16_from_pbn(struct dsc_m
+ dc_dsc_get_default_config_option(param.sink->ctx->dc, &dsc_options);
+ dsc_options.max_target_bpp_limit_override_x16 = drm_connector->display_info.max_dsc_bpp * 16;
+
+- kbps = pbn_to_kbps(pbn, false);
++ kbps = div_u64((u64)pbn * 994 * 8 * 54, 64);
+ dc_dsc_compute_config(
+ param.sink->ctx->dc->res_pool->dscs[0],
+ ¶m.sink->dsc_caps.dsc_dec_caps,
+@@ -1005,11 +1003,12 @@ static int increase_dsc_bpp(struct drm_a
+ int link_timeslots_used;
+ int fair_pbn_alloc;
+ int ret = 0;
++ uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
+
+ for (i = 0; i < count; i++) {
+ if (vars[i + k].dsc_enabled) {
+ initial_slack[i] =
+- kbps_to_pbn(params[i].bw_range.max_kbps, false) - vars[i + k].pbn;
++ kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn;
+ bpp_increased[i] = false;
+ remaining_to_increase += 1;
+ } else {
+@@ -1105,6 +1104,7 @@ static int try_disable_dsc(struct drm_at
+ int next_index;
+ int remaining_to_try = 0;
+ int ret;
++ uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
+ int var_pbn;
+
+ for (i = 0; i < count; i++) {
+@@ -1137,7 +1137,7 @@ static int try_disable_dsc(struct drm_at
+
+ DRM_DEBUG_DRIVER("MST_DSC index #%d, try no compression\n", next_index);
+ var_pbn = vars[next_index].pbn;
+- vars[next_index].pbn = kbps_to_pbn(params[next_index].bw_range.stream_kbps, true);
++ vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
+ ret = drm_dp_atomic_find_time_slots(state,
+ params[next_index].port->mgr,
+ params[next_index].port,
+@@ -1197,6 +1197,7 @@ static int compute_mst_dsc_configs_for_l
+ int count = 0;
+ int i, k, ret;
+ bool debugfs_overwrite = false;
++ uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
+ struct drm_connector_state *new_conn_state;
+
+ memset(params, 0, sizeof(params));
+@@ -1277,7 +1278,7 @@ static int compute_mst_dsc_configs_for_l
+ DRM_DEBUG_DRIVER("MST_DSC Try no compression\n");
+ for (i = 0; i < count; i++) {
+ vars[i + k].aconnector = params[i].aconnector;
+- vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false);
++ vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
+ vars[i + k].dsc_enabled = false;
+ vars[i + k].bpp_x16 = 0;
+ ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
+@@ -1299,7 +1300,7 @@ static int compute_mst_dsc_configs_for_l
+ DRM_DEBUG_DRIVER("MST_DSC Try max compression\n");
+ for (i = 0; i < count; i++) {
+ if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) {
+- vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.min_kbps, false);
++ vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000);
+ vars[i + k].dsc_enabled = true;
+ vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
+ ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+@@ -1307,7 +1308,7 @@ static int compute_mst_dsc_configs_for_l
+ if (ret < 0)
+ return ret;
+ } else {
+- vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false);
++ vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
+ vars[i + k].dsc_enabled = false;
+ vars[i + k].bpp_x16 = 0;
+ ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+@@ -1762,6 +1763,18 @@ clean_exit:
+ return ret;
+ }
+
++static uint32_t kbps_from_pbn(unsigned int pbn)
++{
++ uint64_t kbps = (uint64_t)pbn;
++
++ kbps *= (1000000 / PEAK_FACTOR_X1000);
++ kbps *= 8;
++ kbps *= 54;
++ kbps /= 64;
++
++ return (uint32_t)kbps;
++}
++
+ static bool is_dsc_common_config_possible(struct dc_stream_state *stream,
+ struct dc_dsc_bw_range *bw_range)
+ {
+@@ -1860,7 +1873,7 @@ enum dc_status dm_dp_mst_is_port_support
+ dc_link_get_highest_encoding_format(stream->link));
+ cur_link_settings = stream->link->verified_link_cap;
+ root_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings);
+- virtual_channel_bw_in_kbps = pbn_to_kbps(aconnector->mst_output_port->full_pbn, true);
++ virtual_channel_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
+
+ /* pick the end to end bw bottleneck */
+ end_to_end_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
+@@ -1913,7 +1926,7 @@ enum dc_status dm_dp_mst_is_port_support
+ immediate_upstream_port = aconnector->mst_output_port->parent->port_parent;
+
+ if (immediate_upstream_port) {
+- virtual_channel_bw_in_kbps = pbn_to_kbps(immediate_upstream_port->full_pbn, true);
++ virtual_channel_bw_in_kbps = kbps_from_pbn(immediate_upstream_port->full_pbn);
+ virtual_channel_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
+ } else {
+ /* For topology LCT 1 case - only one mstb*/
gpio-regmap-fix-memleak-in-error-path-in-gpio_regmap_register.patch
gpiolib-acpi-add-quirk-for-dell-precision-7780.patch
gpio-loongson-switch-2k2000-3000-gpio-to-byte_ctrl_mode.patch
+revert-drm-amd-display-fix-pbn-to-kbps-conversion.patch
+drm-amd-display-use-gfp_atomic-in-dc_create_plane_state.patch
+drm-amd-display-fix-scratch-registers-offsets-for-dcn35.patch
+drm-amd-display-fix-scratch-registers-offsets-for-dcn351.patch
+drm-displayid-pass-iter-to-drm_find_displayid_extension.patch