OSDN Git Service

drm/amd/display: make PSR static screen entry within 30 ms
authorAnthony Koo <Anthony.Koo@amd.com>
Mon, 9 Dec 2019 22:26:34 +0000 (17:26 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 16 Jan 2020 19:16:08 +0000 (14:16 -0500)
[Why]
With different refresh rate panels, the PSR entry/exit time is
different since it is dependent on 2 frame entry time today

[How]
Make static screen num frame entry time to be calculated
such that entry time is within 30 ms instead of fixed num
frames.

Signed-off-by: Anthony Koo <Anthony.Koo@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
18 files changed:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dc_types.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h

index 504278d..9402374 100644 (file)
@@ -8393,17 +8393,37 @@ static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream)
 bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
 {
        struct dc_link *link = stream->link;
-       struct dc_static_screen_events triggers = {0};
+       unsigned int vsync_rate_hz = 0;
+       struct dc_static_screen_params params = {0};
+       /* Calculate number of static frames before generating interrupt to
+        * enter PSR.
+        */
+       unsigned int frame_time_microsec = 1000000 / vsync_rate_hz;
+       // Init fail safe of 2 frames static
+       unsigned int num_frames_static = 2;
 
        DRM_DEBUG_DRIVER("Enabling psr...\n");
 
-       triggers.cursor_update = true;
-       triggers.overlay_update = true;
-       triggers.surface_update = true;
+       vsync_rate_hz = div64_u64(div64_u64((
+                       stream->timing.pix_clk_100hz * 100),
+                       stream->timing.v_total),
+                       stream->timing.h_total);
+
+       /* Round up
+        * Calculate number of frames such that at least 30 ms of time has
+        * passed.
+        */
+       if (vsync_rate_hz != 0)
+               num_frames_static = (30000 / frame_time_microsec) + 1;
+
+       params.triggers.cursor_update = true;
+       params.triggers.overlay_update = true;
+       params.triggers.surface_update = true;
+       params.num_frames = num_frames_static;
 
-       dc_stream_set_static_screen_events(link->ctx->dc,
+       dc_stream_set_static_screen_params(link->ctx->dc,
                                           &stream, 1,
-                                          &triggers);
+                                          &params);
 
        return dc_link_set_psr_allow_active(link, true, false);
 }
index c918a0c..6c797fa 100644 (file)
@@ -510,10 +510,10 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
        return ret;
 }
 
-void dc_stream_set_static_screen_events(struct dc *dc,
+void dc_stream_set_static_screen_params(struct dc *dc,
                struct dc_stream_state **streams,
                int num_streams,
-               const struct dc_static_screen_events *events)
+               const struct dc_static_screen_params *params)
 {
        int i = 0;
        int j = 0;
@@ -532,7 +532,7 @@ void dc_stream_set_static_screen_events(struct dc *dc,
                }
        }
 
-       dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events);
+       dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, params);
 }
 
 static void dc_destruct(struct dc *dc)
