summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorIngrid Gallardo <ingridg@codeaurora.org>2016-12-06 12:26:04 -0800
committerIngrid Gallardo <ingridg@codeaurora.org>2017-01-12 17:35:30 -0800
commit61ea22ebdc5e1db1060a2a3affc4a75517d9f835 (patch)
tree55fe58228c8a5ed0ae4653074f957211fc61b7fe /drivers/video
parent5142c18bae30439decd1c139999b54197e2aae91 (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.c165
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;