disp: msm: sde: wait for autorefresh_status to be idle in prepare kickoff
If cont splash is enabled, wait for autorefresh_status to be idle for 1 vsync in prepare kickoff. This patch also prevents entering to rsc_solver_mode if autorefresh_status is busy. Change-Id: Ic4458dcbe8e06ff6f338dd264eb9371365120dd1 Signed-off-by: Yojana Juadi <quic_yjuadi@quicinc.com>
This commit is contained in:
@@ -332,6 +332,16 @@ static bool _sde_encoder_is_autorefresh_enabled(
|
|||||||
CONNECTOR_PROP_AUTOREFRESH) ? true : false;
|
CONNECTOR_PROP_AUTOREFRESH) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _sde_encoder_is_autorefresh_status_busy(struct sde_encoder_virt *sde_enc)
|
||||||
|
{
|
||||||
|
if (!sde_enc->cur_master || !sde_enc->cur_master->hw_intf ||
|
||||||
|
!sde_enc->cur_master->hw_intf->ops.get_autorefresh_status)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return sde_enc->cur_master->hw_intf->ops.get_autorefresh_status(
|
||||||
|
sde_enc->cur_master->hw_intf);
|
||||||
|
}
|
||||||
|
|
||||||
static void sde_configure_qdss(struct sde_encoder_virt *sde_enc,
|
static void sde_configure_qdss(struct sde_encoder_virt *sde_enc,
|
||||||
struct sde_hw_qdss *hw_qdss,
|
struct sde_hw_qdss *hw_qdss,
|
||||||
struct sde_encoder_phys *phys, bool enable)
|
struct sde_encoder_phys *phys, bool enable)
|
||||||
@@ -1498,28 +1508,6 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _sde_encoder_wait_for_vsync_on_autorefresh_busy(struct sde_encoder_phys *phys_enc)
|
|
||||||
{
|
|
||||||
u32 autorefresh_status;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!phys_enc || !phys_enc->hw_intf || !phys_enc->hw_intf->ops.get_autorefresh_status) {
|
|
||||||
SDE_ERROR("invalid params\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status(phys_enc->hw_intf);
|
|
||||||
if (autorefresh_status) {
|
|
||||||
ret = sde_encoder_wait_for_event(phys_enc->parent, MSM_ENC_VBLANK);
|
|
||||||
if (ret) {
|
|
||||||
autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status(
|
|
||||||
phys_enc->hw_intf);
|
|
||||||
SDE_ERROR("wait for vblank timed out, autorefresh_status:%d\n",
|
|
||||||
autorefresh_status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int sde_encoder_helper_switch_vsync(struct drm_encoder *drm_enc,
|
int sde_encoder_helper_switch_vsync(struct drm_encoder *drm_enc,
|
||||||
bool watchdog_te)
|
bool watchdog_te)
|
||||||
{
|
{
|
||||||
@@ -1715,7 +1703,8 @@ static int _sde_encoder_update_rsc_client(
|
|||||||
qsync_mode = sde_connector_get_qsync_mode(
|
qsync_mode = sde_connector_get_qsync_mode(
|
||||||
sde_enc->cur_master->connector);
|
sde_enc->cur_master->connector);
|
||||||
sde_enc->autorefresh_solver_disable =
|
sde_enc->autorefresh_solver_disable =
|
||||||
_sde_encoder_is_autorefresh_enabled(sde_enc) ? true : false;
|
_sde_encoder_is_autorefresh_status_busy(sde_enc) ||
|
||||||
|
_sde_encoder_is_autorefresh_enabled(sde_enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* left primary encoder keep vote */
|
/* left primary encoder keep vote */
|
||||||
@@ -3359,6 +3348,28 @@ static void sde_encoder_wait_for_vsync_event_complete(struct sde_encoder_virt *s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _sde_encoder_helper_virt_disable(struct drm_encoder *drm_enc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
|
||||||
|
|
||||||
|
if (!sde_encoder_in_clone_mode(drm_enc)) {
|
||||||
|
/* disable autorefresh */
|
||||||
|
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
||||||
|
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
|
||||||
|
|
||||||
|
if (phys && phys->ops.disable_autorefresh &&
|
||||||
|
phys->ops.wait_for_vsync_on_autorefresh_busy) {
|
||||||
|
phys->ops.disable_autorefresh(phys);
|
||||||
|
phys->ops.wait_for_vsync_on_autorefresh_busy(phys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for idle */
|
||||||
|
sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
|
static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
|
||||||
{
|
{
|
||||||
struct sde_encoder_virt *sde_enc = NULL;
|
struct sde_encoder_virt *sde_enc = NULL;
|
||||||
@@ -3406,20 +3417,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
|
|||||||
|
|
||||||
SDE_EVT32(DRMID(drm_enc));
|
SDE_EVT32(DRMID(drm_enc));
|
||||||
|
|
||||||
if (!sde_encoder_in_clone_mode(drm_enc)) {
|
_sde_encoder_helper_virt_disable(drm_enc);
|
||||||
/* disable autorefresh */
|
|
||||||
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
|
||||||
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
|
|
||||||
|
|
||||||
if (phys && phys->ops.disable_autorefresh) {
|
|
||||||
phys->ops.disable_autorefresh(phys);
|
|
||||||
_sde_encoder_wait_for_vsync_on_autorefresh_busy(phys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wait for idle */
|
|
||||||
sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sde_encoder_input_handler_unregister(drm_enc);
|
_sde_encoder_input_handler_unregister(drm_enc);
|
||||||
|
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ struct sde_encoder_virt_ops {
|
|||||||
* count and underrun line count
|
* count and underrun line count
|
||||||
* @add_to_minidump: Add this phys_enc data to minidumps
|
* @add_to_minidump: Add this phys_enc data to minidumps
|
||||||
* @disable_autorefresh: Disable autorefresh
|
* @disable_autorefresh: Disable autorefresh
|
||||||
|
* @wait_for_vsync_on_autorefresh_busy: Wait for vsync if autorefresh status busy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct sde_encoder_phys_ops {
|
struct sde_encoder_phys_ops {
|
||||||
@@ -198,6 +199,7 @@ struct sde_encoder_phys_ops {
|
|||||||
u32 (*get_underrun_line_count)(struct sde_encoder_phys *phys);
|
u32 (*get_underrun_line_count)(struct sde_encoder_phys *phys);
|
||||||
void (*add_to_minidump)(struct sde_encoder_phys *phys);
|
void (*add_to_minidump)(struct sde_encoder_phys *phys);
|
||||||
void (*disable_autorefresh)(struct sde_encoder_phys *phys);
|
void (*disable_autorefresh)(struct sde_encoder_phys *phys);
|
||||||
|
void (*wait_for_vsync_on_autorefresh_busy)(struct sde_encoder_phys *phys_enc);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1436,11 +1436,34 @@ static void sde_encoder_phys_cmd_get_hw_resources(
|
|||||||
hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD;
|
hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _sde_encoder_phys_wait_for_vsync_on_autorefresh_busy(struct sde_encoder_phys *phys_enc)
|
||||||
|
{
|
||||||
|
u32 autorefresh_status;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!phys_enc || !phys_enc->hw_intf || !phys_enc->hw_intf->ops.get_autorefresh_status) {
|
||||||
|
SDE_ERROR("invalid params\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status(phys_enc->hw_intf);
|
||||||
|
if (autorefresh_status) {
|
||||||
|
ret = sde_encoder_wait_for_event(phys_enc->parent, MSM_ENC_VBLANK);
|
||||||
|
if (ret) {
|
||||||
|
autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status(
|
||||||
|
phys_enc->hw_intf);
|
||||||
|
SDE_ERROR("wait for vblank timed out, autorefresh_status:%d\n",
|
||||||
|
autorefresh_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int sde_encoder_phys_cmd_prepare_for_kickoff(
|
static int sde_encoder_phys_cmd_prepare_for_kickoff(
|
||||||
struct sde_encoder_phys *phys_enc,
|
struct sde_encoder_phys *phys_enc,
|
||||||
struct sde_encoder_kickoff_params *params)
|
struct sde_encoder_kickoff_params *params)
|
||||||
{
|
{
|
||||||
struct sde_hw_tear_check tc_cfg = {0};
|
struct sde_hw_tear_check tc_cfg = {0};
|
||||||
|
struct sde_encoder_virt *sde_enc;
|
||||||
struct sde_encoder_phys_cmd *cmd_enc =
|
struct sde_encoder_phys_cmd *cmd_enc =
|
||||||
to_sde_encoder_phys_cmd(phys_enc);
|
to_sde_encoder_phys_cmd(phys_enc);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -1453,10 +1476,11 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
|
|||||||
SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
|
SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
|
||||||
|
|
||||||
phys_enc->frame_trigger_mode = params->frame_trigger_mode;
|
phys_enc->frame_trigger_mode = params->frame_trigger_mode;
|
||||||
|
sde_enc = to_sde_encoder_virt(phys_enc->parent);
|
||||||
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
|
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
|
||||||
atomic_read(&phys_enc->pending_kickoff_cnt),
|
atomic_read(&phys_enc->pending_kickoff_cnt),
|
||||||
atomic_read(&cmd_enc->autorefresh.kickoff_cnt),
|
atomic_read(&cmd_enc->autorefresh.kickoff_cnt),
|
||||||
phys_enc->frame_trigger_mode);
|
phys_enc->frame_trigger_mode, phys_enc->cont_splash_enabled);
|
||||||
|
|
||||||
if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) {
|
if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) {
|
||||||
/*
|
/*
|
||||||
@@ -1473,6 +1497,9 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (phys_enc->cont_splash_enabled)
|
||||||
|
_sde_encoder_phys_wait_for_vsync_on_autorefresh_busy(phys_enc);
|
||||||
|
|
||||||
if (phys_enc->recovered) {
|
if (phys_enc->recovered) {
|
||||||
recovery_events = sde_encoder_recovery_events_enabled(
|
recovery_events = sde_encoder_recovery_events_enabled(
|
||||||
phys_enc->parent);
|
phys_enc->parent);
|
||||||
@@ -1965,6 +1992,7 @@ static void _sde_encoder_autorefresh_disable_seq2(
|
|||||||
tear_status.write_count);
|
tear_status.write_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _sde_encoder_phys_disable_autorefresh(struct sde_encoder_phys *phys_enc)
|
static void _sde_encoder_phys_disable_autorefresh(struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||||
@@ -2129,6 +2157,8 @@ static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops)
|
|||||||
ops->collect_misr = sde_encoder_helper_collect_misr;
|
ops->collect_misr = sde_encoder_helper_collect_misr;
|
||||||
ops->add_to_minidump = sde_encoder_phys_cmd_add_enc_to_minidump;
|
ops->add_to_minidump = sde_encoder_phys_cmd_add_enc_to_minidump;
|
||||||
ops->disable_autorefresh = _sde_encoder_phys_disable_autorefresh;
|
ops->disable_autorefresh = _sde_encoder_phys_disable_autorefresh;
|
||||||
|
ops->wait_for_vsync_on_autorefresh_busy =
|
||||||
|
_sde_encoder_phys_wait_for_vsync_on_autorefresh_busy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool sde_encoder_phys_cmd_intf_te_supported(
|
static inline bool sde_encoder_phys_cmd_intf_te_supported(
|
||||||
|
|||||||
Reference in New Issue
Block a user