disp: msm: sde: avoid irq enable/disable during modeset
Avoid irq enable/disable during modeset and trigger frame as posted start frame. This saves mode_set time and also avoids unbalanced vblank_irq in this usecase. Change-Id: I06958da5e52bc2aca0ddc60d2783615f80a839a4 Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org> Signed-off-by: Tatenda Chipeperekwa <tatendac@codeaurora.org>
This commit is contained in:

committed by
Tatenda Chipeperekwa

parent
75037208b6
commit
bd234c1885
@@ -100,13 +100,12 @@
|
|||||||
* @SDE_ENC_RC_EVENT_PRE_MODESET:
|
* @SDE_ENC_RC_EVENT_PRE_MODESET:
|
||||||
* This event happens at NORMAL priority from a work item.
|
* This event happens at NORMAL priority from a work item.
|
||||||
* Event signals that there is a seamless mode switch is in prgoress. A
|
* Event signals that there is a seamless mode switch is in prgoress. A
|
||||||
* client needs to turn of only irq - leave clocks ON to reduce the mode
|
* client needs to leave clocks ON to reduce the mode switch latency.
|
||||||
* switch latency.
|
|
||||||
* @SDE_ENC_RC_EVENT_POST_MODESET:
|
* @SDE_ENC_RC_EVENT_POST_MODESET:
|
||||||
* This event happens at NORMAL priority from a work item.
|
* This event happens at NORMAL priority from a work item.
|
||||||
* Event signals that seamless mode switch is complete and resources are
|
* Event signals that seamless mode switch is complete and resources are
|
||||||
* acquired. Clients wants to turn on the irq again and update the rsc
|
* acquired. Clients wants to update the rsc with new vtotal and update
|
||||||
* with new vtotal.
|
* pm_qos vote.
|
||||||
* @SDE_ENC_RC_EVENT_ENTER_IDLE:
|
* @SDE_ENC_RC_EVENT_ENTER_IDLE:
|
||||||
* This event happens at NORMAL priority from a work item.
|
* This event happens at NORMAL priority from a work item.
|
||||||
* Event signals that there were no frame updates for
|
* Event signals that there were no frame updates for
|
||||||
@@ -1898,19 +1897,6 @@ static int _sde_encoder_rc_pre_modeset(struct drm_encoder *drm_enc,
|
|||||||
sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
|
sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
|
|
||||||
if (ret && ret != -EWOULDBLOCK) {
|
|
||||||
SDE_ERROR_ENC(sde_enc,
|
|
||||||
"wait for commit done returned %d\n",
|
|
||||||
ret);
|
|
||||||
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
|
|
||||||
ret, SDE_EVTLOG_ERROR);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
sde_encoder_irq_control(drm_enc, false);
|
|
||||||
|
|
||||||
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
|
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
|
||||||
SDE_ENC_RC_STATE_MODESET, SDE_EVTLOG_FUNC_CASE5);
|
SDE_ENC_RC_STATE_MODESET, SDE_EVTLOG_FUNC_CASE5);
|
||||||
|
|
||||||
@@ -1945,8 +1931,6 @@ static int _sde_encoder_rc_post_modeset(struct drm_encoder *drm_enc,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
sde_encoder_irq_control(drm_enc, true);
|
|
||||||
|
|
||||||
_sde_encoder_update_rsc_client(drm_enc, true);
|
_sde_encoder_update_rsc_client(drm_enc, true);
|
||||||
|
|
||||||
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
|
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
|
||||||
@@ -2396,6 +2380,11 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (drm_enc->crtc->state->active_changed ||
|
||||||
|
!(msm_is_mode_seamless_dms(msm_mode) ||
|
||||||
|
(msm_is_mode_seamless_dyn_clk(msm_mode) &&
|
||||||
|
sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)))) {
|
||||||
|
|
||||||
/* reserve dynamic resources now, indicating non test-only */
|
/* reserve dynamic resources now, indicating non test-only */
|
||||||
ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state,
|
ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state,
|
||||||
conn->state, false);
|
conn->state, false);
|
||||||
@@ -2404,6 +2393,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
|||||||
"failed to reserve hw resources, %d\n", ret);
|
"failed to reserve hw resources, %d\n", ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* assign the reserved HW blocks to this encoder */
|
/* assign the reserved HW blocks to this encoder */
|
||||||
_sde_encoder_virt_populate_hw_res(drm_enc);
|
_sde_encoder_virt_populate_hw_res(drm_enc);
|
||||||
|
@@ -276,7 +276,6 @@ struct sde_encoder_irq {
|
|||||||
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
|
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
|
||||||
* @enable_state: Enable state tracking
|
* @enable_state: Enable state tracking
|
||||||
* @vblank_refcount: Reference count of vblank request
|
* @vblank_refcount: Reference count of vblank request
|
||||||
* @vblank_cached_refcount: Reference count of vblank cached request
|
|
||||||
* @wbirq_refcount: Reference count of wb irq request
|
* @wbirq_refcount: Reference count of wb irq request
|
||||||
* @vsync_cnt: Vsync count for the physical encoder
|
* @vsync_cnt: Vsync count for the physical encoder
|
||||||
* @last_vsync_timestamp: store last vsync timestamp
|
* @last_vsync_timestamp: store last vsync timestamp
|
||||||
@@ -327,7 +326,6 @@ struct sde_encoder_phys {
|
|||||||
enum sde_enc_enable_state enable_state;
|
enum sde_enc_enable_state enable_state;
|
||||||
struct mutex *vblank_ctl_lock;
|
struct mutex *vblank_ctl_lock;
|
||||||
atomic_t vblank_refcount;
|
atomic_t vblank_refcount;
|
||||||
atomic_t vblank_cached_refcount;
|
|
||||||
atomic_t wbirq_refcount;
|
atomic_t wbirq_refcount;
|
||||||
atomic_t vsync_cnt;
|
atomic_t vsync_cnt;
|
||||||
ktime_t last_vsync_timestamp;
|
ktime_t last_vsync_timestamp;
|
||||||
|
@@ -330,8 +330,6 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
|
|||||||
{
|
{
|
||||||
struct sde_encoder_irq *irq;
|
struct sde_encoder_irq *irq;
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
int ret = 0;
|
|
||||||
u32 vblank_refcount;
|
|
||||||
|
|
||||||
if (!phys_enc->sde_kms || !phys_enc->hw_pp || !phys_enc->hw_ctl) {
|
if (!phys_enc->sde_kms || !phys_enc->hw_pp || !phys_enc->hw_ctl) {
|
||||||
SDE_ERROR("invalid args %d %d %d\n", !phys_enc->sde_kms,
|
SDE_ERROR("invalid args %d %d %d\n", !phys_enc->sde_kms,
|
||||||
@@ -346,39 +344,13 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
|
|||||||
|
|
||||||
sde_kms = phys_enc->sde_kms;
|
sde_kms = phys_enc->sde_kms;
|
||||||
|
|
||||||
mutex_lock(phys_enc->vblank_ctl_lock);
|
|
||||||
vblank_refcount = atomic_read(&phys_enc->vblank_refcount);
|
|
||||||
if (vblank_refcount) {
|
|
||||||
ret = sde_encoder_helper_unregister_irq(phys_enc,
|
|
||||||
INTR_IDX_RDPTR);
|
|
||||||
if (ret)
|
|
||||||
SDE_ERROR(
|
|
||||||
"control vblank irq registration error %d\n",
|
|
||||||
ret);
|
|
||||||
if (vblank_refcount > 1)
|
|
||||||
SDE_ERROR(
|
|
||||||
"vblank_refcount mismatch detected, try to reset %d\n",
|
|
||||||
atomic_read(&phys_enc->vblank_refcount));
|
|
||||||
else
|
|
||||||
atomic_set(&phys_enc->vblank_cached_refcount, 1);
|
|
||||||
|
|
||||||
SDE_EVT32(DRMID(phys_enc->parent),
|
|
||||||
phys_enc->hw_pp->idx - PINGPONG_0, vblank_refcount,
|
|
||||||
atomic_read(&phys_enc->vblank_cached_refcount));
|
|
||||||
}
|
|
||||||
atomic_set(&phys_enc->vblank_refcount, 0);
|
|
||||||
mutex_unlock(phys_enc->vblank_ctl_lock);
|
|
||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_CTL_START];
|
irq = &phys_enc->irq[INTR_IDX_CTL_START];
|
||||||
irq->hw_idx = phys_enc->hw_ctl->idx;
|
irq->hw_idx = phys_enc->hw_ctl->idx;
|
||||||
irq->irq_idx = -EINVAL;
|
|
||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_PINGPONG];
|
irq = &phys_enc->irq[INTR_IDX_PINGPONG];
|
||||||
irq->hw_idx = phys_enc->hw_pp->idx;
|
irq->hw_idx = phys_enc->hw_pp->idx;
|
||||||
irq->irq_idx = -EINVAL;
|
|
||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_RDPTR];
|
irq = &phys_enc->irq[INTR_IDX_RDPTR];
|
||||||
irq->irq_idx = -EINVAL;
|
|
||||||
if (phys_enc->has_intf_te)
|
if (phys_enc->has_intf_te)
|
||||||
irq->hw_idx = phys_enc->hw_intf->idx;
|
irq->hw_idx = phys_enc->hw_intf->idx;
|
||||||
else
|
else
|
||||||
@@ -386,17 +358,14 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
|
|||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
|
irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
|
||||||
irq->hw_idx = phys_enc->intf_idx;
|
irq->hw_idx = phys_enc->intf_idx;
|
||||||
irq->irq_idx = -EINVAL;
|
|
||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_AUTOREFRESH_DONE];
|
irq = &phys_enc->irq[INTR_IDX_AUTOREFRESH_DONE];
|
||||||
irq->irq_idx = -EINVAL;
|
|
||||||
if (phys_enc->has_intf_te)
|
if (phys_enc->has_intf_te)
|
||||||
irq->hw_idx = phys_enc->hw_intf->idx;
|
irq->hw_idx = phys_enc->hw_intf->idx;
|
||||||
else
|
else
|
||||||
irq->hw_idx = phys_enc->hw_pp->idx;
|
irq->hw_idx = phys_enc->hw_pp->idx;
|
||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_WRPTR];
|
irq = &phys_enc->irq[INTR_IDX_WRPTR];
|
||||||
irq->irq_idx = -EINVAL;
|
|
||||||
if (phys_enc->has_intf_te)
|
if (phys_enc->has_intf_te)
|
||||||
irq->hw_idx = phys_enc->hw_intf->idx;
|
irq->hw_idx = phys_enc->hw_intf->idx;
|
||||||
else
|
else
|
||||||
@@ -821,7 +790,7 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
|
|||||||
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;
|
||||||
u32 refcount, cached_refcount;
|
u32 refcount;
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
|
|
||||||
if (!phys_enc || !phys_enc->hw_pp) {
|
if (!phys_enc || !phys_enc->hw_pp) {
|
||||||
@@ -836,18 +805,12 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
|
|||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
refcount = atomic_read(&phys_enc->vblank_refcount);
|
refcount = atomic_read(&phys_enc->vblank_refcount);
|
||||||
cached_refcount = atomic_read(&phys_enc->vblank_cached_refcount);
|
|
||||||
|
|
||||||
/* protect against negative */
|
/* protect against negative */
|
||||||
if (!enable && refcount == 0) {
|
if (!enable && refcount == 0) {
|
||||||
if (cached_refcount == 1) {
|
|
||||||
atomic_set(&phys_enc->vblank_cached_refcount, 0);
|
|
||||||
goto end;
|
|
||||||
} else {
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
|
SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
|
||||||
__builtin_return_address(0), enable, refcount);
|
__builtin_return_address(0), enable, refcount);
|
||||||
@@ -866,11 +829,6 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
|
|||||||
atomic_inc_return(&phys_enc->vblank_refcount);
|
atomic_inc_return(&phys_enc->vblank_refcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable && cached_refcount) {
|
|
||||||
atomic_inc(&phys_enc->vblank_refcount);
|
|
||||||
atomic_set(&phys_enc->vblank_cached_refcount, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
mutex_unlock(phys_enc->vblank_ctl_lock);
|
mutex_unlock(phys_enc->vblank_ctl_lock);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -2108,7 +2066,6 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
|
|||||||
irq->cb.func = sde_encoder_phys_cmd_wr_ptr_irq;
|
irq->cb.func = sde_encoder_phys_cmd_wr_ptr_irq;
|
||||||
|
|
||||||
atomic_set(&phys_enc->vblank_refcount, 0);
|
atomic_set(&phys_enc->vblank_refcount, 0);
|
||||||
atomic_set(&phys_enc->vblank_cached_refcount, 0);
|
|
||||||
atomic_set(&phys_enc->pending_kickoff_cnt, 0);
|
atomic_set(&phys_enc->pending_kickoff_cnt, 0);
|
||||||
atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
|
atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
|
||||||
atomic_set(&cmd_enc->pending_vblank_cnt, 0);
|
atomic_set(&cmd_enc->pending_vblank_cnt, 0);
|
||||||
|
Reference in New Issue
Block a user