]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/mediatek: Fix mode valid issue for dp
authorLiankun Yang <liankun.yang@mediatek.com>
Fri, 25 Oct 2024 08:28:28 +0000 (16:28 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Jan 2025 12:34:40 +0000 (13:34 +0100)
[ Upstream commit 0d68b55887cedc7487036ed34cb4c2097c4228f1 ]

Fix dp mode valid issue to avoid abnormal display of limit state.

After DP passes link training, it can express the lane count of the
current link status is good. Calculate the maximum bandwidth supported
by DP using the current lane count.

The color format will select the best one based on the bandwidth
requirements of the current timing mode. If the current timing mode
uses RGB and meets the DP link bandwidth requirements, RGB will be used.

If the timing mode uses RGB but does not meet the DP link bandwidthi
requirements, it will continue to check whether YUV422 meets
the DP link bandwidth.

FEC overhead is approximately 2.4% from DP 1.4a spec 2.2.1.4.2.
The down-spread amplitude shall either be disabled (0.0%) or up
to 0.5% from 1.4a 3.5.2.6. Add up to approximately 3% total overhead.

Because rate is already divided by 10,
mode->clock does not need to be multiplied by 10.

Fixes: f70ac097a2cf ("drm/mediatek: Add MT8195 Embedded DisplayPort driver")
Signed-off-by: Liankun Yang <liankun.yang@mediatek.com>
Link: https://patchwork.kernel.org/project/dri-devel/patch/20241025083036.8829-3-liankun.yang@mediatek.com/
Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/mediatek/mtk_dp.c

index 04e3f72fa2324c17d4a695d8847fcf8c087c0d5a..09a496588b50f2daaa43455d0a321e22639c04c4 100644 (file)
@@ -2277,12 +2277,19 @@ mtk_dp_bridge_mode_valid(struct drm_bridge *bridge,
 {
        struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
        u32 bpp = info->color_formats & DRM_COLOR_FORMAT_YCBCR422 ? 16 : 24;
-       u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) *
-                             drm_dp_max_lane_count(mtk_dp->rx_cap),
-                        drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) *
-                        mtk_dp->max_lanes);
+       u32 lane_count_min = mtk_dp->train_info.lane_count;
+       u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) *
+                  lane_count_min;
 
-       if (rate < mode->clock * bpp / 8)
+       /*
+        *FEC overhead is approximately 2.4% from DP 1.4a spec 2.2.1.4.2.
+        *The down-spread amplitude shall either be disabled (0.0%) or up
+        *to 0.5% from 1.4a 3.5.2.6. Add up to approximately 3% total overhead.
+        *
+        *Because rate is already divided by 10,
+        *mode->clock does not need to be multiplied by 10
+        */
+       if ((rate * 97 / 100) < (mode->clock * bpp / 8))
                return MODE_CLOCK_HIGH;
 
        return MODE_OK;
@@ -2323,10 +2330,9 @@ static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
        struct drm_display_mode *mode = &crtc_state->adjusted_mode;
        struct drm_display_info *display_info =
                &conn_state->connector->display_info;
-       u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) *
-                             drm_dp_max_lane_count(mtk_dp->rx_cap),
-                        drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) *
-                        mtk_dp->max_lanes);
+       u32 lane_count_min = mtk_dp->train_info.lane_count;
+       u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) *
+                  lane_count_min;
 
        *num_input_fmts = 0;
 
@@ -2335,8 +2341,8 @@ static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
         * datarate of YUV422 and sink device supports YUV422, we output YUV422
         * format. Use this condition, we can support more resolution.
         */
-       if ((rate < (mode->clock * 24 / 8)) &&
-           (rate > (mode->clock * 16 / 8)) &&
+       if (((rate * 97 / 100) < (mode->clock * 24 / 8)) &&
+           ((rate * 97 / 100) > (mode->clock * 16 / 8)) &&
            (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
                input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL);
                if (!input_fmts)