if (link) {
link->dc->link_srv->edp_setup_replay(link, stream);
- link->dc->link_srv->edp_set_coasting_vtotal(link, stream->timing.v_total);
+ link->dc->link_srv->edp_set_coasting_vtotal(link, stream->timing.v_total, 0);
DRM_DEBUG_DRIVER("Enabling replay...\n");
link->dc->link_srv->edp_set_replay_allow_active(link, &replay_active, wait, false, NULL);
return true;
uint32_t coasting_vtotal_table[PR_COASTING_TYPE_NUM];
/* Defer Update Coasting vtotal table */
uint32_t defer_update_coasting_vtotal_table[PR_COASTING_TYPE_NUM];
+ /* Skip frame number table */
+ uint32_t frame_skip_number_table[PR_COASTING_TYPE_NUM];
+ /* Defer skip frame number table */
+ uint32_t defer_frame_skip_number_table[PR_COASTING_TYPE_NUM];
/* Maximum link off frame count */
uint32_t link_off_frame_count;
/* Replay pseudo vtotal for low refresh rate*/
uint16_t last_pseudo_vtotal;
/* Replay desync error */
uint32_t replay_desync_error_fail_count;
+ /* The frame skip number dal send to DMUB */
+ uint16_t frame_skip_number;
};
/* To split out "global" and "per-panel" config settings.
*/
static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
uint32_t coasting_vtotal,
- uint8_t panel_inst)
+ uint8_t panel_inst,
+ uint16_t frame_skip_number)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
pCmd->header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data);
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16;
+ pCmd->replay_set_coasting_vtotal_data.frame_skip_number = frame_skip_number;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
* 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, uint32_t coasting_vtotal)
+ unsigned int power_opt, uint8_t panel_inst, uint32_t coasting_vtotal, uint16_t frame_skip_number)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
pCmd->replay_set_power_opt_data.panel_inst = panel_inst;
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16;
+ pCmd->replay_set_coasting_vtotal_data.frame_skip_number = frame_skip_number;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
void (*replay_send_cmd)(struct dmub_replay *dmub,
enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element);
void (*replay_set_coasting_vtotal)(struct dmub_replay *dmub, uint32_t coasting_vtotal,
- uint8_t panel_inst);
+ uint8_t panel_inst, uint16_t frame_skip_number);
void (*replay_residency)(struct dmub_replay *dmub,
uint8_t panel_inst, uint32_t *residency, const bool is_start, const enum pr_residency_mode mode);
void (*replay_set_power_opt_and_coasting_vtotal)(struct dmub_replay *dmub,
- unsigned int power_opt, uint8_t panel_inst, uint32_t coasting_vtotal);
+ unsigned int power_opt, uint8_t panel_inst, uint32_t coasting_vtotal,
+ uint16_t frame_skip_number);
};
struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
enum replay_FW_Message_type msg,
union dmub_replay_cmd_set *cmd_data);
bool (*edp_set_coasting_vtotal)(
- struct dc_link *link, uint32_t coasting_vtotal);
+ struct dc_link *link, uint32_t coasting_vtotal, uint16_t frame_skip_number);
bool (*edp_replay_residency)(const struct dc_link *link,
unsigned int *residency, const bool is_start,
const enum pr_residency_mode mode);
bool (*edp_set_replay_power_opt_and_coasting_vtotal)(struct dc_link *link,
- const unsigned int *power_opts, uint32_t coasting_vtotal);
+ const unsigned int *power_opts, uint32_t coasting_vtotal, uint16_t frame_skip_number);
bool (*edp_wait_for_t12)(struct dc_link *link);
bool (*edp_is_ilr_optimization_required)(struct dc_link *link,
return true;
}
-bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal)
+bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal, uint16_t frame_skip_number)
{
struct dc *dc = link->ctx->dc;
struct dmub_replay *replay = dc->res_pool->replay;
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
return false;
- if (coasting_vtotal && link->replay_settings.coasting_vtotal != coasting_vtotal) {
- replay->funcs->replay_set_coasting_vtotal(replay, coasting_vtotal, panel_inst);
+ if (coasting_vtotal && (link->replay_settings.coasting_vtotal != coasting_vtotal ||
+ link->replay_settings.frame_skip_number != frame_skip_number)) {
+ replay->funcs->replay_set_coasting_vtotal(replay, coasting_vtotal, panel_inst, frame_skip_number);
link->replay_settings.coasting_vtotal = coasting_vtotal;
+ link->replay_settings.frame_skip_number = frame_skip_number;
}
return true;
}
bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
- const unsigned int *power_opts, uint32_t coasting_vtotal)
+ const unsigned int *power_opts, uint32_t coasting_vtotal, uint16_t frame_skip_number)
{
struct dc *dc = link->ctx->dc;
struct dmub_replay *replay = dc->res_pool->replay;
/* 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) {
+ (coasting_vtotal &&
+ (link->replay_settings.coasting_vtotal != coasting_vtotal ||
+ link->replay_settings.frame_skip_number != frame_skip_number))) {
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);
+ *power_opts, panel_inst, coasting_vtotal, frame_skip_number);
link->replay_settings.replay_power_opt_active = *power_opts;
link->replay_settings.coasting_vtotal = coasting_vtotal;
+ link->replay_settings.frame_skip_number = frame_skip_number;
} else
return false;
} else
bool edp_send_replay_cmd(struct dc_link *link,
enum replay_FW_Message_type msg,
union dmub_replay_cmd_set *cmd_data);
-bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal);
+bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal, uint16_t frame_skip_number);
bool edp_replay_residency(const struct dc_link *link,
unsigned int *residency, const bool is_start, const enum pr_residency_mode mode);
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, uint32_t coasting_vtotal);
+ const unsigned int *power_opts, uint32_t coasting_vtotal, uint16_t frame_skip_number);
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);
return true;
}
+void set_replay_frame_skip_number(struct dc_link *link,
+ enum replay_coasting_vtotal_type type,
+ uint32_t coasting_vtotal_refresh_rate_mhz,
+ uint32_t flicker_free_refresh_rate_mhz,
+ bool is_defer)
+{
+ uint32_t *frame_skip_number_array = NULL;
+ uint32_t frame_skip_number = 0;
+
+ if (link == NULL || flicker_free_refresh_rate_mhz == 0 || coasting_vtotal_refresh_rate_mhz == 0)
+ return;
+
+ if (is_defer)
+ frame_skip_number_array = link->replay_settings.defer_frame_skip_number_table;
+ else
+ frame_skip_number_array = link->replay_settings.frame_skip_number_table;
+
+ if (frame_skip_number_array == NULL)
+ return;
+
+ frame_skip_number = coasting_vtotal_refresh_rate_mhz / flicker_free_refresh_rate_mhz;
+
+ if (frame_skip_number >= 1)
+ frame_skip_number_array[type] = frame_skip_number - 1;
+ else
+ frame_skip_number_array[type] = 0;
+}
+
void set_replay_defer_update_coasting_vtotal(struct dc_link *link,
enum replay_coasting_vtotal_type type,
uint32_t vtotal)
{
link->replay_settings.coasting_vtotal_table[type] =
link->replay_settings.defer_update_coasting_vtotal_table[type];
+ link->replay_settings.frame_skip_number_table[type] =
+ link->replay_settings.defer_frame_skip_number_table[type];
}
void set_replay_coasting_vtotal(struct dc_link *link,
void set_replay_defer_update_coasting_vtotal(struct dc_link *link,
enum replay_coasting_vtotal_type type,
uint32_t vtotal);
+void set_replay_frame_skip_number(struct dc_link *link,
+ enum replay_coasting_vtotal_type type,
+ uint32_t coasting_vtotal_refresh_rate_Mhz,
+ uint32_t flicker_free_refresh_rate_Mhz,
+ bool is_defer);
void update_replay_coasting_vtotal_from_defer(struct dc_link *link,
enum replay_coasting_vtotal_type type);
void set_replay_low_rr_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal);