All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Masney <masneyb@onstation.org>
To: jeffrey.l.hugo@gmail.com, robdclark@gmail.com
Cc: freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org,
	sean@poorly.run
Subject: [PATCH RFC v2] drm/msm/mdp5: enable autorefresh
Date: Sun, 29 Dec 2019 21:00:52 -0500	[thread overview]
Message-ID: <20191230020053.26016-1-masneyb@onstation.org> (raw)

Since the introduction of commit 2d99ced787e3 ("drm/msm: async commit
support"), command-mode panels began throwing the following errors:

    msm fd900000.mdss: pp done time out, lm=0

Let's fix this by enabling the autorefresh feature that's available in
the MDP starting at version 1.0. This will cause the MDP to
automatically send a frame to the panel every time the panel invokes the
TE signal, which will trigger the PP_DONE IRQ. This requires only
sending a single START signal for command-mode panels.

This gives us a counter for command-mode panels that we can use to
implement async commit support for the MDP5 in a follow up patch.

Signed-off-by: Brian Masney <masneyb@onstation.org>
Suggested-by: Jeffrey Hugo <jeffrey.l.hugo@gmail.com>
Fixes: 2d99ced787e3 ("drm/msm: async commit support")
---
Changes since v1:
- Send a single start command to kick off the pipeline.

The reason I marked this patch as a RFC is that the display during some
small percentage of boots will stop updating after a minute or so, and
the ping pong IRQs stop. Most of the time it works with no issues and I
haven't been able to find a way to reproduce the issue. I tried
suspending the phone by toggling /sys/power/state since I thought that
the issue could potentially be related to power management.

 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 17 ++++++++++++-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c  | 31 ++++++++++++++++++++---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h  |  3 +--
 3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index 05cc04f729d6..39dd144295b3 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -436,6 +436,8 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
 		spin_unlock_irqrestore(&mdp5_kms->dev->event_lock, flags);
 	}
 
+	mdp5_ctl_disable(mdp5_cstate->ctl, &mdp5_cstate->pipeline);
+
 	mdp5_crtc->enabled = false;
 }
 
@@ -456,6 +458,7 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 	struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+	struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
 	struct mdp5_kms *mdp5_kms = get_kms(crtc);
 	struct device *dev = &mdp5_kms->pdev->dev;
 
@@ -493,9 +496,21 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
 
-	if (mdp5_cstate->cmd_mode)
+	if (mdp5_cstate->cmd_mode) {
 		mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->pp_done);
 