index 17f00cb..26dce39 100644 (file)
@@ -2542,7 +2542,7 @@ bool dc_link_setup_psr(struct dc_link *link,
                transmitter_to_phy_id(link->link_enc->transmitter);
 
        psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
-       psr_context->vsyncRateHz = div64_u64(div64_u64((stream->
+       psr_context->vsync_rate_hz = div64_u64(div64_u64((stream->
                                        timing.pix_clk_100hz * 100),
                                        stream->timing.v_total),
                                        stream->timing.h_total);
index e1c11af..7639fa0 100644 (file)
@@ -157,11 +157,14 @@ struct dc_surface_dcc_cap {
        bool const_color_support;
 };
 
-struct dc_static_screen_events {
-       bool force_trigger;
-       bool cursor_update;
-       bool surface_update;
-       bool overlay_update;
+struct dc_static_screen_params {
+       struct {
+               bool force_trigger;
+               bool cursor_update;
+               bool surface_update;
+               bool overlay_update;
+       } triggers;
+       unsigned int num_frames;
 };
 
 
index 37c10db..92096de 100644 (file)
@@ -439,10 +439,10 @@ bool dc_stream_get_crc(struct dc *dc,
                       uint32_t *g_y,
                       uint32_t *b_cb);
 
-void dc_stream_set_static_screen_events(struct dc *dc,
+void dc_stream_set_static_screen_params(struct dc *dc,
                                        struct dc_stream_state **stream,
                                        int num_streams,
-                                       const struct dc_static_screen_events *events);
+                                       const struct dc_static_screen_params *params);
 
 void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream,
                enum dc_dynamic_expansion option);
index 4b5b975..e59532d 100644 (file)
@@ -729,7 +729,7 @@ struct psr_context {
        /* The VSync rate in Hz used to calculate the
         * step size for smooth brightness feature
         */
-       unsigned int vsyncRateHz;
+       unsigned int vsync_rate_hz;
        unsigned int skipPsrWaitForPllLock;
        unsigned int numberOfControllers;
        /* Unused, for future use. To indicate that first changed frame from
index 4939cf3..5b68927 100644 (file)
@@ -1373,9 +1373,13 @@ static enum dc_status apply_single_controller_ctx_to_hw(
        // DRR should set trigger event to monitor surface update event
        if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
                event_triggers = 0x80;
+       /* Event triggers and num frames initialized for DRR, but can be
+        * later updated for PSR use. Note DRR trigger events are generated
+        * regardless of whether num frames met.
+        */
        if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
                pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
-                               pipe_ctx->stream_res.tg, event_triggers);
+                               pipe_ctx->stream_res.tg, event_triggers, 2);
 
        if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
                pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg(
@@ -1706,6 +1710,8 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
        struct drr_params params = {0};
        // DRR should set trigger event to monitor surface update event
        unsigned int event_triggers = 0x80;
+       // Note DRR trigger events are generated regardless of whether num frames met.
+       unsigned int num_frames = 2;
 
        params.vertical_total_max = vmax;
        params.vertical_total_min = vmin;
@@ -1721,7 +1727,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
                if (vmax != 0 && vmin != 0)
                        pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
                                        pipe_ctx[i]->stream_res.tg,
-                                       event_triggers);
+                                       event_triggers, num_frames);
        }
 }
 
@@ -1738,30 +1744,31 @@ static void get_position(struct pipe_ctx **pipe_ctx,
 }
 
 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
