From: Robin Chen <robin.c...@amd.com>

[WHY]
We want to support low hz case, but the original
vtotal/vtotal_min/vtotal_max can't support more
than 0x7FFF.

[HOW]
We use the 2 HW reg to contorl long vblank case.
1. OTG_V_COUNT_STOP_CONTROL -> vcount_stop
2. OTG_V_COUNT_STOP_CONTROL2 -> vcount_stop_timer

vcount_stop define from which line we stop using vcount
and start using vcount2.
vcount_stop_timer define how long we use vcount2.

Ex:
Vtotal = 7
OTG_V_COUNT_STOP_CONTROL = 4
OTG_V_COUNT_STOP_CONTROL2 = 5

time    : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
vcount  : 0, 1, 2, 3, -  -  -  -  -  4,  5,  6
vcount2 :             0, 1, 2, 3, 4,

Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Alex Hung <alex.h...@amd.com>
Signed-off-by: ChunTao Tso <chuntao....@amd.com>
Signed-off-by: Robin Chen<robin.c...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  33 ++++
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |  28 +++
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.h   |   3 +
 .../amd/display/dc/hwss/dcn35/dcn35_init.c    |   3 +-
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |   1 +
 .../amd/display/dc/inc/hw/timing_generator.h  |   7 +
 .../amd/display/dc/optc/dcn10/dcn10_optc.h    |   6 +-
 .../amd/display/dc/optc/dcn35/dcn35_optc.c    | 165 +++++++++++++++++-
 .../amd/display/dc/optc/dcn35/dcn35_optc.h    |   6 +-
 .../dc/resource/dcn35/dcn35_resource.h        |   2 +
 .../amd/display/modules/freesync/freesync.c   |   2 +
 12 files changed, 253 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 501e0298623a..daf6c7fe0906 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -386,6 +386,30 @@ static void dc_perf_trace_destroy(struct dc_perf_trace 
**perf_trace)
        *perf_trace = NULL;
 }
 
