linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benoit Parrot <bparrot@ti.com>
To: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>,
	<linux-media@vger.kernel.org>, <devicetree@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, Benoit Parrot <bparrot@ti.com>
Subject: [Patch 04/13] media: am437x-vpfe: Wait for end of frame before tear-down
Date: Mon, 9 Sep 2019 11:27:34 -0500	[thread overview]
Message-ID: <20190909162743.30114-5-bparrot@ti.com> (raw)
In-Reply-To: <20190909162743.30114-1-bparrot@ti.com>

We were originally attempting to stop all processing as soon
as possible, but the in-progress DMA operation cannot be canceled.
This led to the module being in a busy state and prevented proper
power management functionality.

The existing implementation would attempt to clean things up by waiting
up to 50ms. However when receiving video frame at 15fps or lower,
it meant an inter frame arrival rate of 66.6 ms or higher.
In such cases upon tear down the following message could be seen:
omap_hwmod: vpfe0: _wait_target_disable failed

This patch fixes this issue by adding a stopping state where
we would wait for the next Vsync before disabling the hardware.

Signed-off-by: Benoit Parrot <bparrot@ti.com>
---
 drivers/media/platform/am437x/am437x-vpfe.c | 52 ++++++++++-----------
 drivers/media/platform/am437x/am437x-vpfe.h |  3 ++
 2 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index 7c5b734f7143..3a8ad9bdf283 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -441,40 +441,25 @@ static void vpfe_ccdc_restore_defaults(struct vpfe_ccdc *ccdc)
 
 static int vpfe_ccdc_close(struct vpfe_ccdc *ccdc, struct device *dev)
 {
-	int dma_cntl, i, pcr;
+	struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc);
+	u32 dma_cntl, pcr;
 
-	/* If the CCDC module is still busy wait for it to be done */
-	for (i = 0; i < 10; i++) {
-		usleep_range(5000, 6000);
-		pcr = vpfe_reg_read(ccdc, VPFE_PCR);
-		if (!pcr)
-			break;
+	pcr = vpfe_reg_read(ccdc, VPFE_PCR);
+	if (pcr)
+		vpfe_dbg(1, vpfe, "VPFE_PCR is still set (%x)", pcr);
 
-		/* make sure it it is disabled */
-		vpfe_pcr_enable(ccdc, 0);
-	}
+	dma_cntl = vpfe_reg_read(ccdc, VPFE_DMA_CNTL);
+	if ((dma_cntl & VPFE_DMA_CNTL_OVERFLOW))
+		vpfe_dbg(1, vpfe, "VPFE_DMA_CNTL_OVERFLOW is still set (%x)",
+			 dma_cntl);
 
 	/* Disable CCDC by resetting all register to default POR values */
 	vpfe_ccdc_restore_defaults(ccdc);
 
-	/* if DMA_CNTL overflow bit is set. Clear it
-	 *  It appears to take a while for this to become quiescent ~20ms
-	 */
-	for (i = 0; i < 10; i++) {
-		dma_cntl = vpfe_reg_read(ccdc, VPFE_DMA_CNTL);
-		if (!(dma_cntl & VPFE_DMA_CNTL_OVERFLOW))
-			break;
-
-		/* Clear the overflow bit */
-		vpfe_reg_write(ccdc, dma_cntl, VPFE_DMA_CNTL);
-		usleep_range(5000, 6000);
-	}
-
 	/* Disabled the module at the CONFIG level */
 	vpfe_config_enable(ccdc, 0);
 
 	pm_runtime_put_sync(dev);
-
 	return 0;
 }
 