-               int num_pipes, const struct dc_static_screen_events *events)
+               int num_pipes, const struct dc_static_screen_params *params)
 {
        unsigned int i;
-       unsigned int value = 0;
+       unsigned int triggers = 0;
 
-       if (events->overlay_update)
-               value |= 0x100;
-       if (events->surface_update)
-               value |= 0x80;
-       if (events->cursor_update)
-               value |= 0x2;
-       if (events->force_trigger)
-               value |= 0x1;
+       if (params->triggers.overlay_update)
+               triggers |= 0x100;
+       if (params->triggers.surface_update)
+               triggers |= 0x80;
+       if (params->triggers.cursor_update)
+               triggers |= 0x2;
+       if (params->triggers.force_trigger)
+               triggers |= 0x1;
 
        if (num_pipes) {
                struct dc *dc = pipe_ctx[0]->stream->ctx->dc;
 
                if (dc->fbc_compressor)
-                       value |= 0x84;
+                       triggers |= 0x84;
        }
 
        for (i = 0; i < num_pipes; i++)
                pipe_ctx[i]->stream_res.tg->funcs->
-                       set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
+                       set_static_screen_control(pipe_ctx[i]->stream_res.tg,
+                                       triggers, params->num_frames);
 }
 
 /*
index 5f7c2c5..1ea7db8 100644 (file)
@@ -469,22 +469,27 @@ void dce110_timing_generator_set_drr(
 
 void dce110_timing_generator_set_static_screen_control(
        struct timing_generator *tg,
-       uint32_t value)
+       uint32_t event_triggers,
+       uint32_t num_frames)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
        uint32_t static_screen_cntl = 0;
        uint32_t addr = 0;
 
+       // By register spec, it only takes 8 bit value
+       if (num_frames > 0xFF)
+               num_frames = 0xFF;
+
        addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
        static_screen_cntl = dm_read_reg(tg->ctx, addr);
 
        set_reg_field_value(static_screen_cntl,
-                               value,
+                               event_triggers,
                                CRTC_STATIC_SCREEN_CONTROL,
                                CRTC_STATIC_SCREEN_EVENT_MASK);
 
        set_reg_field_value(static_screen_cntl,
-                               2,
+                               num_frames,
                                CRTC_STATIC_SCREEN_CONTROL,
                                CRTC_STATIC_SCREEN_FRAME_COUNT);
 
index 768ccf2..d8a5ed7 100644 (file)
@@ -231,7 +231,8 @@ void dce110_timing_generator_set_drr(
 
 void dce110_timing_generator_set_static_screen_control(
        struct timing_generator *tg,
-       uint32_t value);
+       uint32_t event_triggers,
+       uint32_t num_frames);
 
 void dce110_timing_generator_get_crtc_scanoutpos(
        struct timing_generator *tg,
index 098e569..82bc4e1 100644 (file)
@@ -819,13 +819,18 @@ void dce120_tg_set_colors(struct timing_generator *tg,
 
 static void dce120_timing_generator_set_static_screen_control(
        struct timing_generator *tg,
-       uint32_t value)
+       uint32_t event_triggers,
+       uint32_t num_frames)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 
+       // By register spec, it only takes 8 bit value
+       if (num_frames > 0xFF)
+               num_frames = 0xFF;
+
        CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
-                       CRTC_STATIC_SCREEN_EVENT_MASK, value,
-                       CRTC_STATIC_SCREEN_FRAME_COUNT, 2);
+                       CRTC_STATIC_SCREEN_EVENT_MASK, event_triggers,
+                       CRTC_STATIC_SCREEN_FRAME_COUNT, num_frames);
 }
 
 void dce120_timing_generator_set_test_pattern(
index 2baff3c..5347a85 100644 (file)
@@ -2704,6 +2704,8 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
        struct drr_params params = {0};
        // DRR set trigger event mapped to OTG_TRIG_A (bit 11) for manual control flow
        unsigned int event_triggers = 0x800;
+       // Note DRR trigger events are generated regardless of whether num frames met.
+       unsigned int num_frames = 2;
 
        params.vertical_total_max = vmax;
        params.vertical_total_min = vmin;
@@ -2720,7 +2722,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
                if (vmax != 0 && vmin != 0)
                        pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
                                        pipe_ctx[i]->stream_res.tg,
-                                       event_triggers);
+                                       event_triggers, num_frames);
        }
 }
 
@@ -2737,21 +2739,22 @@ void dcn10_get_position(struct pipe_ctx **pipe_ctx,
 }
 
 void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
-               int num_pipes, const struct dc_static_screen_events *events)
+               int num_pipes, const struct dc_static_screen_params *params)
 {
        unsigned int i;
-       unsigned int value = 0;
+       unsigned int triggers = 0;
 
-       if (events->surface_update)
-               value |= 0x80;
-       if (events->cursor_update)
-               value |= 0x2;
-       if (events->force_trigger)
-               value |= 0x1;
+       if (params->triggers.surface_update)
+               triggers |= 0x80;
+       if (params->triggers.cursor_update)
+               triggers |= 0x2;
+       if (params->triggers.force_trigger)
+               triggers |= 0x1;
 
        for (i = 0; i < num_pipes; i++)
                pipe_ctx[i]->stream_res.tg->funcs->
-                       set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
+                       set_static_screen_control(pipe_ctx[i]->stream_res.tg,
+                                       triggers, params->num_frames);
 }
 
 static void dcn10_config_stereo_parameters(
index 55b8f3b..4d20f65 100644 (file)
@@ -132,7 +132,7 @@ void dcn10_get_position(struct pipe_ctx **pipe_ctx,
                int num_pipes,
                struct crtc_position *position);
 void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
-               int num_pipes, const struct dc_static_screen_events *events);
+               int num_pipes, const struct dc_static_screen_params *params);
 void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc);
 void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable);
 void dcn10_log_hw_state(struct dc *dc,
index cd7412d..a9a43b3 100644 (file)
@@ -789,21 +789,26 @@ void optc1_set_early_control(
 
 void optc1_set_static_screen_control(
        struct timing_generator *optc,
-       uint32_t value)
+       uint32_t event_triggers,
+       uint32_t num_frames)
 {
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
 
+       // By register spec, it only takes 8 bit value
+       if (num_frames > 0xFF)
+               num_frames = 0xFF;
+
        /* Bit 8 is no longer applicable in RV for PSR case,
         * set bit 8 to 0 if given
         */
