From c69dd2d06cdfb1bb8c6cd0ebfb3cc1e502b9de3a Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 8 May 2019 19:06:30 -0400 Subject: [PATCH] drm/amd/display: Refactor clk_mgr functions [Why] Some HW specific implementations can be pulled out into clk_mgr.c. [How] - Pull get_active_display_cnt out to clk_mgr. - Pull out shared logic in set_dispclk and set_dprefclk Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Leo Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 25 ++++++++ .../display/dc/clk_mgr/dcn10/rv1_clk_mgr.c | 25 +------- .../dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c | 58 ++++++++++--------- .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c | 43 +++++--------- .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h | 2 + 5 files changed, 71 insertions(+), 82 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 27d407a9b452..06e73ce45ed0 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -36,6 +36,31 @@ #include "dcn10/rv2_clk_mgr.h" #include "dcn20/dcn20_clk_mgr.h" + +int clk_mgr_helper_get_active_display_cnt( + struct dc *dc, + struct dc_state *context) +{ + int i, display_count; + + display_count = 0; + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream_state *stream = context->streams[i]; + + /* + * Only notify active stream or virtual stream. + * Need to notify virtual stream to work around + * headless case. HPD does not fire when system is in + * S0i2. + */ + if (!stream->dpms_off || stream->signal == SIGNAL_TYPE_VIRTUAL) + display_count++; + } + + return display_count; +} + + struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg) { struct hw_asic_id asic_id = ctx->asic_id; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c index a3f953c8839d..31db9b55e11a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c @@ -114,29 +114,6 @@ static void ramp_up_dispclk_with_dpp(struct clk_mgr_internal *clk_mgr, struct dc clk_mgr->base.clks.max_supported_dppclk_khz = new_clocks->max_supported_dppclk_khz; } -static int get_active_display_cnt( - struct dc *dc, - struct dc_state *context) -{ - int i, display_count; - - display_count = 0; - for (i = 0; i < context->stream_count; i++) { - const struct dc_stream_state *stream = context->streams[i]; - - /* - * Only notify active stream or virtual stream. - * Need to notify virtual stream to work around - * headless case. HPD does not fire when system is in - * S0i2. - */ - if (!stream->dpms_off || stream->signal == SIGNAL_TYPE_VIRTUAL) - display_count++; - } - - return display_count; -} - static void rv1_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower) @@ -156,7 +133,7 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base, pp_smu = &clk_mgr->pp_smu->rv_funcs; - display_count = get_active_display_cnt(dc, context); + display_count = clk_mgr_helper_get_active_display_cnt(dc, context); if (display_count == 0) enter_display_off = true; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c index 196087072063..1897e91c8ccb 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c @@ -68,57 +68,59 @@ static const struct IP_BASE MP1_BASE = { { { { 0x00016000, 0, 0, 0, 0 } }, #define VBIOSSMC_MSG_SetDispclkFreq 0x4 #define VBIOSSMC_MSG_SetDprefclkFreq 0x5 -int rv1_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz) +int rv1_vbios_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, unsigned int msg_id, unsigned int param) { - - int actual_dispclk_set_khz = -1; - struct dc *core_dc = clk_mgr->base.ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - /* First clear response register */ - //dm_write_reg(ctx, mmMP1_SMN_C2PMSG_91, 0); REG_WRITE(MP1_SMN_C2PMSG_91, 0); /* Set the parameter register for the SMU message, unit is Mhz */ - //dm_write_reg(ctx, mmMP1_SMN_C2PMSG_83, requested_dispclk_khz / 1000); - REG_WRITE(MP1_SMN_C2PMSG_83, requested_dispclk_khz / 1000); + REG_WRITE(MP1_SMN_C2PMSG_83, param); /* Trigger the message transaction by writing the message ID */ - //dm_write_reg(ctx, mmMP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDispclkFreq); - REG_WRITE(MP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDispclkFreq); + REG_WRITE(MP1_SMN_C2PMSG_67, msg_id); REG_WAIT(MP1_SMN_C2PMSG_91, CONTENT, 1, 10, 200000); /* Actual dispclk set is returned in the parameter register */ - actual_dispclk_set_khz = REG_READ(MP1_SMN_C2PMSG_83) * 1000; + return REG_READ(MP1_SMN_C2PMSG_83); +} + +int rv1_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz) +{ + int actual_dispclk_set_mhz = -1; + struct dc *core_dc = clk_mgr->base.ctx->dc; + struct dmcu *dmcu = core_dc->res_pool->dmcu; + + /* Unit of SMU msg parameter is Mhz */ + actual_dispclk_set_mhz = rv1_vbios_smu_send_msg_with_param( + clk_mgr, + VBIOSSMC_MSG_SetDispclkFreq, + requested_dispclk_khz / 1000); + + /* Actual dispclk set is returned in the parameter register */ + actual_dispclk_set_mhz = REG_READ(MP1_SMN_C2PMSG_83) * 1000; if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { - if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_khz) + if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_mhz) dmcu->funcs->set_psr_wait_loop(dmcu, - actual_dispclk_set_khz / 1000 / 7); + actual_dispclk_set_mhz / 7); } } - return actual_dispclk_set_khz; + return actual_dispclk_set_mhz * 1000; } int rv1_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) { - int actual_dprefclk_set_khz = -1; + int actual_dprefclk_set_mhz = -1; - REG_WRITE(MP1_SMN_C2PMSG_91, 0); + actual_dprefclk_set_mhz = rv1_vbios_smu_send_msg_with_param( + clk_mgr, + VBIOSSMC_MSG_SetDprefclkFreq, + clk_mgr->base.dprefclk_khz / 1000); - /* Set the parameter register for the SMU message */ - REG_WRITE(MP1_SMN_C2PMSG_83, clk_mgr->base.dprefclk_khz / 1000); + /* TODO: add code for programing DP DTO, currently this is down by command table */ - /* Trigger the message transaction by writing the message ID */ - REG_WRITE(MP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDprefclkFreq); - - /* Wait for SMU response */ - REG_WAIT(MP1_SMN_C2PMSG_91, CONTENT, 1, 10, 200000); - - actual_dprefclk_set_khz = REG_READ(MP1_SMN_C2PMSG_83) * 1000; - - return actual_dprefclk_set_khz; + return actual_dprefclk_set_mhz * 1000; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index ca3e40053978..5814cacbe1be 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -101,30 +101,7 @@ static uint32_t dentist_get_did_from_divider(int divider) return divider_id; } -static int get_active_display_cnt( - struct dc *dc, - struct dc_state *context) -{ - int i, display_count; - - display_count = 0; - for (i = 0; i < context->stream_count; i++) { - const struct dc_stream_state *stream = context->streams[i]; - - /* - * Only notify active stream or virtual stream. - * Need to notify virtual stream to work around - * headless case. HPD does not fire when system is in - * S0i2. - */ - if (!stream->dpms_off || stream->signal == SIGNAL_TYPE_VIRTUAL) - display_count++; - } - - return display_count; -} - -static void update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, +void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context) { int i; @@ -143,7 +120,7 @@ static void update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, } } -static void update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr) +void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr) { int dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->dentist_vco_freq_khz / clk_mgr->base.clks.dppclk_khz; @@ -177,7 +154,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, bool dpp_clock_lowered = false; struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu; - display_count = get_active_display_cnt(dc, context); + display_count = clk_mgr_helper_get_active_display_cnt(dc, context); if (dc->res_pool->pp_smu) pp_smu = &dc->res_pool->pp_smu->nv_funcs; @@ -246,15 +223,21 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, if (dpp_clock_lowered) { // if clock is being lowered, increase DTO before lowering refclk - update_clocks_update_dpp_dto(clk_mgr, context); - update_clocks_update_dentist(clk_mgr); + dcn20_update_clocks_update_dpp_dto(clk_mgr, context); + dcn20_update_clocks_update_dentist(clk_mgr); } else { // if clock is being raised, increase refclk before lowering DTO if (update_dppclk || update_dispclk) - update_clocks_update_dentist(clk_mgr); + dcn20_update_clocks_update_dentist(clk_mgr); if (update_dppclk) - update_clocks_update_dpp_dto(clk_mgr, context); + dcn20_update_clocks_update_dpp_dto(clk_mgr, context); + } + if (update_dispclk && + dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { + /*update dmcu for wait_loop count*/ + dmcu->funcs->set_psr_wait_loop(dmcu, + clk_mgr_base->clks.dispclk_khz / 1000 / 7); } } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h index a3479f96eb9b..a44afc0625c5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h @@ -33,6 +33,8 @@ void dcn2_update_clocks(struct clk_mgr *dccg, void dcn2_update_clocks_fpga(struct clk_mgr *clk_mgr, struct dc_state *context, bool safe_to_lower); +void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, + struct dc_state *context); void dcn2_init_clocks(struct clk_mgr *clk_mgr);