drm/amd/display: Firmware assisted MCLK switch and FS
authorFelipe Clark <felipe.clark@amd.com>
Sun, 7 Mar 2021 18:27:30 +0000 (13:27 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 15 Jun 2022 01:38:41 +0000 (21:38 -0400)
[WHY]
Memory clock switching has great potential for power savings.

[HOW]
The driver code was modified to notify the DMCUB firmware that it should
stretch the vertical blank of frames when a memory clock switch is about
to start so that no blackouts happen on the screen due to unavailability
of the frame buffer.
The driver logic to determine when such firmware assisted strategy can
be initiated is also implemented and consists on checking prerequisites
of the feature.

Acked-by: Alan Liu <HaoPing.Liu@amd.com>
Signed-off-by: Felipe Clark <felipe.clark@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
14 files changed:
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
drivers/gpu/drm/amd/display/modules/freesync/freesync.c
drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h

index 645ec5bc3a7d79ea422e90dcd6f2924a8cc5a04f..cfa6c2d1fc692d51cfadd51b1c7b2a479cee2a8f 100644 (file)
@@ -397,7 +397,6 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
                struct dc_crtc_timing_adjust *adjust)
 {
        int i;
-       bool ret = false;
 
        stream->adjust.v_total_max = adjust->v_total_max;
        stream->adjust.v_total_mid = adjust->v_total_mid;
@@ -412,10 +411,10 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
                                        1,
                                        *adjust);
 
-                       ret = true;
+                       return true;
                }
        }
-       return ret;
+       return false;
 }
 
 /**
@@ -2650,6 +2649,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
        if (update->vrr_infopacket)
                stream->vrr_infopacket = *update->vrr_infopacket;
 
+       if (update->allow_freesync)
+               stream->allow_freesync = *update->allow_freesync;
+
        if (update->crtc_timing_adjust)
                stream->adjust = *update->crtc_timing_adjust;
 
index 11597bca966ab2147a355dc952cb32537f0b66fd..548c91ad1b820f4153d896a1f2a2af75a3bff8ee 100644 (file)
@@ -27,6 +27,8 @@
 #include "dc_dmub_srv.h"
 #include "../dmub/dmub_srv.h"
 #include "dm_helpers.h"
+#include "dc_hw_types.h"
+#include "core_types.h"
 
 #define CTX dc_dmub_srv->ctx
 #define DC_LOGGER CTX->logger
index 50e44b53f14c2393933e93faf4e91ee9f22b14d6..52758ff1e405703d002c098aeea0bc7609d7d3d7 100644 (file)
 
 struct dmub_srv;
 struct dc;
+struct pipe_ctx;
+struct dc_crtc_timing_adjust;
+struct dc_crtc_timing;
+struct dc_state;
 
 struct dc_reg_helper_state {
        bool gather_in_progress;
@@ -69,7 +73,6 @@ bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_bu
 void dc_dmub_trace_event_control(struct dc *dc, bool enable);
 
 void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub);
-
 void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv);
 void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv);
 void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, union dmub_inbox0_data_register data);
index f8f66790d09bfe68c53903b6869313ee6e132f90..68cf06a5a3e3cb28a15c16899ad8f5fb603eb0e8 100644 (file)
@@ -205,6 +205,7 @@ struct dc_stream_state {
        bool use_vsc_sdp_for_colorimetry;
        bool ignore_msa_timing_param;
 
+       bool allow_freesync;
        bool freesync_on_desktop;
 
        bool converter_disable_audio;
@@ -295,9 +296,9 @@ struct dc_stream_update {
        struct dc_info_packet *vrr_infopacket;
        struct dc_info_packet *vsc_infopacket;
        struct dc_info_packet *vsp_infopacket;
-
        bool *dpms_off;
        bool integer_scaling_update;
+       bool *allow_freesync;
 
        struct colorspace_transform *gamut_remap;
        enum dc_color_space *output_color_space;
index 573d5be9e302d38eb9d0d9d8dc02bf7ad844aff2..fff724e94eed0e2749070f5249d76dd57a995a05 100644 (file)
@@ -2613,7 +2613,6 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
        dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
 
        ASSERT(new_mpcc != NULL);
-
        hubp->opp_id = pipe_ctx->stream_res.opp->inst;
        hubp->mpcc_id = mpcc_id;
 }
index facd4e01b7ac126a8770140e69e2378ff840cd5d..76f8b40b216515ef6d14ef91aee3c78fba228053 100644 (file)
@@ -2446,7 +2446,6 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
                        NULL,
                        hubp->inst,
                        mpcc_id);
-
        dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
 
        ASSERT(new_mpcc != NULL);
index ecdc7c7812172a4d92f28da363df0c9d22edab2f..08b8893ff145342122a1be3274fa63e095f762ae 100644 (file)
@@ -48,6 +48,8 @@
 #include "dc_dmub_srv.h"
 #include "link_hwss.h"
 #include "dpcd_defs.h"
+#include "../dcn20/dcn20_hwseq.h"
+#include "dcn30_resource.h"
 #include "inc/dc_link_dp.h"
 #include "inc/link_dpcd.h"
 
@@ -344,17 +346,6 @@ void dcn30_enable_writeback(
        dwb->funcs->enable(dwb, &wb_info->dwb_params);
 }
 
-void dcn30_prepare_bandwidth(struct dc *dc,
-       struct dc_state *context)
-{
-       if (dc->clk_mgr->dc_mode_softmax_enabled)
-               if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
-                               context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
-                       dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
-
-       dcn20_prepare_bandwidth(dc, context);
-}
-
 void dcn30_disable_writeback(
                struct dc *dc,
                unsigned int dwb_pipe_inst)
@@ -647,6 +638,9 @@ void dcn30_init_hw(struct dc *dc)
        if (dc->res_pool->hubbub->funcs->init_crb)
                dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
 
+       // Get DMCUB capabilities
+       dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
+       dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
 }
 
 void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
@@ -962,3 +956,15 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
        pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
                        color_space, color_depth, solid_color, width, height, offset);
 }
+
+void dcn30_prepare_bandwidth(struct dc *dc,
+       struct dc_state *context)
+{
+       if (dc->clk_mgr->dc_mode_softmax_enabled)
+               if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
+                               context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
+                       dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
+
+       dcn20_prepare_bandwidth(dc, context);
+}
+
index 73e7b690e82c90660c0437785cbd9c25aaa84cdf..a24a8e33a3d289e8b99a78fa0d377263fbedde2e 100644 (file)
@@ -47,9 +47,6 @@ void dcn30_disable_writeback(
                struct dc *dc,
                unsigned int dwb_pipe_inst);
 
-void dcn30_prepare_bandwidth(struct dc *dc,
-       struct dc_state *context);
-
 bool dcn30_mmhubbub_warmup(
        struct dc *dc,
        unsigned int num_dwb,
@@ -83,4 +80,12 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
                const struct tg_color *solid_color,
                int width, int height, int offset);
 
+void dcn30_set_hubp_blank(const struct dc *dc,
+               struct pipe_ctx *pipe_ctx,
+               bool blank_enable);
+
+void dcn30_prepare_bandwidth(struct dc *dc,
+       struct dc_state *context);
+
+
 #endif /* __DC_HWSS_DCN30_H__ */