-       if ((value & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN)
+       if ((event_triggers & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN)
                        != 0)
-               value = value &
+               event_triggers = event_triggers &
                ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN;
 
        REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0,
-                       OTG_STATIC_SCREEN_EVENT_MASK, value,
-                       OTG_STATIC_SCREEN_FRAME_COUNT, 2);
+                       OTG_STATIC_SCREEN_EVENT_MASK, event_triggers,
+                       OTG_STATIC_SCREEN_FRAME_COUNT, num_frames);
 }
 
 void optc1_setup_manual_trigger(struct timing_generator *optc)
index 3afeb1a..f277656 100644 (file)
@@ -625,7 +625,8 @@ void optc1_set_drr(
 
 void optc1_set_static_screen_control(
        struct timing_generator *optc,
-       uint32_t value);
+       uint32_t event_triggers,
+       uint32_t num_frames);
 
 void optc1_program_stereo(struct timing_generator *optc,
        const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags);
index 5b9cbed..8992092 100644 (file)
@@ -686,9 +686,13 @@ enum dc_status dcn20_enable_stream_timing(
        // DRR should set trigger event to monitor surface update event
        if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
                event_triggers = 0x80;
+       /* Event triggers and num frames initialized for DRR, but can be
+        * later updated for PSR use. Note DRR trigger events are generated
+        * regardless of whether num frames met.
+        */
        if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
                pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
-                               pipe_ctx->stream_res.tg, event_triggers);
+                               pipe_ctx->stream_res.tg, event_triggers, 2);
 
        /* TODO program crtc source select for non-virtual signal*/
        /* TODO program FMT */
index 2d3efd7..e5e7d94 100644 (file)
@@ -208,7 +208,8 @@ struct timing_generator_funcs {
                                        bool enable, const struct dc_crtc_timing *timing);
        void (*set_drr)(struct timing_generator *tg, const struct drr_params *params);
        void (*set_static_screen_control)(struct timing_generator *tg,
-                                                       uint32_t value);
+                                               uint32_t event_triggers,
+                                               uint32_t num_frames);
        void (*set_test_pattern)(
                struct timing_generator *tg,
                enum controller_dp_test_pattern test_pattern,
index df32046..209118f 100644 (file)
@@ -42,7 +42,7 @@ struct dc_state;
 struct dc_stream_status;
 struct dc_writeback_info;
 struct dchub_init_data;
-struct dc_static_screen_events;
+struct dc_static_screen_params;
 struct resource_pool;
 struct dc_phy_addr_space_config;
 struct dc_virtual_addr_space_config;
@@ -102,7 +102,7 @@ struct hw_sequencer_funcs {
                        unsigned int vmid, unsigned int vmid_frame_number);
        void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx,
                        int num_pipes,
-                       const struct dc_static_screen_events *events);
+                       const struct dc_static_screen_params *events);
 
        /* Stream Related */
        void (*enable_stream)(struct pipe_ctx *pipe_ctx);
index 8ba06f0..ecf5663 100644 (file)
@@ -51,7 +51,7 @@ struct dc_state;
 struct dc_stream_status;
 struct dc_writeback_info;
 struct dchub_init_data;
-struct dc_static_screen_events;
+struct dc_static_screen_params;
 struct resource_pool;
 struct resource_context;
 struct stream_resource;