]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: refactor DSC cap calculation for dcn35
authorMohit Bawa <Mohit.Bawa@amd.com>
Thu, 23 Oct 2025 14:40:41 +0000 (10:40 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 12 Nov 2025 02:54:15 +0000 (21:54 -0500)
why:
dcn35 currently uses a hardcoded DSC display clock value which is incorrect
for some asic types. Newer DCN versions retrieve dsc display clock from
clk_mgr. The same can be done for dcn35.

how:
Refactor the DSC cap calculation using pre-existing logic.
Handle ODM combine requirements in dc_dsc.c.
Replace hardcoded display clock with actual value retrieved from clk_mgr.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: Charlene Liu <charlene.liu@amd.com>
Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Mohit Bawa <Mohit.Bawa@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c

index 35d20a663d67ab8db310f1a140e3a09c655c759a..dfd0c9505af096c26350174bed2db7d38e3fb523 100644 (file)
@@ -1295,6 +1295,35 @@ static void dcn35_update_clocks_fpga(struct clk_mgr *clk_mgr,
        dcn35_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
 }
 
+static unsigned int dcn35_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+       unsigned int num_clk_levels;
+
+       switch (clk_type) {
+       case CLK_TYPE_DISPCLK:
+               num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+               return num_clk_levels ?
+                               clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 :
+                               clk_mgr->base.boot_snapshot.dispclk;
+       case CLK_TYPE_DPPCLK:
+               num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dppclk_levels;
+               return num_clk_levels ?
+                               clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dppclk_mhz * 1000 :
+                               clk_mgr->base.boot_snapshot.dppclk;
+       case CLK_TYPE_DSCCLK:
+               num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+               return num_clk_levels ?
+                               clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 / 3 :
+                               clk_mgr->base.boot_snapshot.dispclk / 3;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static struct clk_mgr_funcs dcn35_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
@@ -1306,6 +1335,7 @@ static struct clk_mgr_funcs dcn35_funcs = {
        .set_low_power_state = dcn35_set_low_power_state,
        .exit_low_power_state = dcn35_exit_low_power_state,
        .is_ips_supported = dcn35_is_ips_supported,
+       .get_max_clock_khz = dcn35_get_max_clock_khz,
 };
 
 struct clk_mgr_funcs dcn35_fpga_funcs = {
index f9c6377ac66cf90b86a3bf7c961d3abc941ad14b..e712985f7abdbcc16f71f4796f814f0296b19fb3 100644 (file)
@@ -28,9 +28,9 @@
 #include "reg_helper.h"
 
 static void dsc35_enable(struct display_stream_compressor *dsc, int opp_pipe);
+static void dsc35_get_single_enc_caps(struct dsc_enc_caps *dsc_enc_caps, unsigned int max_dscclk_khz);
 
 static const struct dsc_funcs dcn35_dsc_funcs = {
-       .dsc_get_enc_caps = dsc2_get_enc_caps,
        .dsc_read_state = dsc2_read_state,
        .dsc_read_reg_state = dsc2_read_reg_state,
        .dsc_validate_stream = dsc2_validate_stream,
@@ -40,6 +40,7 @@ static const struct dsc_funcs dcn35_dsc_funcs = {
        .dsc_disable = dsc2_disable,
        .dsc_disconnect = dsc2_disconnect,
        .dsc_wait_disconnect_pending_clear = dsc2_wait_disconnect_pending_clear,
+       .dsc_get_single_enc_caps = dsc35_get_single_enc_caps,
 };
 
 /* Macro definitios for REG_SET macros*/
@@ -111,3 +112,31 @@ void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable)
 {
        REG_UPDATE(DSC_TOP_CONTROL, DSC_FGCG_REP_DIS, !enable);
 }
+
+void dsc35_get_single_enc_caps(struct dsc_enc_caps *dsc_enc_caps, unsigned int max_dscclk_khz)
+{
+       dsc_enc_caps->dsc_version = 0x21; /* v1.2 - DP spec defined it in reverse order and we kept it */
+
+       dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 1;
+       dsc_enc_caps->slice_caps.bits.NUM_SLICES_2 = 1;
+       dsc_enc_caps->slice_caps.bits.NUM_SLICES_3 = 1;
+       dsc_enc_caps->slice_caps.bits.NUM_SLICES_4 = 1;
+
+       dsc_enc_caps->lb_bit_depth = 13;
+       dsc_enc_caps->is_block_pred_supported = true;
+
+       dsc_enc_caps->color_formats.bits.RGB = 1;
+       dsc_enc_caps->color_formats.bits.YCBCR_444 = 1;
+       dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 1;
+       dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 0;
+       dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_420 = 1;
+
+       dsc_enc_caps->color_depth.bits.COLOR_DEPTH_8_BPC = 1;
+       dsc_enc_caps->color_depth.bits.COLOR_DEPTH_10_BPC = 1;
+       dsc_enc_caps->color_depth.bits.COLOR_DEPTH_12_BPC = 1;
+
+       dsc_enc_caps->max_total_throughput_mps = max_dscclk_khz * 3 / 1000;
+
+       dsc_enc_caps->max_slice_width = 5184; /* (including 64 overlap pixels for eDP MSO mode) */
+       dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */
+}