index bb347319de83a4670ffa7983a6ba6c3e98a57059..4c06e6e1ba4a6f654e79c1e74d1ade4e52ce4b93 100644 (file)
@@ -59,7 +59,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = {
        .pipe_control_lock = dcn20_pipe_control_lock,
        .interdependent_update_lock = dcn10_lock_all_pipes,
        .cursor_lock = dcn10_cursor_lock,
-       .prepare_bandwidth = dcn20_prepare_bandwidth,
+       .prepare_bandwidth = dcn30_prepare_bandwidth,
        .optimize_bandwidth = dcn20_optimize_bandwidth,
        .update_bandwidth = dcn20_update_bandwidth,
        .set_drr = dcn10_set_drr,
index b604fb26f288d718dd214ecb4576e78bb8a5ccac..9a440ae8f865782ff6fef91f1fbdc1346701cf9b 100644 (file)
@@ -27,6 +27,7 @@
 #include "dcn30_optc.h"
 #include "dc.h"
 #include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
 
 #include "dml/dcn30/dcn30_fpu.h"
 
index 1c1a67c4cec1c5f0d9857e4f1d50145e078fd60a..4cf9a6cff46ea12f44ce763f760453f46e50b1f2 100644 (file)
@@ -89,6 +89,7 @@
 #include "vm_helper.h"
 #include "dcn20/dcn20_vmid.h"
 #include "amdgpu_socbb.h"
+#include "dc_dmub_srv.h"
 
 #define DC_LOGGER_INIT(logger)
 
index 62a62e4fc4a8dad709fa85298fb796b486904f4a..ded45f8f4b8215d545f8b8ea6fc4734d0fc3e1cd 100644 (file)
@@ -68,6 +68,7 @@ struct dce_hwseq;
 struct timing_generator;
 struct tg_color;
 struct output_pixel_processor;
+struct mpcc_blnd_cfg;
 
 struct hwseq_private_funcs {
 
index 03fa63d56fa65d2bc3898a32cc62d9d958f05c8f..aa121d45d9b8f691b718dcea39bca9fb261bee10 100644 (file)
@@ -1374,6 +1374,11 @@ unsigned long long mod_freesync_calc_field_rate_from_timing(
        return field_rate_in_uhz;
 }
 
+bool mod_freesync_get_freesync_enabled(struct mod_vrr_params *pVrr, struct dc_stream_state *const pStream)
+{
+       return (pVrr->state != VRR_STATE_UNSUPPORTED) && (pVrr->state != VRR_STATE_DISABLED);
+}
+
 bool mod_freesync_is_valid_range(uint32_t min_refresh_cap_in_uhz,
                uint32_t max_refresh_cap_in_uhz,
                uint32_t nominal_field_rate_in_uhz)
index cf6bc94462445ceceef1778250a1215859147f55..62e326dd29a8d520ee83f8f2188ebc6212949f69 100644 (file)
@@ -194,4 +194,8 @@ unsigned int mod_freesync_calc_v_total_from_refresh(
                const struct dc_stream_state *stream,
                unsigned int refresh_in_uhz);
 
+// Returns true when FreeSync is supported and enabled (even if it is inactive)
+bool mod_freesync_get_freesync_enabled(struct mod_vrr_params *pVrr,
+               struct dc_stream_state *const pStream);
+
 #endif