+static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, 
struct dc_crtc_timing_adjust *adjust)
+{
+       if (!dc || !stream || !adjust)
+               return false;
+
+       if (!dc->current_state)
+               return false;
+
+       int i;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+               if (pipe->stream == stream && pipe->stream_res.tg) {
+                       if (dc->hwss.set_long_vtotal)
+                               dc->hwss.set_long_vtotal(&pipe, 1, 
adjust->v_total_min, adjust->v_total_max);
+
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 /**
  *  dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR
  *  @dc:     dc reference
@@ -420,6 +444,15 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
        stream->adjust.v_total_mid = adjust->v_total_mid;
        stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
        stream->adjust.v_total_min = adjust->v_total_min;
+       stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt;
+
+       if (dc->caps.max_v_total != 0 &&
+               (adjust->v_total_max > dc->caps.max_v_total || 
adjust->v_total_min > dc->caps.max_v_total)) {
+               if (adjust->allow_otg_v_count_halt)
+                       return set_long_vtotal(dc, stream, adjust);
+               else
+                       return false;
+       }
 
        for (i = 0; i < MAX_PIPES; i++) {
                struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h 
b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index aae2f3a2660d..465e15f57f93 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -974,6 +974,7 @@ struct dc_crtc_timing_adjust {
        uint32_t v_total_max;
        uint32_t v_total_mid;
        uint32_t v_total_mid_frame_num;
+       uint32_t allow_otg_v_count_halt;
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index 4b92df23ff0d..2e8ec58a16eb 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -1394,3 +1394,31 @@ void dcn35_set_static_screen_control(struct pipe_ctx 
**pipe_ctx,
                        set_static_screen_control(pipe_ctx[i]->stream_res.tg,
                                        triggers, params->num_frames);
 }
+
+void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx,
+               int num_pipes, uint32_t v_total_min, uint32_t v_total_max)
+{
+       int i = 0;
+       struct long_vtotal_params params = {0};
+
+       params.vertical_total_max = v_total_max;
+       params.vertical_total_min = v_total_min;
+
+       for (i = 0; i < num_pipes; i++) {
+               if (!pipe_ctx[i])
+                       continue;
+
+               if (pipe_ctx[i]->stream) {
+                       struct dc_crtc_timing *timing = 
&pipe_ctx[i]->stream->timing;
+
+                       if (timing)
+                               params.vertical_blank_start = timing->v_total - 
timing->v_front_porch;
+                       else
+                               params.vertical_blank_start = 0;
+
+                       if ((pipe_ctx[i]->stream_res.tg != NULL) && 
pipe_ctx[i]->stream_res.tg->funcs &&
+                               
pipe_ctx[i]->stream_res.tg->funcs->set_long_vtotal)
+                               
pipe_ctx[i]->stream_res.tg->funcs->set_long_vtotal(pipe_ctx[i]->stream_res.tg, 
&params);
+               }
+       }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
index c354efa6c1b2..7c33bea3f4e7 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
@@ -93,4 +93,7 @@ void dcn35_set_drr(struct pipe_ctx **pipe_ctx,
 void dcn35_set_static_screen_control(struct pipe_ctx **pipe_ctx,
                int num_pipes, const struct dc_static_screen_params *params);
 
+void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx,
+               int num_pipes, uint32_t v_total_min, uint32_t v_total_max);
+
 #endif /* __DC_HWSS_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
index a93073055e7b..dce620d359a6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
@@ -122,7 +122,8 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
        .hw_block_power_down = dcn35_hw_block_power_down,
        .root_clock_control = dcn35_root_clock_control,
        .set_idle_state = dcn35_set_idle_state,
-       .get_idle_state = dcn35_get_idle_state
+       .get_idle_state = dcn35_get_idle_state,
+       .set_long_vtotal = dcn35_set_long_vblank,
 };
 
 static const struct hwseq_private_funcs dcn35_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h 
b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index f89f205e42a1..26ea86316e50 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -429,6 +429,7 @@ struct hw_sequencer_funcs {
        bool (*is_pipe_topology_transition_seamless)(struct dc *dc,
                        const struct dc_state *cur_ctx,
                        const struct dc_state *new_ctx);
+       void (*set_long_vtotal)(struct pipe_ctx **pipe_ctx, int num_pipes, 
uint32_t v_total_min, uint32_t v_total_max);
 };
 
 void color_space_to_black_color(
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index d98d72f35be5..c5527f68f076 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -64,6 +64,12 @@ struct drr_params {
        bool immediate_flip;
 };
 
+struct long_vtotal_params {
+       uint32_t vertical_total_min;
+       uint32_t vertical_total_max;
+       uint32_t vertical_blank_start;
+};
+
 #define LEFT_EYE_3D_PRIMARY_SURFACE 1
 #define RIGHT_EYE_3D_PRIMARY_SURFACE 0
 
@@ -331,6 +337,7 @@ struct timing_generator_funcs {
 
        void (*init_odm)(struct timing_generator *tg);
        void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator 
*tg);
+       void (*set_long_vtotal)(struct timing_generator *optc, const struct 
long_vtotal_params *params);
 };
 
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h 
b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
index ab81594a7fad..4cfd1ed06777 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
@@ -129,6 +129,8 @@ struct dcn_optc_registers {
        uint32_t OTG_V_TOTAL_MID;
        uint32_t OTG_V_TOTAL_MIN;
        uint32_t OTG_V_TOTAL_CONTROL;
+       uint32_t OTG_V_COUNT_STOP_CONTROL;
+       uint32_t OTG_V_COUNT_STOP_CONTROL2;
        uint32_t OTG_TRIGA_CNTL;
        uint32_t OTG_TRIGA_MANUAL_TRIG;
        uint32_t OTG_MANUAL_FLOW_CONTROL;
@@ -580,7 +582,9 @@ struct dcn_optc_registers {
        type OTG_CRC1_WINDOWB_X_END_READBACK;\
        type OTG_CRC1_WINDOWB_Y_START_READBACK;\
        type OTG_CRC1_WINDOWB_Y_END_READBACK;\
-       type OPTC_FGCG_REP_DIS;
+       type OPTC_FGCG_REP_DIS;\
+       type OTG_V_COUNT_STOP;\
+       type OTG_V_COUNT_STOP_TIMER;
 
 struct dcn_optc_shift {
        TG_REG_FIELD_LIST(uint8_t)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c 
b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
index 5b1547508850..d393be30dff8 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
@@ -32,6 +32,7 @@
 #include "reg_helper.h"
 #include "dc.h"
 #include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
 
 #define REG(reg)\
        optc1->tg_regs->reg
@@ -213,6 +214,167 @@ static bool optc35_configure_crc(struct timing_generator 
*optc,
        return true;
 }
 
+static void optc35_setup_manual_trigger(struct timing_generator *optc)
+{
+       if (!optc || !optc->ctx)
+               return;
+
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       struct dc *dc = optc->ctx->dc;
+
+       if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams)
+               dc_dmub_srv_set_drr_manual_trigger_cmd(dc, optc->inst);
+       else {
+               /*
+                * MIN_MASK_EN is gone and MASK is now always enabled.
+                *
+                * To get it to it work with manual trigger we need to make sure
+                * we program the correct bit.
+                */
+               REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+                               OTG_V_TOTAL_MIN_SEL, 1,
+                               OTG_V_TOTAL_MAX_SEL, 1,
+                               OTG_FORCE_LOCK_ON_EVENT, 0,
+                               OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */
+
+               // Setup manual flow control for EOF via TRIG_A
+               if (optc->funcs && optc->funcs->setup_manual_trigger)
+                       optc->funcs->setup_manual_trigger(optc);
+       }
+}
+
+void optc35_set_drr(
+       struct timing_generator *optc,
+       const struct drr_params *params)
+{
+       if (!optc || !params)
+               return;
+
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       uint32_t max_otg_v_total = optc1->max_v_total - 1;
+
+       if (params != NULL &&
+               params->vertical_total_max > 0 &&
+               params->vertical_total_min > 0) {
+
+               if (params->vertical_total_mid != 0) {
+
+                       REG_SET(OTG_V_TOTAL_MID, 0,
+                               OTG_V_TOTAL_MID, params->vertical_total_mid - 
1);
+
+                       REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
+                                       OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
+                                       OTG_VTOTAL_MID_FRAME_NUM,
+                                       
(uint8_t)params->vertical_total_mid_frame_num);
+
+               }
+
+               if (optc->funcs && optc->funcs->set_vtotal_min_max)
+                       optc->funcs->set_vtotal_min_max(optc,
+                               params->vertical_total_min - 1, 
params->vertical_total_max - 1);
+               optc35_setup_manual_trigger(optc);
+       } else {
+               REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+                               OTG_SET_V_TOTAL_MIN_MASK, 0,
+                               OTG_V_TOTAL_MIN_SEL, 0,
+                               OTG_V_TOTAL_MAX_SEL, 0,
+                               OTG_FORCE_LOCK_ON_EVENT, 0);
+
+               if (optc->funcs && optc->funcs->set_vtotal_min_max)
+                       optc->funcs->set_vtotal_min_max(optc, 0, 0);
+       }
+
+       REG_WRITE(OTG_V_COUNT_STOP_CONTROL, max_otg_v_total);
+       REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, 0);
+}
+
+static void optc35_set_long_vtotal(
+       struct timing_generator *optc,
+       const struct long_vtotal_params *params)
+{
+       if (!optc || !params)
+               return;
+
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       uint32_t vcount_stop_timer = 0, vcount_stop = 0;
+       uint32_t max_otg_v_total = optc1->max_v_total - 1;
+
+       if (params->vertical_total_min <= max_otg_v_total && 
params->vertical_total_max <= max_otg_v_total)
+               return;
+
+       if (params->vertical_total_max == 0 || params->vertical_total_min == 0) 
{
+               REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+                                               OTG_SET_V_TOTAL_MIN_MASK, 0,
+                                               OTG_V_TOTAL_MIN_SEL, 0,
+                                               OTG_V_TOTAL_MAX_SEL, 0,
+                                               OTG_FORCE_LOCK_ON_EVENT, 0);
+
+               if (optc->funcs && optc->funcs->set_vtotal_min_max)
+                       optc->funcs->set_vtotal_min_max(optc, 0, 0);
+       } else if (params->vertical_total_max == params->vertical_total_min) {
+               vcount_stop = params->vertical_blank_start;
+               vcount_stop_timer = params->vertical_total_max - 
max_otg_v_total;
+
+               REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+                               OTG_V_TOTAL_MIN_SEL, 1,
+                               OTG_V_TOTAL_MAX_SEL, 1,
+                               OTG_FORCE_LOCK_ON_EVENT, 0,
+                               OTG_SET_V_TOTAL_MIN_MASK, 0);
+
+               if (optc->funcs && optc->funcs->set_vtotal_min_max)
+                       optc->funcs->set_vtotal_min_max(optc, max_otg_v_total, 
max_otg_v_total);
+
+               REG_WRITE(OTG_V_COUNT_STOP_CONTROL, vcount_stop);
+               REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, vcount_stop_timer);
+       } else {
+               // Variable rate, keep DRR trigger mask
+               if (params->vertical_total_min > max_otg_v_total) {
+                       // cannot be supported
+                       // If MAX_OTG_V_COUNT < DRR trigger < v_total_min < 
v_total_max,
+                       // DRR trigger will drop the vtotal counting directly 
to a new frame.
+                       // But it should trigger between v_total_min and 
v_total_max.
+                       ASSERT(0);
+
+                       REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+                               OTG_SET_V_TOTAL_MIN_MASK, 0,
+                               OTG_V_TOTAL_MIN_SEL, 0,
+                               OTG_V_TOTAL_MAX_SEL, 0,
+                               OTG_FORCE_LOCK_ON_EVENT, 0);
+
+                       if (optc->funcs && optc->funcs->set_vtotal_min_max)
+                               optc->funcs->set_vtotal_min_max(optc, 0, 0);
+
+                       REG_WRITE(OTG_V_COUNT_STOP_CONTROL, max_otg_v_total);
+                       REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, 0);
+               } else {
+                       // For total_min <= MAX_OTG_V_COUNT and total_max > 
MAX_OTG_V_COUNT
+                       vcount_stop = params->vertical_total_min;
+                       vcount_stop_timer = params->vertical_total_max - 
max_otg_v_total;
+
+                       // Example:
+                       // params->vertical_total_min 1000
+                       // params->vertical_total_max 2000
+                       // MAX_OTG_V_COUNT_STOP = 1500
+                       //
+                       // If DRR event not happened,
+                       //     time     
0,1,2,3,4,...1000,1001,........,1500,1501,1502,     ...1999
+                       //     vcount   
0,1,2,3,4....1000...................,1001,1002,1003,...1399
+                       //     vcount2                       0,1,2,3,4,..499,
+                       // else (DRR event happened, ex : at line 1004)
+                       //     time    0,1,2,3,4,...1000,1001.....1004, 0
+                       //     vcount  0,1,2,3,4....1000,.............. 0 (new 
frame)
+                       //     vcount2                      0,1,2,   3, -
+                       if (optc->funcs && optc->funcs->set_vtotal_min_max)
+                               optc->funcs->set_vtotal_min_max(optc,
+                                       params->vertical_total_min - 1, 
max_otg_v_total);
+                       optc35_setup_manual_trigger(optc);
+
+                       REG_WRITE(OTG_V_COUNT_STOP_CONTROL, vcount_stop);
+                       REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, vcount_stop_timer);
+               }
+       }
+}
+
 static struct timing_generator_funcs dcn35_tg_funcs = {
                .validate_timing = optc1_validate_timing,
                .program_timing = optc1_program_timing,
@@ -245,7 +407,7 @@ static struct timing_generator_funcs dcn35_tg_funcs = {
                .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
                .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
                .enable_optc_clock = optc1_enable_optc_clock,
-               .set_drr = optc31_set_drr,
+               .set_drr = optc35_set_drr,
                .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
                .set_vtotal_min_max = optc1_set_vtotal_min_max,
                .set_static_screen_control = optc1_set_static_screen_control,
@@ -275,6 +437,7 @@ static struct timing_generator_funcs dcn35_tg_funcs = {
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
                .init_odm = optc3_init_odm,
+               .set_long_vtotal = optc35_set_long_vtotal,
 };
 
 void dcn35_timing_generator_init(struct optc *optc1)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h 
b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h
index 1f422e4c468f..d077e2392379 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h
@@ -65,10 +65,14 @@
        SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, 
OTG_CRC1_WINDOWB_X_END_READBACK, mask_sh),\
        SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, 
OTG_CRC1_WINDOWB_Y_START_READBACK, mask_sh),\
        SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, 
