]> www.infradead.org Git - users/hch/misc.git/commitdiff
drm/amd/display: Reject modes with too high pixel clock on DCE6-10
authorTimur Kristóf <timur.kristof@gmail.com>
Wed, 24 Sep 2025 11:38:34 +0000 (13:38 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 25 Sep 2025 19:51:07 +0000 (15:51 -0400)
Reject modes with a pixel clock higher than the maximum display
clock. Use 400 MHz as a fallback value when the maximum display
clock is not known. Pixel clocks that are higher than the display
clock just won't work and are not supported.

With the addition of the YUV422 fallback, DC can now accidentally
select a mode requiring higher pixel clock than actually supported
when the DP version supports the required bandwidth but the clock
is otherwise too high for the display engine. DCE 6-10 don't
support these modes but they don't have a bandwidth calculation
to reject them properly.

Fixes: db291ed1732e ("drm/amd/display: Add fallback path for YCBCR422")
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c
drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c

index dbd6ef1b60a0b76f849fcc47d9ada15740347fa0..6131ede2db7a25c9fbb003488abd1dbf2bc38ca2 100644 (file)
@@ -463,6 +463,9 @@ void dce_clk_mgr_construct(
                clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
        clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID;
 
+       base->clks.max_supported_dispclk_khz =
+               clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
+
        dce_clock_read_integrated_info(clk_mgr);
        dce_clock_read_ss_info(clk_mgr);
 }
index a39641a0ff09ef82451f1d812415ada9d95a12a0..69dd80d9f73888380b98b549dd41da364c99af3d 100644 (file)
@@ -147,6 +147,8 @@ void dce60_clk_mgr_construct(
                struct dc_context *ctx,
                struct clk_mgr_internal *clk_mgr)
 {
+       struct clk_mgr *base = &clk_mgr->base;
+
        dce_clk_mgr_construct(ctx, clk_mgr);
 
        memcpy(clk_mgr->max_clks_by_state,
@@ -157,5 +159,8 @@ void dce60_clk_mgr_construct(
        clk_mgr->clk_mgr_shift = &disp_clk_shift;
        clk_mgr->clk_mgr_mask = &disp_clk_mask;
        clk_mgr->base.funcs = &dce60_funcs;
+
+       base->clks.max_supported_dispclk_khz =
+               clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
 }
 
index 3a51be63f020836c6cb94937caec203c280a9d11..f36ec4edf0aec4a1f319de9983d3205e3e0a3ca8 100644 (file)
@@ -29,6 +29,7 @@
 #include "stream_encoder.h"
 
 #include "resource.h"
+#include "clk_mgr.h"
 #include "include/irq_service_interface.h"
 #include "virtual/virtual_stream_encoder.h"
 #include "dce110/dce110_resource.h"
@@ -843,10 +844,17 @@ static enum dc_status dce100_validate_bandwidth(
 {
        int i;
        bool at_least_one_pipe = false;
+       struct dc_stream_state *stream = NULL;
+       const uint32_t max_pix_clk_khz = max(dc->clk_mgr->clks.max_supported_dispclk_khz, 400000);
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               if (context->res_ctx.pipe_ctx[i].stream)
+               stream = context->res_ctx.pipe_ctx[i].stream;
+               if (stream) {
                        at_least_one_pipe = true;
+
+                       if (stream->timing.pix_clk_100hz >= max_pix_clk_khz * 10)
+                               return DC_FAIL_BANDWIDTH_VALIDATE;
+               }
        }
 
        if (at_least_one_pipe) {
index c164d2500c2a4dabe863848e9685182106f766e1..b5433349fc7a6a43e1599f3af3d64286a29eb10d 100644 (file)
@@ -34,6 +34,7 @@
 #include "stream_encoder.h"
 
 #include "resource.h"
+#include "clk_mgr.h"
 #include "include/irq_service_interface.h"
 #include "irq/dce60/irq_service_dce60.h"
 #include "dce110/dce110_timing_generator.h"
@@ -870,10 +871,17 @@ static enum dc_status dce60_validate_bandwidth(
 {
        int i;
        bool at_least_one_pipe = false;
+       struct dc_stream_state *stream = NULL;
+       const uint32_t max_pix_clk_khz = max(dc->clk_mgr->clks.max_supported_dispclk_khz, 400000);
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               if (context->res_ctx.pipe_ctx[i].stream)
+               stream = context->res_ctx.pipe_ctx[i].stream;
+               if (stream) {
                        at_least_one_pipe = true;
+
+                       if (stream->timing.pix_clk_100hz >= max_pix_clk_khz * 10)
+                               return DC_FAIL_BANDWIDTH_VALIDATE;
+               }
        }
 
        if (at_least_one_pipe) {
index 3e8b0ac11d906db127089fe5fea0f47075c8520a..538eafea82d5f1baafe24602564ee67dc7280a50 100644 (file)
@@ -32,6 +32,7 @@
 #include "stream_encoder.h"
 
 #include "resource.h"
+#include "clk_mgr.h"
 #include "include/irq_service_interface.h"
 #include "irq/dce80/irq_service_dce80.h"
 #include "dce110/dce110_timing_generator.h"
@@ -876,10 +877,17 @@ static enum dc_status dce80_validate_bandwidth(
 {
        int i;
        bool at_least_one_pipe = false;
+       struct dc_stream_state *stream = NULL;
+       const uint32_t max_pix_clk_khz = max(dc->clk_mgr->clks.max_supported_dispclk_khz, 400000);
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               if (context->res_ctx.pipe_ctx[i].stream)
+               stream = context->res_ctx.pipe_ctx[i].stream;
+               if (stream) {
                        at_least_one_pipe = true;
+
+                       if (stream->timing.pix_clk_100hz >= max_pix_clk_khz * 10)
+                               return DC_FAIL_BANDWIDTH_VALIDATE;
+               }
        }
 
        if (at_least_one_pipe) {