From 9a7fcee75c717dc7c0444bc097d2504a6273878b Mon Sep 17 00:00:00 2001 From: usbpc Date: Mon, 29 Jul 2024 21:18:05 +0200 Subject: [PATCH] Added patch to apply fa57924c76d995 to fix a problem with external displays introduced by 4df96ba66760 to kernel v6.10.2. --- ...d-fa57924c76d995-to-apply-to-v6.10.2.patch | 293 ++++++++++++++++++ PKGBUILD | 11 +- 2 files changed, 300 insertions(+), 4 deletions(-) create mode 100644 0001-Cherry-picked-fa57924c76d995-to-apply-to-v6.10.2.patch diff --git a/0001-Cherry-picked-fa57924c76d995-to-apply-to-v6.10.2.patch b/0001-Cherry-picked-fa57924c76d995-to-apply-to-v6.10.2.patch new file mode 100644 index 0000000..0d5d837 --- /dev/null +++ b/0001-Cherry-picked-fa57924c76d995-to-apply-to-v6.10.2.patch @@ -0,0 +1,293 @@ +From bdfdb325ed919c4e1f8e7e953c2a2bbc01957b27 Mon Sep 17 00:00:00 2001 +From: Kevin Holm +Date: Mon, 20 May 2024 16:37:01 +0800 +Subject: [PATCH] Cherry-picked fa57924c76d995 to apply to v6.10.2 + +[Why] 4df96ba6676034 ("drm/amd/display: Add timing pixel encoding for mst +mode validation") introduced a bug that caused some displays connected +through a usb-c docking station to not show an image on some laptops. + +[How] Cherry-picked fa57924c76d995 ("drm/amd/display: Refactor function +dm_dp_mst_is_port_support_mode()") from upstream. + +Link: https://lore.kernel.org/stable/fd8ece71459cd79f669efcfd25e4ce38b80d4164@holm.dev/T/#t +Fixes: 4df96ba6676034 ("drm/amd/display: Add timing pixel encoding for mst mode validation") + +Original commit message: + +drm/amd/display: Refactor function dm_dp_mst_is_port_support_mode() + +[Why] +dm_dp_mst_is_port_support_mode() is a bit not following the original design rule and cause +light up issue with multiple 4k monitors after mst dsc hub. + +[How] +Refactor function dm_dp_mst_is_port_support_mode() a bit to solve the light up issue. +--- + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 232 +++++++++++------- + 1 file changed, 147 insertions(+), 85 deletions(-) + +diff --git 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 +index a5e1a93ddaea..e90f9d697511 100644 +--- 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 +@@ -1595,109 +1595,171 @@ static bool is_dsc_common_config_possible(struct dc_stream_state *stream, + return bw_range->max_target_bpp_x16 && bw_range->min_target_bpp_x16; + } + ++#if defined(CONFIG_DRM_AMD_DC_FP) ++static bool dp_get_link_current_set_bw(struct drm_dp_aux *aux, uint32_t *cur_link_bw) ++{ ++ uint32_t total_data_bw_efficiency_x10000 = 0; ++ uint32_t link_rate_per_lane_kbps = 0; ++ enum dc_link_rate link_rate; ++ union lane_count_set lane_count; ++ u8 dp_link_encoding; ++ u8 link_bw_set = 0; ++ ++ *cur_link_bw = 0; ++ ++ if (drm_dp_dpcd_read(aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &dp_link_encoding, 1) != 1 || ++ drm_dp_dpcd_read(aux, DP_LANE_COUNT_SET, &lane_count.raw, 1) != 1 || ++ drm_dp_dpcd_read(aux, DP_LINK_BW_SET, &link_bw_set, 1) != 1) ++ return false; ++ ++ switch (dp_link_encoding) { ++ case DP_8b_10b_ENCODING: ++ link_rate = link_bw_set; ++ link_rate_per_lane_kbps = link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE; ++ total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000; ++ total_data_bw_efficiency_x10000 /= 100; ++ total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100; ++ break; ++ case DP_128b_132b_ENCODING: ++ switch (link_bw_set) { ++ case DP_LINK_BW_10: ++ link_rate = LINK_RATE_UHBR10; ++ break; ++ case DP_LINK_BW_13_5: ++ link_rate = LINK_RATE_UHBR13_5; ++ break; ++ case DP_LINK_BW_20: ++ link_rate = LINK_RATE_UHBR20; ++ break; ++ default: ++ return false; ++ } ++ ++ link_rate_per_lane_kbps = link_rate * 10000; ++ total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_128b_132b_x10000; ++ break; ++ default: ++ return false; ++ } ++ ++ *cur_link_bw = link_rate_per_lane_kbps * lane_count.bits.LANE_COUNT_SET / 10000 * total_data_bw_efficiency_x10000; ++ return true; ++} ++#endif ++ + enum dc_status dm_dp_mst_is_port_support_mode( + struct amdgpu_dm_connector *aconnector, + struct dc_stream_state *stream) + { +- int pbn, branch_max_throughput_mps = 0; ++#if defined(CONFIG_DRM_AMD_DC_FP) ++ int branch_max_throughput_mps = 0; + struct dc_link_settings cur_link_settings; +- unsigned int end_to_end_bw_in_kbps = 0; +- unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; ++ uint32_t end_to_end_bw_in_kbps = 0; ++ uint32_t root_link_bw_in_kbps = 0; ++ uint32_t virtual_channel_bw_in_kbps = 0; + struct dc_dsc_bw_range bw_range = {0}; + struct dc_dsc_config_options dsc_options = {0}; ++ uint32_t stream_kbps; + +- /* +- * Consider the case with the depth of the mst topology tree is equal or less than 2 +- * A. When dsc bitstream can be transmitted along the entire path +- * 1. dsc is possible between source and branch/leaf device (common dsc params is possible), AND +- * 2. dsc passthrough supported at MST branch, or +- * 3. dsc decoding supported at leaf MST device +- * Use maximum dsc compression as bw constraint +- * B. When dsc bitstream cannot be transmitted along the entire path +- * Use native bw as bw constraint ++ /* DSC unnecessary case ++ * Check if timing could be supported within end-to-end BW + */ +- if (is_dsc_common_config_possible(stream, &bw_range) && +- (aconnector->mst_output_port->passthrough_aux || +- aconnector->dsc_aux == &aconnector->mst_output_port->aux)) { +- cur_link_settings = stream->link->verified_link_cap; +- upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings); +- down_link_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(upper_link_bw_in_kbps, down_link_bw_in_kbps); +- +- if (end_to_end_bw_in_kbps < bw_range.min_kbps) { +- DRM_DEBUG_DRIVER("maximum dsc compression cannot fit into end-to-end bandwidth\n"); ++ stream_kbps = ++ dc_bandwidth_in_kbps_from_timing(&stream->timing, ++ 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 = 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); ++ ++ if (stream_kbps <= end_to_end_bw_in_kbps) { ++ DRM_DEBUG_DRIVER("No DSC needed. End-to-end bw sufficient."); ++ return DC_OK; ++ } ++ ++ /*DSC necessary case*/ ++ if (!aconnector->dsc_aux) ++ return DC_FAIL_BANDWIDTH_VALIDATE; ++ ++ if (is_dsc_common_config_possible(stream, &bw_range)) { ++ ++ /*capable of dsc passthough. dsc bitstream along the entire path*/ ++ if (aconnector->mst_output_port->passthrough_aux) { ++ if (bw_range.min_kbps > end_to_end_bw_in_kbps) { ++ DRM_DEBUG_DRIVER("DSC passthrough. Max dsc compression can't fit into end-to-end bw\n"); + return DC_FAIL_BANDWIDTH_VALIDATE; +- } ++ } ++ } else { ++ /*dsc bitstream decoded at the dp last link*/ ++ struct drm_dp_mst_port *immediate_upstream_port = NULL; ++ uint32_t end_link_bw = 0; ++ ++ /*Get last DP link BW capability*/ ++ if (dp_get_link_current_set_bw(&aconnector->mst_output_port->aux, &end_link_bw)) { ++ if (stream_kbps > end_link_bw) { ++ DRM_DEBUG_DRIVER("DSC decode at last link. Mode required bw can't fit into available bw\n"); ++ return DC_FAIL_BANDWIDTH_VALIDATE; ++ } ++ } + +- if (end_to_end_bw_in_kbps < bw_range.stream_kbps) { +- dc_dsc_get_default_config_option(stream->link->dc, &dsc_options); +- dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16; +- if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0], +- &stream->sink->dsc_caps.dsc_dec_caps, +- &dsc_options, +- end_to_end_bw_in_kbps, +- &stream->timing, +- dc_link_get_highest_encoding_format(stream->link), +- &stream->timing.dsc_cfg)) { +- stream->timing.flags.DSC = 1; +- DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc and dsc config found\n"); +- } else { +- DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc but dsc config not found\n"); +- return DC_FAIL_BANDWIDTH_VALIDATE; ++ /*Get virtual channel bandwidth between source and the link before the last link*/ ++ if (aconnector->mst_output_port->parent->port_parent) ++ immediate_upstream_port = aconnector->mst_output_port->parent->port_parent; ++ ++ if (immediate_upstream_port) { ++ 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); ++ if (bw_range.min_kbps > virtual_channel_bw_in_kbps) { ++ DRM_DEBUG_DRIVER("DSC decode at last link. Max dsc compression can't fit into MST available bw\n"); ++ return DC_FAIL_BANDWIDTH_VALIDATE; ++ } + } + } +- } else { +- /* Check if mode could be supported within max slot +- * number of current mst link and full_pbn of mst links. +- */ +- int pbn_div, slot_num, max_slot_num; +- enum dc_link_encoding_format link_encoding; +- uint32_t stream_kbps = +- dc_bandwidth_in_kbps_from_timing(&stream->timing, +- dc_link_get_highest_encoding_format(stream->link)); +- +- pbn = kbps_to_peak_pbn(stream_kbps); +- pbn_div = dm_mst_get_pbn_divider(stream->link); +- slot_num = DIV_ROUND_UP(pbn, pbn_div); +- +- link_encoding = dc_link_get_highest_encoding_format(stream->link); +- if (link_encoding == DC_LINK_ENCODING_DP_8b_10b) +- max_slot_num = 63; +- else if (link_encoding == DC_LINK_ENCODING_DP_128b_132b) +- max_slot_num = 64; +- else { +- DRM_DEBUG_DRIVER("Invalid link encoding format\n"); +- return DC_FAIL_BANDWIDTH_VALIDATE; +- } + +- if (slot_num > max_slot_num || +- pbn > aconnector->mst_output_port->full_pbn) { +- DRM_DEBUG_DRIVER("Mode can not be supported within mst links!"); ++ /*Confirm if we can obtain dsc config*/ ++ dc_dsc_get_default_config_option(stream->link->dc, &dsc_options); ++ dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16; ++ if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0], ++ &stream->sink->dsc_caps.dsc_dec_caps, ++ &dsc_options, ++ end_to_end_bw_in_kbps, ++ &stream->timing, ++ dc_link_get_highest_encoding_format(stream->link), ++ &stream->timing.dsc_cfg)) { ++ stream->timing.flags.DSC = 1; ++ DRM_DEBUG_DRIVER("Require dsc and dsc config found\n"); ++ } else { ++ DRM_DEBUG_DRIVER("Require dsc but can't find appropriate dsc config\n"); + return DC_FAIL_BANDWIDTH_VALIDATE; + } +- } + +- /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */ +- switch (stream->timing.pixel_encoding) { +- case PIXEL_ENCODING_RGB: +- case PIXEL_ENCODING_YCBCR444: +- branch_max_throughput_mps = +- aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_0_mps; +- break; +- case PIXEL_ENCODING_YCBCR422: +- case PIXEL_ENCODING_YCBCR420: +- branch_max_throughput_mps = +- aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_1_mps; +- break; +- default: +- break; +- } ++ /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */ ++ switch (stream->timing.pixel_encoding) { ++ case PIXEL_ENCODING_RGB: ++ case PIXEL_ENCODING_YCBCR444: ++ branch_max_throughput_mps = ++ aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_0_mps; ++ break; ++ case PIXEL_ENCODING_YCBCR422: ++ case PIXEL_ENCODING_YCBCR420: ++ branch_max_throughput_mps = ++ aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_1_mps; ++ break; ++ default: ++ break; ++ } + +- if (branch_max_throughput_mps != 0 && +- ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000)) ++ if (branch_max_throughput_mps != 0 && ++ ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000)) { ++ DRM_DEBUG_DRIVER("DSC is required but max throughput mps fails"); + return DC_FAIL_BANDWIDTH_VALIDATE; +- ++ } ++ } else { ++ DRM_DEBUG_DRIVER("DSC is required but can't find common dsc config."); ++ return DC_FAIL_BANDWIDTH_VALIDATE; ++ } ++#endif + return DC_OK; + } +-- +2.45.2 + diff --git a/PKGBUILD b/PKGBUILD index 5da9e6f..0b46021 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,8 +1,8 @@ # Maintainer: Jan Alexander Steffens (heftig) -pkgbase=linux +pkgbase=linux-kjh pkgver=6.10.2.arch1 -pkgrel=1 +pkgrel=2 pkgdesc='Linux' url='https://github.com/archlinux/linux' arch=(x86_64) @@ -35,6 +35,7 @@ source=( https://cdn.kernel.org/pub/linux/kernel/v${pkgver%%.*}.x/${_srcname}.tar.{xz,sign} $url/releases/download/$_srctag/linux-$_srctag.patch.zst{,.sig} config # the main kernel config file + 0001-Cherry-picked-fa57924c76d995-to-apply-to-v6.10.2.patch ) validpgpkeys=( ABAF11C65A2970B130ABE3C479BE3E4300411886 # Linus Torvalds @@ -46,12 +47,14 @@ sha256sums=('73d8520dd9cba5acfc5e7208e76b35d9740b8aae38210a9224e32ec4c0d29b70' 'SKIP' 'a4efb43085bdfff93b11f26dd276859d347752958717b99c9f4a97133b857515' 'SKIP' - 'db35dc40884ec866a32225b2f7916fa7ae24273e08f9e204cddb010816255e17') + 'db35dc40884ec866a32225b2f7916fa7ae24273e08f9e204cddb010816255e17' + '0815c14c97f5956422ab4cfd3b6b86c4221dc80a378e4ece3bd8f85ef48c8c27') b2sums=('ab1d2e79a1bb8a9b78ab5b1af93db7ef356cb5e14bba1121bbd3ae06b9589c8bfc32bab373acdd0ecf965ac132130e7eb34e70b35a9df1bd85b49dab97e2c02a' 'SKIP' '9c16132af733ba448db39467d0d20df7143e2f2c1acf01653afa898a3e10f5fa170db24bdede4e7083b72064a3dc4bc4e6d616d3ac7cdc0a6b25d5725ff633fc' 'SKIP' - '3f8f9bbde186b92bca111978c7df904446465b63e612fb2220d063758b0d11eab2f6907d41512170056cd35233021a2614302911a1ac796e5e1fbd42eaed3b8a') + '3f8f9bbde186b92bca111978c7df904446465b63e612fb2220d063758b0d11eab2f6907d41512170056cd35233021a2614302911a1ac796e5e1fbd42eaed3b8a' + '1b200dec4cef94645c1cee86170f1ddaf83bec1bdba5deacc54a2c2434c7705707410a5faae75e70bc37ad62e1d72a5cf0cf543eb12617b7ac8aa26ebc692b3e') export KBUILD_BUILD_HOST=archlinux export KBUILD_BUILD_USER=$pkgbase