summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/ti-vpe/cal-video.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-12-07 00:53:42 +0100
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2021-01-04 11:43:52 +0100
commitcbb8cd7cc129f2920a3edf686bf2d7961cd1b00c (patch)
tree13f067adc6c1f38e6fd27558e0b9816576ecdcb8 /drivers/media/platform/ti-vpe/cal-video.c
parent172ba79dafa0fab92b646671ddae54ae46e9d354 (diff)
downloadlinux-cbb8cd7cc129f2920a3edf686bf2d7961cd1b00c.tar.bz2
media: ti-vpe: cal: Stop write DMA without disabling PPI
When stopping the stream, the driver needs to ensure that ongoing DMA completes and that no new DMA is started. It does so using a feature of the PPI that can be stopped on a frame boundary. The downside of this mechanism is that the DMA can't be stopped independently of the source, which prevents usage of multiple contexts for the same source (to handle CSI-2 virtual channels or data types). Rework the stream stop mechanism to stop the write DMA without disabling the PPI first. The new mechanism relies on the combination of a state machine in the driver and shadowing of the CAL_WR_DMA_CTRL_j.MODE field in the hardware. When a stop is requested, the DMA start interrupt handler will request the hardware to stop at the end of the current frame by disabling the write DMA context in the shadowed register, and flag that a stop is in progress. The next DMA end interrupt will then report that the stop is complete. This makes it possible to stop the PPI after stopping the DMA, and fold the cal_camerarx_ppi_disable() call into cal_camerarx_stop(). Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Benoit Parrot <bparrot@ti.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/media/platform/ti-vpe/cal-video.c')
-rw-r--r--drivers/media/platform/ti-vpe/cal-video.c26
1 files changed, 7 insertions, 19 deletions
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 627d816548b8..d3f805a512c0 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -9,7 +9,6 @@
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*/
-#include <linux/delay.h>
#include <linux/ioctl.h>
#include <linux/pm_runtime.h>
#include <linux/videodev2.h>
@@ -511,6 +510,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
ctx->sequence = 0;
+ ctx->dma_state = CAL_DMA_RUNNING;
pm_runtime_get_sync(ctx->cal->dev);
@@ -530,6 +530,10 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
return 0;
err:
+ cal_ctx_wr_dma_disable(ctx);
+ cal_ctx_disable_irqs(ctx);
+ ctx->dma_state = CAL_DMA_STOPPED;
+
spin_lock_irqsave(&ctx->slock, flags);
vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
ctx->cur_frm = NULL;
@@ -547,26 +551,9 @@ static void cal_stop_streaming(struct vb2_queue *vq)
struct cal_ctx *ctx = vb2_get_drv_priv(vq);
struct cal_dmaqueue *dma_q = &ctx->vidq;
struct cal_buffer *buf, *tmp;
- unsigned long timeout;
unsigned long flags;
- bool dma_act;
-
- cal_camerarx_ppi_disable(ctx->phy);
-
- /* wait for stream and dma to finish */
- dma_act = true;
- timeout = jiffies + msecs_to_jiffies(500);
- while (dma_act && time_before(jiffies, timeout)) {
- msleep(50);
-
- spin_lock_irqsave(&ctx->slock, flags);
- dma_act = ctx->dma_act;
- spin_unlock_irqrestore(&ctx->slock, flags);
- }
-
- if (dma_act)
- ctx_err(ctx, "failed to disable dma cleanly\n");
+ cal_ctx_wr_dma_stop(ctx);
cal_ctx_disable_irqs(ctx);
v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0);
@@ -745,6 +732,7 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
INIT_LIST_HEAD(&ctx->vidq.active);
spin_lock_init(&ctx->slock);
mutex_init(&ctx->mutex);
+ init_waitqueue_head(&ctx->dma_wait);
/* Initialize the vb2 queue. */
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;