drm/amd/display: Add some functions for Panel Replay
[WHY] Prepare for enabling the Panel Replay feature [HOW] - Add some Panel Replay setting functions in DC - Add the Panel Replay resource in dcn35_resource.c - Add debug masks for Panel Replay Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> Reviewed-by: Leo Li <sunpeng.li@amd.com> Signed-off-by: Tom Chung <chiahsuan.chung@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
d6398866a6
commit
e379787cbc
13 changed files with 235 additions and 6 deletions
|
@ -4770,6 +4770,38 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* enable/disable eDP Replay without specify stream for eDP */
|
||||
bool dc_set_replay_allow_active(struct dc *dc, bool active)
|
||||
{
|
||||
int i;
|
||||
bool allow_active;
|
||||
|
||||
for (i = 0; i < dc->current_state->stream_count; i++) {
|
||||
struct dc_link *link;
|
||||
struct dc_stream_state *stream = dc->current_state->streams[i];
|
||||
|
||||
link = stream->link;
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
if (link->replay_settings.replay_feature_enabled) {
|
||||
if (active && !link->replay_settings.replay_allow_active) {
|
||||
allow_active = true;
|
||||
if (!dc_link_set_replay_allow_active(link, &allow_active,
|
||||
false, false, NULL))
|
||||
return false;
|
||||
} else if (!active && link->replay_settings.replay_allow_active) {
|
||||
allow_active = false;
|
||||
if (!dc_link_set_replay_allow_active(link, &allow_active,
|
||||
true, false, NULL))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dc_allow_idle_optimizations(struct dc *dc, bool allow)
|
||||
{
|
||||
if (dc->debug.disable_idle_power_optimizations)
|
||||
|
@ -5315,6 +5347,8 @@ bool dc_abm_save_restore(
|
|||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *edp_links[MAX_NUM_EDP];
|
||||
|
||||
if (link->replay_settings.replay_feature_enabled)
|
||||
return false;
|
||||
|
||||
/*find primary pipe associated with stream*/
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
|
|
|
@ -467,6 +467,13 @@ bool dc_link_setup_psr(struct dc_link *link,
|
|||
return link->dc->link_srv->edp_setup_psr(link, stream, psr_config, psr_context);
|
||||
}
|
||||
|
||||
bool dc_link_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
|
||||
bool wait, bool force_static, const unsigned int *power_opts)
|
||||
{
|
||||
return link->dc->link_srv->edp_set_replay_allow_active(link, allow_active, wait,
|
||||
force_static, power_opts);
|
||||
}
|
||||
|
||||
bool dc_link_get_replay_state(const struct dc_link *link, uint64_t *state)
|
||||
{
|
||||
return link->dc->link_srv->edp_get_replay_state(link, state);
|
||||
|
|
|
@ -463,6 +463,12 @@ enum dml_hostvm_override_opts {
|
|||
DML_HOSTVM_OVERRIDE_TRUE = 0x2,
|
||||
};
|
||||
|
||||
enum dc_replay_power_opts {
|
||||
replay_power_opt_invalid = 0x0,
|
||||
replay_power_opt_smu_opt_static_screen = 0x1,
|
||||
replay_power_opt_z10_static_screen = 0x10,
|
||||
};
|
||||
|
||||
enum dcc_option {
|
||||
DCC_ENABLE = 0,
|
||||
DCC_DISABLE = 1,
|
||||
|
@ -2077,6 +2083,20 @@ bool dc_link_setup_psr(struct dc_link *dc_link,
|
|||
const struct dc_stream_state *stream, struct psr_config *psr_config,
|
||||
struct psr_context *psr_context);
|
||||
|
||||
/*
|
||||
* Communicate with DMUB to allow or disallow Panel Replay on the specified link:
|
||||
*
|
||||
* @link: pointer to the dc_link struct instance
|
||||
* @enable: enable(active) or disable(inactive) replay
|
||||
* @wait: state transition need to wait the active set completed.
|
||||
* @force_static: force disable(inactive) the replay
|
||||
* @power_opts: set power optimazation parameters to DMUB.
|
||||
*
|
||||
* return: allow Replay active will return true, else will return false.
|
||||
*/
|
||||
bool dc_link_set_replay_allow_active(struct dc_link *dc_link, const bool *enable,
|
||||
bool wait, bool force_static, const unsigned int *power_opts);
|
||||
|
||||
bool dc_link_get_replay_state(const struct dc_link *dc_link, uint64_t *state);
|
||||
|
||||
/* On eDP links this function call will stall until T12 has elapsed.
|
||||
|
@ -2321,6 +2341,9 @@ void dc_hardware_release(struct dc *dc);
|
|||
void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc);
|
||||
|
||||
bool dc_set_psr_allow_active(struct dc *dc, bool enable);
|
||||
|
||||
bool dc_set_replay_allow_active(struct dc *dc, bool active);
|
||||
|
||||
void dc_z10_restore(const struct dc *dc);
|
||||
void dc_z10_save_init(struct dc *dc);
|
||||
|
||||
|
|
|
@ -258,13 +258,97 @@ static void dmub_replay_residency(struct dmub_replay *dmub, uint8_t panel_inst,
|
|||
*residency = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set REPLAY power optimization flags and coasting vtotal.
|
||||
*/
|
||||
static void dmub_replay_set_power_opt_and_coasting_vtotal(struct dmub_replay *dmub,
|
||||
unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *dc = dmub->ctx;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.header.type = DMUB_CMD__REPLAY;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.header.sub_type =
|
||||
DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal);
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.power_opt = power_opt;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.panel_inst = panel_inst;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_coasting_vtotal_data.coasting_vtotal = coasting_vtotal;
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* send Replay general cmd to DMUB.
|
||||
*/
|
||||
static void dmub_replay_send_cmd(struct dmub_replay *dmub,
|
||||
enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *ctx = NULL;
|
||||
|
||||
if (dmub == NULL || cmd_element == NULL)
|
||||
return;
|
||||
|
||||
ctx = dmub->ctx;
|
||||
if (ctx != NULL) {
|
||||
|
||||
if (msg != Replay_Msg_Not_Support) {
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
//Header
|
||||
cmd.replay_set_timing_sync.header.type = DMUB_CMD__REPLAY;
|
||||
} else
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
|
||||
switch (msg) {
|
||||
case Replay_Set_Timing_Sync_Supported:
|
||||
//Header
|
||||
cmd.replay_set_timing_sync.header.sub_type =
|
||||
DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED;
|
||||
cmd.replay_set_timing_sync.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_timing_sync);
|
||||
//Cmd Body
|
||||
cmd.replay_set_timing_sync.replay_set_timing_sync_data.panel_inst =
|
||||
cmd_element->sync_data.panel_inst;
|
||||
cmd.replay_set_timing_sync.replay_set_timing_sync_data.timing_sync_supported =
|
||||
cmd_element->sync_data.timing_sync_supported;
|
||||
break;
|
||||
case Replay_Set_Residency_Frameupdate_Timer:
|
||||
//Header
|
||||
cmd.replay_set_frameupdate_timer.header.sub_type =
|
||||
DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER;
|
||||
cmd.replay_set_frameupdate_timer.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_frameupdate_timer);
|
||||
//Cmd Body
|
||||
cmd.replay_set_frameupdate_timer.data.panel_inst =
|
||||
cmd_element->panel_inst;
|
||||
cmd.replay_set_frameupdate_timer.data.enable =
|
||||
cmd_element->timer_data.enable;
|
||||
cmd.replay_set_frameupdate_timer.data.frameupdate_count =
|
||||
cmd_element->timer_data.frameupdate_count;
|
||||
break;
|
||||
case Replay_Msg_Not_Support:
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static const struct dmub_replay_funcs replay_funcs = {
|
||||
.replay_copy_settings = dmub_replay_copy_settings,
|
||||
.replay_enable = dmub_replay_enable,
|
||||
.replay_get_state = dmub_replay_get_state,
|
||||
.replay_set_power_opt = dmub_replay_set_power_opt,
|
||||
.replay_set_coasting_vtotal = dmub_replay_set_coasting_vtotal,
|
||||
.replay_residency = dmub_replay_residency,
|
||||
.replay_copy_settings = dmub_replay_copy_settings,
|
||||
.replay_enable = dmub_replay_enable,
|
||||
.replay_get_state = dmub_replay_get_state,
|
||||
.replay_set_power_opt = dmub_replay_set_power_opt,
|
||||
.replay_set_coasting_vtotal = dmub_replay_set_coasting_vtotal,
|
||||
.replay_residency = dmub_replay_residency,
|
||||
.replay_set_power_opt_and_coasting_vtotal = dmub_replay_set_power_opt_and_coasting_vtotal,
|
||||
.replay_send_cmd = dmub_replay_send_cmd,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -51,6 +51,8 @@ struct dmub_replay_funcs {
|
|||
uint8_t panel_inst);
|
||||
void (*replay_residency)(struct dmub_replay *dmub,
|
||||
uint8_t panel_inst, uint32_t *residency, const bool is_start, const bool is_alpm);
|
||||
void (*replay_set_power_opt_and_coasting_vtotal)(struct dmub_replay *dmub,
|
||||
unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal);
|
||||
};
|
||||
|
||||
struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
|
||||
|
|
|
@ -289,6 +289,8 @@ struct link_service {
|
|||
bool (*edp_replay_residency)(const struct dc_link *link,
|
||||
unsigned int *residency, const bool is_start,
|
||||
const bool is_alpm);
|
||||
bool (*edp_set_replay_power_opt_and_coasting_vtotal)(struct dc_link *link,
|
||||
const unsigned int *power_opts, uint16_t coasting_vtotal);
|
||||
|
||||
bool (*edp_wait_for_t12)(struct dc_link *link);
|
||||
bool (*edp_is_ilr_optimization_required)(struct dc_link *link,
|
||||
|
|
|
@ -216,6 +216,7 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s
|
|||
link_srv->edp_send_replay_cmd = edp_send_replay_cmd;
|
||||
link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal;
|
||||
link_srv->edp_replay_residency = edp_replay_residency;
|
||||
link_srv->edp_set_replay_power_opt_and_coasting_vtotal = edp_set_replay_power_opt_and_coasting_vtotal;
|
||||
|
||||
link_srv->edp_wait_for_t12 = edp_wait_for_t12;
|
||||
link_srv->edp_is_ilr_optimization_required =
|
||||
|
|
|
@ -1068,6 +1068,33 @@ bool edp_replay_residency(const struct dc_link *link,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
|
||||
const unsigned int *power_opts, uint16_t coasting_vtotal)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
struct dmub_replay *replay = dc->res_pool->replay;
|
||||
unsigned int panel_inst;
|
||||
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
/* Only both power and coasting vtotal changed, this func could return true */
|
||||
if (power_opts && link->replay_settings.replay_power_opt_active != *power_opts &&
|
||||
coasting_vtotal && link->replay_settings.coasting_vtotal != coasting_vtotal) {
|
||||
if (link->replay_settings.replay_feature_enabled &&
|
||||
replay->funcs->replay_set_power_opt_and_coasting_vtotal) {
|
||||
replay->funcs->replay_set_power_opt_and_coasting_vtotal(replay,
|
||||
*power_opts, panel_inst, coasting_vtotal);
|
||||
link->replay_settings.replay_power_opt_active = *power_opts;
|
||||
link->replay_settings.coasting_vtotal = coasting_vtotal;
|
||||
} else
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct abm *get_abm_from_stream_res(const struct dc_link *link)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -63,6 +63,8 @@ bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal);
|
|||
bool edp_replay_residency(const struct dc_link *link,
|
||||
unsigned int *residency, const bool is_start, const bool is_alpm);
|
||||
bool edp_get_replay_state(const struct dc_link *link, uint64_t *state);
|
||||
bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
|
||||
const unsigned int *power_opts, uint16_t coasting_vtotal);
|
||||
bool edp_wait_for_t12(struct dc_link *link);
|
||||
bool edp_is_ilr_optimization_required(struct dc_link *link,
|
||||
struct dc_crtc_timing *crtc_timing);
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#include "reg_helper.h"
|
||||
#include "dce/dmub_abm.h"
|
||||
#include "dce/dmub_psr.h"
|
||||
#include "dce/dmub_replay.h"
|
||||
#include "dce/dce_aux.h"
|
||||
#include "dce/dce_i2c.h"
|
||||
#include "dml/dcn31/display_mode_vba_31.h" /*temp*/
|
||||
|
@ -788,6 +789,7 @@ static const struct dc_panel_config panel_config_defaults = {
|
|||
.psr = {
|
||||
.disable_psr = false,
|
||||
.disallow_psrsu = false,
|
||||
.disallow_replay = false,
|
||||
},
|
||||
.ilr = {
|
||||
.optimize_edp_link_rate = true,
|
||||
|
@ -1546,6 +1548,9 @@ static void dcn35_resource_destruct(struct dcn35_resource_pool *pool)
|
|||
if (pool->base.psr != NULL)
|
||||
dmub_psr_destroy(&pool->base.psr);
|
||||
|
||||
if (pool->base.replay != NULL)
|
||||
dmub_replay_destroy(&pool->base.replay);
|
||||
|
||||
if (pool->base.pg_cntl != NULL)
|
||||
dcn_pg_cntl_destroy(&pool->base.pg_cntl);
|
||||
|
||||
|
@ -2030,6 +2035,14 @@ static bool dcn35_resource_construct(
|
|||
goto create_fail;
|
||||
}
|
||||
|
||||
/* Replay */
|
||||
pool->base.replay = dmub_replay_create(ctx);
|
||||
if (pool->base.replay == NULL) {
|
||||
dm_error("DC: failed to create replay obj!\n");
|
||||
BREAK_TO_DEBUGGER();
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* ABM */
|
||||
for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
|
||||
pool->base.multiple_abms[i] = dmub_abm_create(ctx,
|
||||
|
|
|
@ -973,6 +973,34 @@ bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
|
|||
return true;
|
||||
}
|
||||
|
||||
void set_replay_coasting_vtotal(struct dc_link *link,
|
||||
enum replay_coasting_vtotal_type type,
|
||||
uint16_t vtotal)
|
||||
{
|
||||
link->replay_settings.coasting_vtotal_table[type] = vtotal;
|
||||
}
|
||||
|
||||
void calculate_replay_link_off_frame_count(struct dc_link *link,
|
||||
uint16_t vtotal, uint16_t htotal)
|
||||
{
|
||||
uint8_t max_link_off_frame_count = 0;
|
||||
uint16_t max_deviation_line = 0, pixel_deviation_per_line = 0;
|
||||
|
||||
max_deviation_line = link->dpcd_caps.pr_info.max_deviation_line;
|
||||
pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line;
|
||||
|
||||
if (htotal != 0 && vtotal != 0)
|
||||
max_link_off_frame_count = htotal * max_deviation_line / (pixel_deviation_per_line * vtotal);
|
||||
else
|
||||
ASSERT(0);
|
||||
|
||||
link->replay_settings.link_off_frame_count_level =
|
||||
max_link_off_frame_count >= PR_LINK_OFF_FRAME_COUNT_BEST ? PR_LINK_OFF_FRAME_COUNT_BEST :
|
||||
max_link_off_frame_count >= PR_LINK_OFF_FRAME_COUNT_GOOD ? PR_LINK_OFF_FRAME_COUNT_GOOD :
|
||||
PR_LINK_OFF_FRAME_COUNT_FAIL;
|
||||
|
||||
}
|
||||
|
||||
bool fill_custom_backlight_caps(unsigned int config_no, struct dm_acpi_atif_backlight_caps *caps)
|
||||
{
|
||||
unsigned int data_points_size;
|
||||
|
|
|
@ -54,6 +54,11 @@ bool dmub_init_abm_config(struct resource_pool *res_pool,
|
|||
unsigned int inst);
|
||||
|
||||
void init_replay_config(struct dc_link *link, struct replay_config *pr_config);
|
||||
void set_replay_coasting_vtotal(struct dc_link *link,
|
||||
enum replay_coasting_vtotal_type type,
|
||||
uint16_t vtotal);
|
||||
void calculate_replay_link_off_frame_count(struct dc_link *link,
|
||||
uint16_t vtotal, uint16_t htotal);
|
||||
|
||||
bool is_psr_su_specific_panel(struct dc_link *link);
|
||||
void mod_power_calc_psr_configs(struct psr_config *psr_config,
|
||||
|
|
|
@ -257,6 +257,7 @@ enum DC_DEBUG_MASK {
|
|||
DC_ENABLE_DPIA_TRACE = 0x80,
|
||||
DC_ENABLE_DML2 = 0x100,
|
||||
DC_DISABLE_PSR_SU = 0x200,
|
||||
DC_DISABLE_REPLAY = 0x400,
|
||||
};
|
||||
|
||||
enum amd_dpm_forced_level;
|
||||
|
|
Loading…
Add table
Reference in a new issue