Skip to content

Commit

Permalink
drm/amd/display: Refactor clk_mgr functions
Browse files Browse the repository at this point in the history
[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 <Eric.Yang2@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Eric Yang authored and Alex Deucher committed Jun 22, 2019
1 parent 8712bda commit c69dd2d
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 82 deletions.
25 changes: 25 additions & 0 deletions drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 1 addition & 24 deletions drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

REG_WRITE(MP1_SMN_C2PMSG_91, 0);

/* Set the parameter register for the SMU message */
REG_WRITE(MP1_SMN_C2PMSG_83, clk_mgr->base.dprefclk_khz / 1000);
int actual_dprefclk_set_mhz = -1;

/* 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_mhz = rv1_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDprefclkFreq,
clk_mgr->base.dprefclk_khz / 1000);

actual_dprefclk_set_khz = REG_READ(MP1_SMN_C2PMSG_83) * 1000;
/* TODO: add code for programing DP DTO, currently this is down by command table */

return actual_dprefclk_set_khz;
return actual_dprefclk_set_mhz * 1000;
}
43 changes: 13 additions & 30 deletions drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit c69dd2d

Please sign in to comment.