From nobody Sat Feb 7 17:31:54 2026 Received: from out-181.mta1.migadu.com (out-181.mta1.migadu.com [95.215.58.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34CE01AA3D0 for ; Tue, 30 Jul 2024 18:53:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722365631; cv=none; b=UEmvoSKqVxpyzamq0vfDyO067A4HJrCu2TjNMI91zzifh+PYOYKpz37CMvzW+19LKVNjJbpJarq4yA1nmhw5B9dlL+F0oQezdpDkpx8A10pkiHKDFBZPPmd4Y0lzDnxkh2xM8nTHIoPCF/zoLdZsY++3TQsIvBcO5R4AAcLfKfo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722365631; c=relaxed/simple; bh=3KF1m7Yt4Ol9otmLzmXemHFItOj8lfFyse+zAjzf1lw=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=H21gx+Qv9ZXD4ClMy5+1k4BoXvco6h1VPNrBm1yyK1DyM72ZIMhEte/JdS1MscN2igU/yakx0kGDbku/zEpics5ivlPi/6y8wPBDet1bkVPp+Frcs3Dx1IJ954eRarTaa9ZfdLVUgw6F4NuKX+qjlKb8XH23cRrXoC45+H2z2Ds= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=holm.dev; spf=pass smtp.mailfrom=holm.dev; dkim=pass (2048-bit key) header.d=holm.dev header.i=@holm.dev header.b=mKbTeXjP; arc=none smtp.client-ip=95.215.58.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=holm.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=holm.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=holm.dev header.i=@holm.dev header.b="mKbTeXjP" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=holm.dev; s=key1; t=1722365626; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=Dn0xLoWfpimcsell+FemET9LAXc+6vt12NIgpqJmTuA=; b=mKbTeXjP4/9I1YF92icnDI09ZeHIfFWNXVz6Xr+njiwq//LEdXFTrZXsXIM/NRagozi3Bq V15l4NcBHoTVjm0dsn9tpEt58s4cDH/KDmdeLnYedz8WcFEZHS6m8uB4JfWAa1TcOLAgs8 1lnJfWAr3RxvEL/vTM+G+hhlnMhrUHjlnT8z2LBVsf5Hc1ZCljUD4ysAmgmKuHD8MZgStY 84jmZj3d2GQ8UsTyLI99gc+PJFhEAdIds2eGNQXGy6JUMBQpOa+UbS9e8X7WnFboTGXMtb nthKe0cP7YjasayTr4vDRHHlXOAhH0Kpfch8cthWynbQPBRrkhXZhji8QxMiCw== From: Kevin Holm To: stable@vger.kernel.org Cc: regressions@lists.linux.dev, amd-gfx@lists.freedesktop.org, ML dri-devel , LKML , Wayne Lin , Jerry Zuo , Zaeem Mohamed , Daniel Wheeler , Alex Deucher , Kevin Holm Subject: [PATCH 6.10] drm/amd/display: Refactor function dm_dp_mst_is_port_support_mode() Date: Tue, 30 Jul 2024 20:53:39 +0200 Message-ID: <20240730185339.543359-1-kevin@holm.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Wayne Lin [ Upstream commit fa57924c76d995e87ca3533ec60d1d5e55769a27 ] [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. Reviewed-by: Jerry Zuo Acked-by: Zaeem Mohamed Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher [kevin@holm.dev: Resolved merge conflict in .../amdgpu_dm_mst_types.c] Fixes: 4df96ba6676034 ("drm/amd/display: Add timing pixel encoding for mst = mode validation") Link: https://lore.kernel.org/stable/d74a7768e957e6ce88c27a5bece0c64dff132e= 24@holm.dev/T/#u Signed-off-by: Kevin Holm --- I resolved the merge conflict so that, after this patch is applied to the linux-6.10.y branch of the stable git repository, the resulting function dm_dp_mst_is_port_support_mode (and also the new function=20 dp_get_link_current_set_bw) is identical to the original commit. I've confirmed that it fixes the regression I reported for my use case. --- .../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; } =20 +#if defined(CONFIG_DRM_AMD_DC_FP) +static bool dp_get_link_current_set_bw(struct drm_dp_aux *aux, uint32_t *c= ur_link_bw) +{ + uint32_t total_data_bw_efficiency_x10000 =3D 0; + uint32_t link_rate_per_lane_kbps =3D 0; + enum dc_link_rate link_rate; + union lane_count_set lane_count; + u8 dp_link_encoding; + u8 link_bw_set =3D 0; + + *cur_link_bw =3D 0; + + if (drm_dp_dpcd_read(aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &dp_link_encod= ing, 1) !=3D 1 || + drm_dp_dpcd_read(aux, DP_LANE_COUNT_SET, &lane_count.raw, 1) !=3D 1 || + drm_dp_dpcd_read(aux, DP_LINK_BW_SET, &link_bw_set, 1) !=3D 1) + return false; + + switch (dp_link_encoding) { + case DP_8b_10b_ENCODING: + link_rate =3D link_bw_set; + link_rate_per_lane_kbps =3D link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS= _PER_DP_BYTE; + total_data_bw_efficiency_x10000 =3D DATA_EFFICIENCY_8b_10b_x10000; + total_data_bw_efficiency_x10000 /=3D 100; + total_data_bw_efficiency_x10000 *=3D DATA_EFFICIENCY_8b_10b_FEC_EFFICIEN= CY_x100; + break; + case DP_128b_132b_ENCODING: + switch (link_bw_set) { + case DP_LINK_BW_10: + link_rate =3D LINK_RATE_UHBR10; + break; + case DP_LINK_BW_13_5: + link_rate =3D LINK_RATE_UHBR13_5; + break; + case DP_LINK_BW_20: + link_rate =3D LINK_RATE_UHBR20; + break; + default: + return false; + } + + link_rate_per_lane_kbps =3D link_rate * 10000; + total_data_bw_efficiency_x10000 =3D DATA_EFFICIENCY_128b_132b_x10000; + break; + default: + return false; + } + + *cur_link_bw =3D 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 =3D 0; +#if defined(CONFIG_DRM_AMD_DC_FP) + int branch_max_throughput_mps =3D 0; struct dc_link_settings cur_link_settings; - unsigned int end_to_end_bw_in_kbps =3D 0; - unsigned int upper_link_bw_in_kbps =3D 0, down_link_bw_in_kbps =3D 0; + uint32_t end_to_end_bw_in_kbps =3D 0; + uint32_t root_link_bw_in_kbps =3D 0; + uint32_t virtual_channel_bw_in_kbps =3D 0; struct dc_dsc_bw_range bw_range =3D {0}; struct dc_dsc_config_options dsc_options =3D {0}; + uint32_t stream_kbps; =20 - /* - * 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 ds= c 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 =3D=3D &aconnector->mst_output_port->aux)) { - cur_link_settings =3D stream->link->verified_link_cap; - upper_link_bw_in_kbps =3D dc_link_bandwidth_kbps(aconnector->dc_link, &c= ur_link_settings); - down_link_bw_in_kbps =3D kbps_from_pbn(aconnector->mst_output_port->full= _pbn); - - /* pick the end to end bw bottleneck */ - end_to_end_bw_in_kbps =3D min(upper_link_bw_in_kbps, down_link_bw_in_kbp= s); - - if (end_to_end_bw_in_kbps < bw_range.min_kbps) { - DRM_DEBUG_DRIVER("maximum dsc compression cannot fit into end-to-end ba= ndwidth\n"); + stream_kbps =3D + dc_bandwidth_in_kbps_from_timing(&stream->timing, + dc_link_get_highest_encoding_format(stream->link)); + cur_link_settings =3D stream->link->verified_link_cap; + root_link_bw_in_kbps =3D dc_link_bandwidth_kbps(aconnector->dc_link, &cur= _link_settings); + virtual_channel_bw_in_kbps =3D kbps_from_pbn(aconnector->mst_output_port-= >full_pbn); + + /* pick the end to end bw bottleneck */ + end_to_end_bw_in_kbps =3D min(root_link_bw_in_kbps, virtual_channel_bw_in= _kbps); + + if (stream_kbps <=3D 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 =3D NULL; + uint32_t end_link_bw =3D 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; + } + } =20 - 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 =3D aconnector->base.disp= lay_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 =3D 1; - DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc and dsc config foun= d\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 =3D aconnector->mst_output_port->parent->port_= parent; + + if (immediate_upstream_port) { + virtual_channel_bw_in_kbps =3D kbps_from_pbn(immediate_upstream_port->= full_pbn); + virtual_channel_bw_in_kbps =3D min(root_link_bw_in_kbps, virtual_chann= el_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 =3D - dc_bandwidth_in_kbps_from_timing(&stream->timing, - dc_link_get_highest_encoding_format(stream->link)); - - pbn =3D kbps_to_peak_pbn(stream_kbps); - pbn_div =3D dm_mst_get_pbn_divider(stream->link); - slot_num =3D DIV_ROUND_UP(pbn, pbn_div); - - link_encoding =3D dc_link_get_highest_encoding_format(stream->link); - if (link_encoding =3D=3D DC_LINK_ENCODING_DP_8b_10b) - max_slot_num =3D 63; - else if (link_encoding =3D=3D DC_LINK_ENCODING_DP_128b_132b) - max_slot_num =3D 64; - else { - DRM_DEBUG_DRIVER("Invalid link encoding format\n"); - return DC_FAIL_BANDWIDTH_VALIDATE; - } =20 - 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 =3D aconnector->base.displ= ay_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 =3D 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; } - } =20 - /* 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 =3D - 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 =3D - 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 =3D + 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 =3D + aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_1= _mps; + break; + default: + break; + } =20 - if (branch_max_throughput_mps !=3D 0 && - ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000= )) + if (branch_max_throughput_mps !=3D 0 && + ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 100= 0)) { + 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; } --=20 2.45.2