From 5c69cc559afb76b729478c7abae8e27bfc401442 Mon Sep 17 00:00:00 2001 From: Jayendran Ramani Date: Tue, 4 May 2021 13:41:18 -0400 Subject: [PATCH] drm/amd/display: Return last used DRR VTOTAL from DC [How] Add call to get the last used VTOTAL from DC Signed-off-by: Jayendran Ramani Reviewed-by: Anthony Koo Acked-by: Stylon Wang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 42 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_stream.h | 4 ++ .../dc/dce110/dce110_timing_generator.c | 1 + .../dc/dce120/dce120_timing_generator.c | 1 + .../display/dc/dce80/dce80_timing_generator.c | 1 + .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 1 + .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | 4 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 10 ++++- .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h | 9 +++- .../gpu/drm/amd/display/dc/dcn30/dcn30_optc.c | 1 + .../gpu/drm/amd/display/dc/dcn30/dcn30_optc.h | 6 ++- .../amd/display/dc/inc/hw/timing_generator.h | 1 + 12 files changed, 75 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2b7639af4cd0..be1dbd3136ec 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -325,6 +325,48 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, return ret; } +/** + ***************************************************************************** + * Function: dc_stream_get_last_vrr_vtotal + * + * @brief + * Looks up the pipe context of dc_stream_state and gets the + * last VTOTAL used by DRR (Dynamic Refresh Rate) + * + * @param [in] dc: dc reference + * @param [in] stream: Initial dc stream state + * @param [in] adjust: Updated parameters for vertical_total_min and + * vertical_total_max + ***************************************************************************** + */ +bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, + struct dc_stream_state *stream, + uint32_t *refresh_rate) +{ + bool status = false; + + int i = 0; + + 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) { + /* Only execute if a function pointer has been defined for + * the DC version in question + */ + if (pipe->stream_res.tg->funcs->get_last_used_drr_vtotal) { + pipe->stream_res.tg->funcs->get_last_used_drr_vtotal(pipe->stream_res.tg, refresh_rate); + + status = true; + + break; + } + } + } + + return status; +} + bool dc_stream_get_crtc_position(struct dc *dc, struct dc_stream_state **streams, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos) diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 0ab1a33dae84..b8ebc1f09538 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -465,6 +465,10 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, struct dc_stream_state *stream, struct dc_crtc_timing_adjust *adjust); +bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, + struct dc_stream_state *stream, + uint32_t *refresh_rate); + bool dc_stream_get_crtc_position(struct dc *dc, struct dc_stream_state **stream, int num_streams, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index d88a74559edd..27cbb5b42c7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -2231,6 +2231,7 @@ static const struct timing_generator_funcs dce110_tg_funcs = { dce110_timing_generator_enable_advanced_request, .set_drr = dce110_timing_generator_set_drr, + .get_last_used_drr_vtotal = NULL, .set_static_screen_control = dce110_timing_generator_set_static_screen_control, .set_test_pattern = dce110_timing_generator_set_test_pattern, diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index b57c466124e7..4af0c70098c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -1190,6 +1190,7 @@ static const struct timing_generator_funcs dce120_tg_funcs = { .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock, .enable_advanced_request = dce120_timing_generator_enable_advanced_request, .set_drr = dce120_timing_generator_set_drr, + .get_last_used_drr_vtotal = NULL, .set_static_screen_control = dce120_timing_generator_set_static_screen_control, .set_test_pattern = dce120_timing_generator_set_test_pattern, .arm_vert_intr = dce120_arm_vert_intr, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index 397e7f94e1e8..b8fd43dc010b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -209,6 +209,7 @@ static const struct timing_generator_funcs dce80_tg_funcs = { .tear_down_global_swap_lock = dce110_timing_generator_tear_down_global_swap_lock, .set_drr = dce110_timing_generator_set_drr, + .get_last_used_drr_vtotal = NULL, .set_static_screen_control = dce110_timing_generator_set_static_screen_control, .set_test_pattern = dce110_timing_generator_set_test_pattern, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 9bc97e9c48c2..3696faf12d86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -1554,6 +1554,7 @@ static const struct timing_generator_funcs dcn10_tg_funcs = { .unlock = optc1_unlock, .enable_optc_clock = optc1_enable_optc_clock, .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = NULL, .set_static_screen_control = optc1_set_static_screen_control, .set_test_pattern = optc1_set_test_pattern, .program_stereo = optc1_program_stereo, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index a6b74907fe8d..29d6fbe0093a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -171,6 +171,7 @@ struct dcn_optc_registers { uint32_t OPTC_DATA_FORMAT_CONTROL; uint32_t OPTC_BYTES_PER_PIXEL; uint32_t OPTC_WIDTH_CONTROL; + uint32_t OTG_DRR_CONTROL; uint32_t OTG_BLANK_DATA_COLOR; uint32_t OTG_BLANK_DATA_COLOR_EXT; uint32_t OTG_DRR_TRIGGER_WINDOW; @@ -517,7 +518,8 @@ struct dcn_optc_registers { type OTG_CRC_DSC_MODE;\ type OTG_CRC_DATA_STREAM_COMBINE_MODE;\ type OTG_CRC_DATA_STREAM_SPLIT_MODE;\ - type OTG_CRC_DATA_FORMAT; + type OTG_CRC_DATA_FORMAT;\ + type OTG_V_TOTAL_LAST_USED_BY_DRR; struct dcn_optc_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c index 3139d90017ee..7fa9fc656b0c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c @@ -520,6 +520,14 @@ bool optc2_configure_crc(struct timing_generator *optc, return optc1_configure_crc(optc, params); } + +void optc2_get_last_used_drr_vtotal(struct timing_generator *optc, uint32_t *refresh_rate) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET(OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, refresh_rate); +} + static struct timing_generator_funcs dcn20_tg_funcs = { .validate_timing = optc1_validate_timing, .program_timing = optc1_program_timing, @@ -553,6 +561,7 @@ static struct timing_generator_funcs dcn20_tg_funcs = { .lock_doublebuffer_disable = optc2_lock_doublebuffer_disable, .enable_optc_clock = optc1_enable_optc_clock, .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, .set_static_screen_control = optc1_set_static_screen_control, .program_stereo = optc1_program_stereo, .is_stereo_left_eye = optc1_is_stereo_left_eye, @@ -591,4 +600,3 @@ void dcn20_timing_generator_init(struct optc *optc1) optc1->min_h_sync_width = 4;// Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue. optc1->min_v_sync_width = 1; } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h index 3dee2ec2a1bb..be19a6885fbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h @@ -42,7 +42,8 @@ SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ SR(DWB_SOURCE_SELECT),\ - SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst) + SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst), \ + SRI(OTG_DRR_CONTROL, OTG, inst) #define TG_COMMON_MASK_SH_LIST_DCN2_0(mask_sh)\ TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ @@ -75,10 +76,14 @@ SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_MANUAL_FLOW_CONTROL, MANUAL_FLOW_CONTROL, mask_sh) + SF(OTG0_OTG_MANUAL_FLOW_CONTROL, MANUAL_FLOW_CONTROL, mask_sh), \ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) void dcn20_timing_generator_init(struct optc *optc); +void optc2_get_last_used_drr_vtotal(struct timing_generator *optc, + uint32_t *refresh_rate); + bool optc2_enable_crtc(struct timing_generator *optc); void optc2_set_gsl(struct timing_generator *optc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c index ac478bdcfb2a..f37e8254df21 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c @@ -315,6 +315,7 @@ static struct timing_generator_funcs dcn30_tg_funcs = { .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, .enable_optc_clock = optc1_enable_optc_clock, .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, .set_static_screen_control = optc1_set_static_screen_control, .program_stereo = optc1_program_stereo, .is_stereo_left_eye = optc1_is_stereo_left_eye, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h index 379616831636..736e63bc80c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h @@ -87,7 +87,8 @@ SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ SR(GSL_SOURCE_SELECT),\ - SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst) + SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ + SRI(OTG_DRR_CONTROL, OTG, inst) #define OPTC_COMMON_REG_LIST_DCN3_0(inst) \ @@ -233,7 +234,8 @@ SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh) + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) #define OPTC_COMMON_MASK_SH_LIST_DCN3_0(mask_sh)\ OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh),\ 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 a77eb9cd049f..8f06e273e703 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 @@ -227,6 +227,7 @@ 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_vtotal_min_max)(struct timing_generator *optc, int vtotal_min, int vtotal_max); + void (*get_last_used_drr_vtotal)(struct timing_generator *optc, uint32_t *refresh_rate); void (*set_static_screen_control)(struct timing_generator *tg, uint32_t event_triggers, uint32_t num_frames);