+		/*
+		 * Enable autorefresh so we get regular ping/pong IRQs.
+		 * - Bit 31 is the enable bit
+		 * - Bits 0-15 represent the frame count, specifically how many
+		 *   TE events before the MDP sends a frame.
+		 */
+		mdp5_write(mdp5_kms,
+			   REG_MDP5_PP_AUTOREFRESH_CONFIG(pipeline->mixer->pp),
+			   BIT(31) | BIT(0));
+		crtc_flush_all(crtc);
+	}
+
 	mdp5_crtc->enabled = true;
 }
 
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
index 030279d7b64b..965757d4f356 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
@@ -50,6 +50,13 @@ struct mdp5_ctl {
 	bool flush_pending;
 
 	struct mdp5_ctl *pair; /* Paired CTL to be flushed together */
+
+	/*
+	 * The command mode panels are ran with autorefresh enabled. Only a
+	 * single START command can be sent so keep track on a per ping pong
+	 * basis.
+	 */
+	bool start_sent_by_pp[4];
 };
 
 struct mdp5_ctl_manager {
@@ -191,7 +198,8 @@ static bool start_signal_needed(struct mdp5_ctl *ctl,
 	case INTF_WB:
 		return true;
 	case INTF_DSI:
-		return intf->mode == MDP5_INTF_DSI_MODE_COMMAND;
+		return intf->mode == MDP5_INTF_DSI_MODE_COMMAND &&
+			!ctl->start_sent_by_pp[pipeline->mixer->pp];
 	default:
 		return false;
 	}
@@ -204,13 +212,17 @@ static bool start_signal_needed(struct mdp5_ctl *ctl,
  * executed in order to kick off operation and activate all layers.
  * e.g.: DSI command mode, Writeback
  */
-static void send_start_signal(struct mdp5_ctl *ctl)
+static void send_start_signal(struct mdp5_ctl *ctl,
+			      struct mdp5_pipeline *pipeline)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&ctl->hw_lock, flags);
 	ctl_write(ctl, REG_MDP5_CTL_START(ctl->id), 1);
 	spin_unlock_irqrestore(&ctl->hw_lock, flags);
+
+	if (pipeline->intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
+		ctl->start_sent_by_pp[pipeline->mixer->pp] = true;
 }
 
 /**
@@ -234,7 +246,7 @@ int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl,
 	DBG("intf_%d: %s", intf->num, enabled ? "on" : "off");
 
 	if (start_signal_needed(ctl, pipeline)) {
-		send_start_signal(ctl);
+		send_start_signal(ctl, pipeline);
 	}
 
 	return 0;
@@ -562,7 +574,7 @@ u32 mdp5_ctl_commit(struct mdp5_ctl *ctl,
 	}
 
 	if (start_signal_needed(ctl, pipeline)) {
-		send_start_signal(ctl);
+		send_start_signal(ctl, pipeline);
 	}
 
 	return curr_ctl_flush_mask;
@@ -753,3 +765,14 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
 
 	return ERR_PTR(ret);
 }
+
+void mdp5_ctl_disable(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline)
+{
+	int i;
+
+	if (pipeline->intf->mode != MDP5_INTF_DSI_MODE_COMMAND)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(ctl->start_sent_by_pp); i++)
+		ctl->start_sent_by_pp[i] = false;
+}
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
index c2af68aa77ae..f9bbf1295669 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
@@ -72,7 +72,6 @@ u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
 u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
 		    u32 flush_mask, bool start);
 u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);
-
-
+void mdp5_ctl_disable(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline);
 
 #endif /* __MDP5_CTL_H__ */
-- 
2.21.0


WARNING: multiple messages have this Message-ID (diff)
From: Brian Masney <masneyb@onstation.org>
To: jeffrey.l.hugo@gmail.com, robdclark@gmail.com
Cc: sean@poorly.run, linux-arm-msm@vger.kernel.org,
	freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org
Subject: [PATCH RFC v2] drm/msm/mdp5: enable autorefresh
Date: Sun, 29 Dec 2019 21:00:52 -0500	[thread overview]
Message-ID: <20191230020053.26016-1-masneyb@onstation.org> (raw)

Since the introduction of commit 2d99ced787e3 ("drm/msm: async commit
support"), command-mode panels began throwing the following errors:

    msm fd900000.mdss: pp done time out, lm=0

Let's fix this by enabling the autorefresh feature that's available in
the MDP starting at version 1.0. This will cause the MDP to
automatically send a frame to the panel every time the panel invokes the
TE signal, which will trigger the PP_DONE IRQ. This requires only
sending a single START signal for command-mode panels.

This gives us a counter for command-mode panels that we can use to
implement async commit support for the MDP5 in a follow up patch.

Signed-off-by: Brian Masney <masneyb@onstation.org>
Suggested-by: Jeffrey Hugo <jeffrey.l.hugo@gmail.com>
Fixes: 2d99ced787e3 ("drm/msm: async commit support")
---
Changes since v1:
- Send a single start command to kick off the pipeline.

The reason I marked this patch as a RFC is that the display during some
small percentage of boots will stop updating after a minute or so, and
the ping pong IRQs stop. Most of the time it works with no issues and I
haven't been able to find a way to reproduce the issue. I tried
suspending the phone by toggling /sys/power/state since I thought that
the issue could potentially be related to power management.

 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 17 ++++++++++++-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c  | 31 ++++++++++++++++++++---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h  |  3 +--
 3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index 05cc04f729d6..39dd144295b3 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -436,6 +436,8 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
 		spin_unlock_irqrestore(&mdp5_kms->dev->event_lock, flags);
 	}
 
+	mdp5_ctl_disable(mdp5_cstate->ctl, &mdp5_cstate->pipeline);
+
 	mdp5_crtc->enabled = false;
 }
 
@@ -456,6 +458,7 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 	struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+	struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
 	struct mdp5_kms *mdp5_kms = get_kms(crtc);
 	struct device *dev = &mdp5_kms->pdev->dev;
 
@@ -493,9 +496,21 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
 
-	if (mdp5_cstate->cmd_mode)
+	if (mdp5_cstate->cmd_mode) {
 		mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->pp_done);
 
