All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] media: renesas: vsp1: Align VSPD startup to HW manual
@ 2023-02-16  9:42 Tomi Valkeinen
  0 siblings, 0 replies; only message in thread
From: Tomi Valkeinen @ 2023-02-16  9:42 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media, linux-renesas-soc; +Cc: Tomi Valkeinen

From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

The hardware manual states that after setting VI6_CMD0.STRCMD to 1, we
need to wait until VI6_DISP0_IRQ_STA.DST is set before proceeding. The
driver is missing this wait.

Add the wait with readl_poll_timeout, because:
1) The VI6_DISP0_IRQ_STA.DST bit is usually set more or less immediately
   after setting the VI6_CMD0.STRCMD (i.e. the first test passes).
2) While we have an interrupt handler, we never enable nor handle the
   VI6_DISP0_IRQ interrupts.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 .../media/platform/renesas/vsp1/vsp1_drm.c    | 19 ++++++++++++++++++-
 .../media/platform/renesas/vsp1/vsp1_pipe.c   |  7 ++++++-
 .../media/platform/renesas/vsp1/vsp1_pipe.h   |  2 +-
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drm.c b/drivers/media/platform/renesas/vsp1/vsp1_drm.c
index 5da1bc991750..767ebab65114 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_drm.c
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
 #include <linux/slab.h>
 
 #include <media/media-entity.h>
@@ -648,7 +649,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	struct vsp1_pipeline *pipe;
 	unsigned long flags;
 	unsigned int i;
+	bool started;
 	int ret;
+	u32 v;
 
 	if (pipe_index >= vsp1->info->lif_count)
 		return -EINVAL;
@@ -757,11 +760,25 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	if (ret < 0)
 		return ret;
 
+	/* Clear VI6_DISP_IRQ_STA_DST flag */
+	v = vsp1_read(vsp1, VI6_DISP_IRQ_STA(pipe->output->entity.index));
+	vsp1_write(vsp1, VI6_DISP_IRQ_STA(pipe->output->entity.index),
+		   ~v & VI6_DISP_IRQ_STA_DST);
+
 	/* Start the pipeline. */
 	spin_lock_irqsave(&pipe->irqlock, flags);
-	vsp1_pipeline_run(pipe);
+	started = vsp1_pipeline_run(pipe);
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 
+	if (started) {
+		/* Wait for VI6_DISP_IRQ_STA_DST flag */
+		ret = readl_poll_timeout(vsp1->mmio + VI6_DISP_IRQ_STA(pipe->output->entity.index),
+			v, v & VI6_DISP_IRQ_STA_DST, 1,  100 * USEC_PER_MSEC);
+		if (ret)
+			dev_warn(vsp1->dev,
+				 "Timeout waiting for VI6_DISP_IRQ_STA_DST\n");
+	}
+
 	dev_dbg(vsp1->dev, "%s: pipeline enabled\n", __func__);
 
 	return 0;
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c
index f8093ba9539e..87f97d2d5773 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c
@@ -302,17 +302,22 @@ void vsp1_pipeline_init(struct vsp1_pipeline *pipe)
 }
 
 /* Must be called with the pipe irqlock held. */
-void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
+bool vsp1_pipeline_run(struct vsp1_pipeline *pipe)
 {
 	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
+	bool started = false;
 
 	if (pipe->state == VSP1_PIPELINE_STOPPED) {
 		vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index),
 			   VI6_CMD_STRCMD);
 		pipe->state = VSP1_PIPELINE_RUNNING;
+
+		started = true;
 	}
 
 	pipe->buffers_ready = 0;
+
+	return started;
 }
 
 bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe)
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_pipe.h b/drivers/media/platform/renesas/vsp1/vsp1_pipe.h
index 674b5748d929..5a7b38efa67a 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1_pipe.h
@@ -155,7 +155,7 @@ struct vsp1_pipeline {
 void vsp1_pipeline_reset(struct vsp1_pipeline *pipe);
 void vsp1_pipeline_init(struct vsp1_pipeline *pipe);
 
-void vsp1_pipeline_run(struct vsp1_pipeline *pipe);
+bool vsp1_pipeline_run(struct vsp1_pipeline *pipe);
 bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe);
 int vsp1_pipeline_stop(struct vsp1_pipeline *pipe);
 bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2023-02-16  9:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-16  9:42 [PATCH] media: renesas: vsp1: Align VSPD startup to HW manual Tomi Valkeinen

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.