diff options
| author | Ingrid Gallardo <ingridg@codeaurora.org> | 2016-12-06 12:26:04 -0800 |
|---|---|---|
| committer | Ingrid Gallardo <ingridg@codeaurora.org> | 2017-01-12 17:35:30 -0800 |
| commit | 61ea22ebdc5e1db1060a2a3affc4a75517d9f835 (patch) | |
| tree | 55fe58228c8a5ed0ae4653074f957211fc61b7fe /drivers/video | |
| parent | 5142c18bae30439decd1c139999b54197e2aae91 (diff) | |
msm: mdss: fix autorefresh disable sequence
Sequence to disable autorefresh when handoff is
done to the kernel is missing to wait for the
previous transaction to finish. This change
makes sure any previous on-going transaction
finishes before disabling autorefresh.
Change-Id: I547aea5cc82989d03963b2153e2561092fd7b36c
Signed-off-by: Ingrid Gallardo <ingridg@codeaurora.org>
Diffstat (limited to 'drivers/video')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 165 |
1 files changed, 87 insertions, 78 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 4852fc73f040..3adba504cc3b 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -335,6 +335,87 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer, return 0; } +/** + * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh + * @arg: void pointer to the controller context. + * + * This function is the pp_done interrupt callback while disabling + * autorefresh. This function does not modify the kickoff count (koff_cnt). + */ +static void mdss_mdp_cmd_autorefresh_pp_done(void *arg) +{ + struct mdss_mdp_ctl *ctl = arg; + struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX]; + + if (!ctx) { + pr_err("%s: invalid ctx\n", __func__); + return; + } + + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num); + mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num, NULL, NULL); + + MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num); + complete_all(&ctx->autorefresh_ppdone); + + pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__, + ctl->num, ctl->intf_num, ctx->current_pp_num, + atomic_read(&ctx->koff_cnt)); +} + +static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl) +{ + int rc; + u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP; + char __iomem *pp_base = ctl->mixer_left->pingpong_base; + struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX]; + + line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT); + + MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h); + pr_debug("ctl:%d line_out:%d\n", ctl->num, line_out); + + if (!ctx) { + pr_err("%s: invalid ctx\n", __func__); + return; + } + + if (line_out < ctl->mixer_left->roi.h) { + reinit_completion(&ctx->autorefresh_ppdone); + + /* enable ping pong done */ + mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num, + mdss_mdp_cmd_autorefresh_pp_done, ctl); + mdss_mdp_irq_enable(intr_type, ctx->current_pp_num); + + /* wait for ping pong done */ + rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone, + KOFF_TIMEOUT); + if (rc <= 0) { + val = mdss_mdp_pingpong_read(pp_base, + MDSS_MDP_REG_PP_LINE_COUNT); + if (val == ctl->mixer_left->roi.h) { + mdss_mdp_irq_clear(ctl->mdata, + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num); + mdss_mdp_irq_disable_nosync(intr_type, + ctx->current_pp_num); + mdss_mdp_set_intr_callback(intr_type, + ctx->current_pp_num, NULL, NULL); + } else { + pr_err("timedout waiting for ctl%d autorefresh pp done\n", + ctl->num); + MDSS_XLOG(0xbad3); + MDSS_XLOG_TOUT_HANDLER("mdp", + "vbif", "dbg_bus", "vbif_dbg_bus", + "panic"); + } + } + } +} + static bool __disable_rd_ptr_from_te(char __iomem *pingpong_base) { u32 cfg; @@ -408,7 +489,10 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx, rd_ptr_disabled = __disable_rd_ptr_from_te(mixer->pingpong_base); - /* 2. disable autorefresh */ + /* 2. wait for previous transfer to finish */ + mdss_mdp_cmd_wait4_autorefresh_pp(ctl); + + /* 3. disable autorefresh */ if (is_pingpong_split(ctl->mfd)) __disable_autorefresh( mdata->slave_pingpong_base); @@ -425,7 +509,7 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx, __disable_autorefresh(mixer->pingpong_base); pr_debug("%s: disabling auto refresh\n", __func__); - /* 2. re-enable rd pointer from te (if was enabled) */ + /* 4. re-enable rd pointer from te (if was enabled) */ if (rd_ptr_disabled) __enable_rd_ptr_from_te(mixer->pingpong_base); @@ -1473,36 +1557,6 @@ static int mdss_mdp_cmd_update_lineptr(struct mdss_mdp_ctl *ctl, bool enable) return 0; } -/** - * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh - * @arg: void pointer to the controller context. - * - * This function is the pp_done interrupt callback while disabling - * autorefresh. This function does not modify the kickoff count (koff_cnt). - */ -static void mdss_mdp_cmd_autorefresh_pp_done(void *arg) -{ - struct mdss_mdp_ctl *ctl = arg; - struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX]; - - if (!ctx) { - pr_err("%s: invalid ctx\n", __func__); - return; - } - - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, - ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, - ctx->current_pp_num, NULL, NULL); - - MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num); - complete_all(&ctx->autorefresh_ppdone); - - pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__, - ctl->num, ctl->intf_num, ctx->current_pp_num, - atomic_read(&ctx->koff_cnt)); -} - static void pingpong_done_work(struct work_struct *work) { u32 status; @@ -2484,51 +2538,6 @@ static void mdss_mdp_cmd_post_programming(struct mdss_mdp_ctl *mctl) } } -static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl) -{ - int rc; - u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP; - char __iomem *pp_base = ctl->mixer_left->pingpong_base; - struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX]; - - line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT); - - MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h); - - if (line_out < ctl->mixer_left->roi.h) { - reinit_completion(&ctx->autorefresh_ppdone); - - /* enable ping pong done */ - mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num, - mdss_mdp_cmd_autorefresh_pp_done, ctl); - mdss_mdp_irq_enable(intr_type, ctx->current_pp_num); - - /* wait for ping pong done */ - rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone, - KOFF_TIMEOUT); - if (rc <= 0) { - val = mdss_mdp_pingpong_read(pp_base, - MDSS_MDP_REG_PP_LINE_COUNT); - if (val == ctl->mixer_left->roi.h) { - mdss_mdp_irq_clear(ctl->mdata, - MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, - ctx->current_pp_num); - mdss_mdp_irq_disable_nosync(intr_type, - ctx->current_pp_num); - mdss_mdp_set_intr_callback(intr_type, - ctx->current_pp_num, NULL, NULL); - } else { - pr_err("timedout waiting for ctl%d autorefresh pp done\n", - ctl->num); - MDSS_XLOG(0xbad3); - MDSS_XLOG_TOUT_HANDLER("mdp", - "vbif", "dbg_bus", "vbif_dbg_bus", - "panic"); - } - } - } -} - static void mdss_mdp_cmd_autorefresh_done(void *arg) { struct mdss_mdp_ctl *ctl = arg; |