@@ -1303,6 +1288,9 @@ static void vpfe_handle_interlaced_irq(struct vpfe_device *vpfe,
 			if (vpfe->cur_frm != vpfe->next_frm)
 				vpfe_process_buffer_complete(vpfe);
 
+			if (vpfe->stopping)
+				return;
+
 			/*
 			 * based on whether the two fields are stored
 			 * interleave or separately in memory,
@@ -1341,7 +1329,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev)
 {
 	struct vpfe_device *vpfe = (struct vpfe_device *)dev;
 	enum v4l2_field field = vpfe->fmt.fmt.pix.field;
-	int intr_status;
+	int intr_status, stopping = vpfe->stopping;
 
 	intr_status = vpfe_reg_read(&vpfe->ccdc, VPFE_IRQ_STS);
 
@@ -1352,9 +1340,13 @@ static irqreturn_t vpfe_isr(int irq, void *dev)
 		} else {
 			vpfe_handle_interlaced_irq(vpfe, field);
 		}
+		if (stopping) {
+			vpfe->stopping = false;
+			complete(&vpfe->capture_stop);
+		}
 	}
 
-	if (intr_status & VPFE_VDINT1) {
+	if (intr_status & VPFE_VDINT1 && !stopping) {
 		if (field == V4L2_FIELD_NONE &&
 		    vpfe->cur_frm == vpfe->next_frm)
 			vpfe_schedule_next_buffer(vpfe);
@@ -1980,6 +1972,9 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	vpfe_attach_irq(vpfe);
 
+	vpfe->stopping = false;
+	init_completion(&vpfe->capture_stop);
+
 	if (vpfe->ccdc.ccdc_cfg.if_type == VPFE_RAW_BAYER)
 		vpfe_ccdc_config_raw(&vpfe->ccdc);
 	else
@@ -2032,6 +2027,11 @@ static void vpfe_stop_streaming(struct vb2_queue *vq)
 
 	vpfe_pcr_enable(&vpfe->ccdc, 0);
 
+	/* Wait for the last frame to be captured */
+	vpfe->stopping = true;
+	wait_for_completion_timeout(&vpfe->capture_stop,
+				    msecs_to_jiffies(250));
+
 	vpfe_detach_irq(vpfe);
 
 	sdinfo = vpfe->current_subdev;
diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h
index 4678285f34c6..2dde09780215 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.h
+++ b/drivers/media/platform/am437x/am437x-vpfe.h
@@ -23,6 +23,7 @@
 
 #include <linux/am437x-vpfe.h>
 #include <linux/clk.h>
+#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
@@ -270,6 +271,8 @@ struct vpfe_device {
 	 */
 	u32 field_off;
 	struct vpfe_ccdc ccdc;
+	int stopping;
+	struct completion capture_stop;
 };
 
 #endif	/* AM437X_VPFE_H */
-- 
2.17.1


  parent reply	other threads:[~2019-09-09 16:26 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-09 16:27 [Patch 00/13] media: am437x-vpfe: overdue maintenance Benoit Parrot
2019-09-09 16:27 ` [Patch 01/13] media: am437x-vpfe: Fix suspend path to always handle pinctrl config Benoit Parrot
2019-09-13 12:59   ` Hans Verkuil
2019-09-13 13:24     ` Benoit Parrot
2019-09-09 16:27 ` [Patch 02/13] media: am437x-vpfe: Fix missing first line Benoit Parrot
2019-09-13 13:00   ` Hans Verkuil
2019-09-13 13:25     ` Benoit Parrot
2019-09-09 16:27 ` [Patch 03/13] media: am437x-vpfe: Rework ISR routine for clarity Benoit Parrot
2019-09-09 16:27 ` Benoit Parrot [this message]
2019-09-09 16:27 ` [Patch 05/13] media: am437x-vpfe: Streamlined vb2 buffer cleanup Benoit Parrot
2019-09-16  8:00   ` Lad, Prabhakar
2019-09-16 14:53     ` Benoit Parrot
2019-09-16 16:02       ` Lad, Prabhakar
2019-09-09 16:27 ` [Patch 06/13] media: am437x-vpfe: Setting STD to current value is not an error Benoit Parrot
2019-09-09 16:27 ` [Patch 07/13] media: am437x-vpfe: Use a per instance format array instead of a static one Benoit Parrot
2019-09-13 13:07   ` Hans Verkuil
2019-09-13 13:29     ` Benoit Parrot
2019-09-17 16:19     ` Benoit Parrot
2019-09-09 16:27 ` [Patch 08/13] media: am437x-vpfe: Maintain a reference to the current vpfe_fmt Benoit Parrot
2019-09-13 13:14   ` Hans Verkuil
2019-09-13 13:32     ` Benoit Parrot
2019-09-13 13:34       ` Hans Verkuil
2019-09-13 13:43         ` Benoit Parrot
2019-09-09 16:27 ` [Patch 09/13] media: am437x-vpfe: fix function trace debug log Benoit Parrot
2019-09-09 16:54   ` Joe Perches
2019-09-09 17:14     ` Benoit Parrot
2019-09-09 16:27 ` [Patch 10/13] media: am437x-vpfe: Remove print_fourcc helper Benoit Parrot
2019-09-09 16:39   ` Joe Perches
2019-09-09 17:12     ` Benoit Parrot
2019-09-09 16:27 ` [Patch 11/13] media: am437x-vpfe: TRY_FMT ioctl is not really trying anything Benoit Parrot
2019-09-09 16:27 ` [Patch 12/13] media: am437x-vpfe: Remove per bus width static data Benoit Parrot
2019-09-13 13:19   ` Hans Verkuil
2019-09-13 13:34     ` Benoit Parrot
2019-09-09 16:27 ` [Patch 13/13] media: am437x-vpfe: Switch to SPDX Licensing Benoit Parrot
2019-09-10 10:42 ` [Patch 00/13] media: am437x-vpfe: overdue maintenance Hans Verkuil
2019-09-10 16:20   ` Benoit Parrot

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=20190909162743.30114-5-bparrot@ti.com \
    --to=bparrot@ti.com \
    --cc=devicetree@vger.kernel.org \
    --cc=hverkuil@xs4all.nl \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=prabhakar.csengg@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).