mdss: display: last pp_done do the notification at partial update
For left+right partial update case, both pingpong_done are enabled. The last pingpong_done will do the notification to signal timeline to release buffer. Change-Id: Ibfe115d3c9cc05cdc7f9171b9421e85f1cc56157 Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
This commit is contained in:
parent
3a28acf18f
commit
20a1446910
2 changed files with 121 additions and 44 deletions
|
@ -2771,16 +2771,13 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
!mdss_mdp_ctl_perf_get_transaction_status(sctl);
|
||||
}
|
||||
|
||||
if (sctl && !ctl->valid_roi && sctl->valid_roi) {
|
||||
/*
|
||||
* Seperate kickoff on DSI1 is needed only when we have
|
||||
* ONLY right half updating on a dual DSI panel
|
||||
*/
|
||||
mdss_mdp_ctl_perf_set_transaction_status(ctl,
|
||||
PERF_SW_COMMIT_STATE, PERF_STATUS_BUSY);
|
||||
|
||||
if (sctl && sctl->roi.w && sctl->roi.h) {
|
||||
/* left + right*/
|
||||
mdss_mdp_ctl_perf_set_transaction_status(sctl,
|
||||
PERF_SW_COMMIT_STATE, PERF_STATUS_BUSY);
|
||||
} else {
|
||||
mdss_mdp_ctl_perf_set_transaction_status(ctl,
|
||||
PERF_SW_COMMIT_STATE, PERF_STATUS_BUSY);
|
||||
PERF_SW_COMMIT_STATE, PERF_STATUS_BUSY);
|
||||
}
|
||||
|
||||
if (is_bw_released || ctl->force_screen_state ||
|
||||
|
|
|
@ -36,7 +36,7 @@ struct mdss_mdp_cmd_ctx {
|
|||
struct completion stop_comp;
|
||||
struct list_head vsync_handlers;
|
||||
int panel_on;
|
||||
int koff_cnt;
|
||||
atomic_t koff_cnt;
|
||||
int clk_enabled;
|
||||
int vsync_enabled;
|
||||
int rdptr_enabled;
|
||||
|
@ -48,10 +48,13 @@ struct mdss_mdp_cmd_ctx {
|
|||
atomic_t pp_done_cnt;
|
||||
struct mdss_panel_recovery recovery;
|
||||
bool ulps;
|
||||
struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */
|
||||
};
|
||||
|
||||
struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
|
||||
|
||||
static int mdss_mdp_cmd_do_notifier(struct mdss_mdp_cmd_ctx *ctx);
|
||||
|
||||
static inline u32 mdss_mdp_cmd_line_count(struct mdss_mdp_ctl *ctl)
|
||||
{
|
||||
struct mdss_mdp_mixer *mixer;
|
||||
|
@ -188,7 +191,7 @@ static inline void mdss_mdp_cmd_clk_on(struct mdss_mdp_cmd_ctx *ctx)
|
|||
return;
|
||||
|
||||
mutex_lock(&ctx->clk_mtx);
|
||||
MDSS_XLOG(ctx->pp_num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctx->pp_num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
if (!ctx->clk_enabled) {
|
||||
ctx->clk_enabled = 1;
|
||||
|
@ -225,7 +228,7 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx)
|
|||
int set_clk_off = 0;
|
||||
|
||||
mutex_lock(&ctx->clk_mtx);
|
||||
MDSS_XLOG(ctx->pp_num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctx->pp_num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
spin_lock_irqsave(&ctx->clk_lock, flags);
|
||||
if (!ctx->rdptr_enabled)
|
||||
|
@ -258,7 +261,7 @@ static void mdss_mdp_cmd_readptr_done(void *arg)
|
|||
|
||||
vsync_time = ktime_get();
|
||||
ctl->vsync_cnt++;
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
|
||||
spin_lock(&ctx->clk_lock);
|
||||
|
@ -272,7 +275,7 @@ static void mdss_mdp_cmd_readptr_done(void *arg)
|
|||
ctx->rdptr_enabled--;
|
||||
|
||||
/* keep clk on during kickoff */
|
||||
if (ctx->rdptr_enabled == 0 && ctx->koff_cnt)
|
||||
if (ctx->rdptr_enabled == 0 && atomic_read(&ctx->koff_cnt))
|
||||
ctx->rdptr_enabled++;
|
||||
}
|
||||
|
||||
|
@ -299,11 +302,11 @@ static void mdss_mdp_cmd_underflow_recovery(void *data)
|
|||
if (!ctx->ctl)
|
||||
return;
|
||||
spin_lock_irqsave(&ctx->clk_lock, flags);
|
||||
if (ctx->koff_cnt) {
|
||||
if (atomic_read(&ctx->koff_cnt)) {
|
||||
mdss_mdp_ctl_reset(ctx->ctl);
|
||||
pr_debug("%s: intf_num=%d\n", __func__,
|
||||
ctx->ctl->intf_num);
|
||||
ctx->koff_cnt--;
|
||||
atomic_dec(&ctx->koff_cnt);
|
||||
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
|
||||
ctx->pp_num);
|
||||
complete_all(&ctx->pp_comp);
|
||||
|
@ -334,24 +337,27 @@ static void mdss_mdp_cmd_pingpong_done(void *arg)
|
|||
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
|
||||
|
||||
complete_all(&ctx->pp_comp);
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
|
||||
if (ctx->koff_cnt) {
|
||||
atomic_inc(&ctx->pp_done_cnt);
|
||||
schedule_work(&ctx->pp_done_work);
|
||||
ctx->koff_cnt--;
|
||||
if (ctx->koff_cnt) {
|
||||
if (atomic_read(&ctx->koff_cnt)) {
|
||||
if (atomic_dec_return(&ctx->koff_cnt)) {
|
||||
pr_err("%s: too many kickoffs=%d!\n", __func__,
|
||||
ctx->koff_cnt);
|
||||
ctx->koff_cnt = 0;
|
||||
atomic_read(&ctx->koff_cnt));
|
||||
atomic_set(&ctx->koff_cnt, 0);
|
||||
}
|
||||
if (mdss_mdp_cmd_do_notifier(ctx)) {
|
||||
atomic_inc(&ctx->pp_done_cnt);
|
||||
schedule_work(&ctx->pp_done_work);
|
||||
}
|
||||
} else
|
||||
pr_err("%s: should not have pingpong interrupt!\n", __func__);
|
||||
|
||||
trace_mdp_cmd_pingpong_done(ctl, ctx->pp_num, ctx->koff_cnt);
|
||||
trace_mdp_cmd_pingpong_done(ctl, ctx->pp_num,
|
||||
atomic_read(&ctx->koff_cnt));
|
||||
pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d kcnt=%d\n", __func__,
|
||||
ctl->num, ctl->intf_num, ctx->pp_num, ctx->koff_cnt);
|
||||
ctl->num, ctl->intf_num, ctx->pp_num,
|
||||
atomic_read(&ctx->koff_cnt));
|
||||
|
||||
spin_unlock(&ctx->clk_lock);
|
||||
}
|
||||
|
@ -424,7 +430,7 @@ static int mdss_mdp_cmd_add_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
if (sctl)
|
||||
|
@ -466,7 +472,7 @@ static int mdss_mdp_cmd_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled, 0x88888);
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
if (sctl)
|
||||
|
@ -522,14 +528,14 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
pdata = ctl->panel_data;
|
||||
|
||||
spin_lock_irqsave(&ctx->clk_lock, flags);
|
||||
if (ctx->koff_cnt > 0)
|
||||
if (atomic_read(&ctx->koff_cnt) > 0)
|
||||
need_wait = 1;
|
||||
spin_unlock_irqrestore(&ctx->clk_lock, flags);
|
||||
|
||||
ctl->roi_bkup.w = ctl->width;
|
||||
ctl->roi_bkup.h = ctl->height;
|
||||
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled, ctl->roi_bkup.w,
|
||||
ctl->roi_bkup.h);
|
||||
|
||||
|
@ -540,7 +546,8 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
rc = wait_for_completion_timeout(
|
||||
&ctx->pp_comp, KOFF_TIMEOUT);
|
||||
|
||||
trace_mdp_cmd_wait_pingpong(ctl->num, ctx->koff_cnt);
|
||||
trace_mdp_cmd_wait_pingpong(ctl->num,
|
||||
atomic_read(&ctx->koff_cnt));
|
||||
|
||||
if (rc <= 0) {
|
||||
WARN(1, "cmd kickoff timed out (%d) ctl=%d\n",
|
||||
|
@ -554,11 +561,48 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
}
|
||||
}
|
||||
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mdss_mdp_cmd_do_notifier(struct mdss_mdp_cmd_ctx *ctx)
|
||||
{
|
||||
struct mdss_mdp_cmd_ctx *sctx;
|
||||
|
||||
sctx = ctx->sync_ctx;
|
||||
if (!sctx || atomic_read(&sctx->koff_cnt) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mdss_mdp_cmd_set_sync_ctx(
|
||||
struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl)
|
||||
{
|
||||
struct mdss_mdp_cmd_ctx *ctx, *sctx;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *)ctl->priv_data;
|
||||
|
||||
if (!ctl->panel_data->panel_info.partial_update_enabled || !sctl) {
|
||||
/* not partial or right only at partial update */
|
||||
ctx->sync_ctx = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
sctx = (struct mdss_mdp_cmd_ctx *)sctl->priv_data;
|
||||
|
||||
if (!sctl->roi.w && !sctl->roi.h) {
|
||||
/* left only */
|
||||
ctx->sync_ctx = NULL;
|
||||
sctx->sync_ctx = NULL;
|
||||
} else {
|
||||
/* left + right */
|
||||
ctx->sync_ctx = sctx;
|
||||
sctx->sync_ctx = ctx;
|
||||
}
|
||||
}
|
||||
|
||||
static int mdss_mdp_cmd_set_partial_roi(struct mdss_mdp_ctl *ctl)
|
||||
{
|
||||
struct mdss_mdp_ctl *sctl = NULL;
|
||||
|
@ -599,9 +643,21 @@ static int mdss_mdp_cmd_set_stream_size(struct mdss_mdp_ctl *ctl)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are 3 partial update possibilities
|
||||
* left only ==> enable left pingpong_done
|
||||
* left + right ==> enable both pingpong_done
|
||||
* right only ==> enable right pingpong_done
|
||||
*
|
||||
* notification is triggered at pingpong_done which will
|
||||
* signal timeline to release source buffer
|
||||
*
|
||||
* for left+right case, pingpong_done is enabled for both and
|
||||
* only the last pingpong_done should trigger the notification
|
||||
*/
|
||||
int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
|
||||
{
|
||||
struct mdss_mdp_ctl *sctl;
|
||||
struct mdss_mdp_ctl *sctl = NULL;
|
||||
struct mdss_mdp_cmd_ctx *ctx, *sctx = NULL;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
@ -612,13 +668,25 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
if (sctl)
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
if (ctl->panel_data->panel_info.partial_update_enabled) {
|
||||
/* sctl will be null for right only */
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
}
|
||||
|
||||
if (sctl && (sctl->roi.w == 0 || sctl->roi.h == 0)) {
|
||||
/* left update only */
|
||||
sctl = NULL;
|
||||
}
|
||||
|
||||
mdss_mdp_ctl_perf_set_transaction_status(ctl,
|
||||
PERF_HW_MDP_STATE, PERF_STATUS_BUSY);
|
||||
|
||||
if (sctl) {
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
mdss_mdp_ctl_perf_set_transaction_status(sctl,
|
||||
PERF_HW_MDP_STATE, PERF_STATUS_BUSY);
|
||||
}
|
||||
|
||||
if (ctx->panel_on == 0) {
|
||||
rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_UNBLANK, NULL);
|
||||
WARN(rc, "intf %d unblank error (%d)\n", ctl->intf_num, rc);
|
||||
|
@ -635,9 +703,11 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
ctl->roi.h);
|
||||
|
||||
spin_lock_irqsave(&ctx->clk_lock, flags);
|
||||
ctx->koff_cnt++;
|
||||
atomic_inc(&ctx->koff_cnt);
|
||||
if (sctx)
|
||||
atomic_inc(&sctx->koff_cnt);
|
||||
spin_unlock_irqrestore(&ctx->clk_lock, flags);
|
||||
trace_mdp_cmd_kickoff(ctl->num, ctx->koff_cnt);
|
||||
trace_mdp_cmd_kickoff(ctl->num, atomic_read(&ctx->koff_cnt));
|
||||
|
||||
mdss_mdp_cmd_clk_on(ctx);
|
||||
|
||||
|
@ -650,17 +720,27 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
(void *)&ctx->recovery);
|
||||
mdss_mdp_cmd_set_stream_size(ctl);
|
||||
|
||||
mdss_mdp_cmd_set_sync_ctx(ctl, sctl);
|
||||
|
||||
INIT_COMPLETION(ctx->pp_comp);
|
||||
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
|
||||
if (sctx) {
|
||||
INIT_COMPLETION(sctx->pp_comp);
|
||||
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, sctx->pp_num);
|
||||
}
|
||||
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
|
||||
|
||||
mdss_mdp_ctl_perf_set_transaction_status(ctl,
|
||||
PERF_SW_COMMIT_STATE, PERF_STATUS_DONE);
|
||||
|
||||
mb();
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
if (sctl) {
|
||||
mdss_mdp_ctl_perf_set_transaction_status(sctl,
|
||||
PERF_SW_COMMIT_STATE, PERF_STATUS_DONE);
|
||||
}
|
||||
|
||||
mb();
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -682,7 +762,7 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
|
|||
|
||||
list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
|
||||
mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled, XLOG_FUNC_ENTRY);
|
||||
|
||||
spin_lock_irqsave(&ctx->clk_lock, flags);
|
||||
|
@ -748,7 +828,7 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
|
|||
ctl->add_vsync_handler = NULL;
|
||||
ctl->remove_vsync_handler = NULL;
|
||||
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled, XLOG_FUNC_EXIT);
|
||||
pr_debug("%s:-\n", __func__);
|
||||
|
||||
|
@ -804,7 +884,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl)
|
|||
|
||||
pr_debug("%s: ctx=%p num=%d mixer=%d\n", __func__,
|
||||
ctx, ctx->pp_num, mixer->num);
|
||||
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
|
||||
|
|
Loading…
Add table
Reference in a new issue