+		/*
+		 * Enable autorefresh so we get regular ping/pong IRQs.
+		 * - Bit 31 is the enable bit
+		 * - Bits 0-15 represent the frame count, specifically how many
+		 *   TE events before the MDP sends a frame.
+		 */
+		mdp5_write(mdp5_kms,
+			   REG_MDP5_PP_AUTOREFRESH_CONFIG(pipeline->mixer->pp),
+			   BIT(31) | BIT(0));
+		crtc_flush_all(crtc);
+	}
+
 	mdp5_crtc->enabled = true;
 }
 
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
index 030279d7b64b..965757d4f356 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
@@ -50,6 +50,13 @@ struct mdp5_ctl {
 	bool flush_pending;
 
 	struct mdp5_ctl *pair; /* Paired CTL to be flushed together */
+
+	/*
+	 * The command mode panels are ran with autorefresh enabled. Only a
+	 * single START command can be sent so keep track on a per ping pong
+	 * basis.
+	 */
+	bool start_sent_by_pp[4];
 };
 
 struct mdp5_ctl_manager {
@@ -191,7 +198,8 @@ static bool start_signal_needed(struct mdp5_ctl *ctl,
 	case INTF_WB:
 		return true;
 	case INTF_DSI:
-		return intf->mode == MDP5_INTF_DSI_MODE_COMMAND;
+		return intf->mode == MDP5_INTF_DSI_MODE_COMMAND &&
+			!ctl->start_sent_by_pp[pipeline->mixer->pp];
 	default:
 		return false;
 	}
@@ -204,13 +212,17 @@ static bool start_signal_needed(struct mdp5_ctl *ctl,
  * executed in order to kick off operation and activate all layers.
  * e.g.: DSI command mode, Writeback
  */
-static void send_start_signal(struct mdp5_ctl *ctl)
+static void send_start_signal(struct mdp5_ctl *ctl,
+			      struct mdp5_pipeline *pipeline)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&ctl->hw_lock, flags);
 	ctl_write(ctl, REG_MDP5_CTL_START(ctl->id), 1);
 	spin_unlock_irqrestore(&ctl->hw_lock, flags);
+
+	if (pipeline->intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
+		ctl->start_sent_by_pp[pipeline->mixer->pp] = true;
 }
 
 /**
@@ -234,7 +246,7 @@ int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl,
 	DBG("intf_%d: %s", intf->num, enabled ? "on" : "off");
 
 	if (start_signal_needed(ctl, pipeline)) {
-		send_start_signal(ctl);
+		send_start_signal(ctl, pipeline);
 	}
 
 	return 0;
@@ -562,7 +574,7 @@ u32 mdp5_ctl_commit(struct mdp5_ctl *ctl,
 	}
 
 	if (start_signal_needed(ctl, pipeline)) {
-		send_start_signal(ctl);
+		send_start_signal(ctl, pipeline);
 	}
 
 	return curr_ctl_flush_mask;
@@ -753,3 +765,14 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
 
 	return ERR_PTR(ret);
 }
+
+void mdp5_ctl_disable(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline)
+{
+	int i;
+
+	if (pipeline->intf->mode != MDP5_INTF_DSI_MODE_COMMAND)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(ctl->start_sent_by_pp); i++)
+		ctl->start_sent_by_pp[i] = false;
+}
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
index c2af68aa77ae..f9bbf1295669 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
@@ -72,7 +72,6 @@ u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
 u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
 		    u32 flush_mask, bool start);
 u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);
-
-
+void mdp5_ctl_disable(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline);
 
 #endif /* __MDP5_CTL_H__ */
-- 
2.21.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

             reply	other threads:[~2019-12-30  2:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-30  2:00 Brian Masney [this message]
2019-12-30  2:00 ` [PATCH RFC v2] drm/msm/mdp5: enable autorefresh Brian Masney
2019-12-30  2:00 ` Brian Masney
2019-12-30  2:00   ` Brian Masney
2020-01-01  3:50   ` Brian Masney
2020-01-01  3:50     ` Brian Masney
2020-01-18 21:02     ` Brian Masney
2020-01-18 21:02       ` Brian Masney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191230020053.26016-1-masneyb@onstation.org \
    --to=masneyb@onstation.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=freedreno@lists.freedesktop.org \
    --cc=jeffrey.l.hugo@gmail.com \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robdclark@gmail.com \
    --cc=sean@poorly.run \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.