OTG_CRC1_WINDOWB_Y_END_READBACK, mask_sh),\
-       SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh)
+       SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh),\
+       SF(OTG0_OTG_V_COUNT_STOP_CONTROL, OTG_V_COUNT_STOP, mask_sh),\
+       SF(OTG0_OTG_V_COUNT_STOP_CONTROL2, OTG_V_COUNT_STOP_TIMER, mask_sh)
 
 void dcn35_timing_generator_init(struct optc *optc1);
 
 void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable);
 
+void optc35_set_drr(struct timing_generator *optc, const struct drr_params 
*params);
+
 #endif /* __DC_OPTC_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h 
b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
index a51c4a9eaafe..f97bb4cb3761 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
@@ -240,6 +240,8 @@ struct resource_pool *dcn35_create_resource_pool(
        SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst),\
        SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst),\
        SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst),\
+       SRI_ARR(OTG_V_COUNT_STOP_CONTROL, OTG, inst),\
+       SRI_ARR(OTG_V_COUNT_STOP_CONTROL2, OTG, inst),\
        SRI_ARR(OTG_TRIGA_CNTL, OTG, inst),\
        SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\
        SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c 
b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index 3955b7e4b2e2..fbaa6effd0e3 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -1126,6 +1126,8 @@ void mod_freesync_build_vrr_params(struct mod_freesync 
*mod_freesync,
                in_out_vrr->adjust.v_total_min = stream->timing.v_total;
                in_out_vrr->adjust.v_total_max = stream->timing.v_total;
        }
+
+       in_out_vrr->adjust.allow_otg_v_count_halt = (in_config->state == 
VRR_STATE_ACTIVE_FIXED) ? true : false;
 }
 
 void mod_freesync_handle_preflip(struct mod_freesync *mod_freesync,
-- 
2.34.1

Reply via email to