Different framerates imply different periods between successive frames.
Therefore it is reasonable to make the timeout of the irq_timer
configurable at the run time so userspace can avoid unnecessary long
waiting times. Therefore this commit adds a new custom control to rcar-vin.
This allows to change the timeout before the start of streaming.

Signed-off-by: Michael Rodin <[email protected]>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 17 ++++++++++++++++-
 drivers/media/platform/rcar-vin/rcar-dma.c  | 14 +++++++++-----
 drivers/media/platform/rcar-vin/rcar-vin.h  |  5 +++++
 include/uapi/linux/rcar-vin.h               |  7 +++++++
 include/uapi/linux/v4l2-controls.h          |  6 ++++++
 5 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c 
b/drivers/media/platform/rcar-vin/rcar-core.c
index 7440c89..81faa87 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -884,6 +884,17 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
        return 0;
 }
 
+static const struct v4l2_ctrl_config rvin_ctrl_irq_timeout = {
+       .ops = &rvin_ctrl_ops,
+       .id = V4L2_CID_RCAR_VIN_IRQ_TIMEOUT,
+       .name = "frame completion timeout",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = S32_MAX,
+       .step = 1,
+       .def = IRQ_TIMEOUT_MS,
+};
+
 static int rvin_mc_init(struct rvin_dev *vin)
 {
        int ret;
@@ -901,13 +912,17 @@ static int rvin_mc_init(struct rvin_dev *vin)
        if (ret)
                rvin_group_put(vin);
 
-       ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 1);
+       ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 2);
        if (ret < 0)
                return ret;
 
        v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
                          V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
 
+       vin->ctrl_irq_timeout = v4l2_ctrl_new_custom(&vin->ctrl_handler,
+                                                    &rvin_ctrl_irq_timeout,
+                                                    NULL);
+
        if (vin->ctrl_handler.error) {
                ret = vin->ctrl_handler.error;
                v4l2_ctrl_handler_free(&vin->ctrl_handler);
diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
b/drivers/media/platform/rcar-vin/rcar-dma.c
index bf8d733..062f338 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -947,7 +947,7 @@ static void rvin_irq_timer_function(struct timer_list 
*timer)
                                            irq_timer);
 
        vin_err(vin, "%s: frame completion timeout after %i ms!\n",
-               __func__, IRQ_TIMEOUT_MS);
+               __func__, jiffies_to_msecs(vin->irq_timeout));
        v4l2_event_queue(&vin->vdev, &rvin_irq_timeout);
 }
 
@@ -1022,7 +1022,7 @@ static irqreturn_t rvin_irq(int irq, void *data)
                vin_dbg(vin, "Dropping frame %u\n", vin->sequence);
        }
 
-       mod_timer(&vin->irq_timer, jiffies + msecs_to_jiffies(IRQ_TIMEOUT_MS));
+       mod_timer(&vin->irq_timer, jiffies + vin->irq_timeout);
 
        vin->sequence++;
 
@@ -1233,6 +1233,7 @@ static int rvin_start_streaming(struct vb2_queue *vq, 
unsigned int count)
        struct rvin_dev *vin = vb2_get_drv_priv(vq);
        unsigned long flags;
        int ret;
+       s32 irq_timeout = v4l2_ctrl_g_ctrl(vin->ctrl_irq_timeout);
 
        /* Allocate scratch buffer. */
        vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage,
@@ -1265,11 +1266,14 @@ static int rvin_start_streaming(struct vb2_queue *vq, 
unsigned int count)
 
        spin_unlock_irqrestore(&vin->qlock, flags);
 out:
-       if (ret)
+       if (ret) {
                dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
                                  vin->scratch_phys);
-       else
-               mod_timer(&vin->irq_timer, jiffies + 
msecs_to_jiffies(IRQ_TIMEOUT_MS));
+       } else {
+               vin->irq_timeout = msecs_to_jiffies(irq_timeout);
+               mod_timer(&vin->irq_timer, jiffies + vin->irq_timeout);
+               vin_dbg(vin, "%s: set irq timer to %i ms\n", __func__, 
irq_timeout);
+       }
 
        return ret;
 }
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h 
b/drivers/media/platform/rcar-vin/rcar-vin.h
index 7408f67..4e514e7 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -201,6 +201,9 @@ struct rvin_info {
  * @src_rect:          active size of the video source
  * @std:               active video standard of the video source
  * @irq_timer:         monitors regular capturing of frames in rvin_irq()
+ * @irq_timeout:       timeout value in jiffies, which is currently used by
+ *                     @irq_timer and can be changed via @ctrl_irq_timeout
+ * @ctrl_irq_timeout:  controls value of @irq_timeout
  *
  * @alpha:             Alpha component to fill in for supported pixel formats
  */
@@ -246,6 +249,8 @@ struct rvin_dev {
        v4l2_std_id std;
 
        struct timer_list irq_timer;
+       unsigned long irq_timeout;
+       struct v4l2_ctrl *ctrl_irq_timeout;
        unsigned int alpha;
 };
 
diff --git a/include/uapi/linux/rcar-vin.h b/include/uapi/linux/rcar-vin.h
index 4eb7f5e..6c72584 100644
--- a/include/uapi/linux/rcar-vin.h
+++ b/include/uapi/linux/rcar-vin.h
@@ -3,8 +3,15 @@
 #ifndef RCAR_VIN_USER_H
 #define RCAR_VIN_USER_H
 
+#include <linux/v4l2-controls.h>
+
 /* class for events sent by the rcar-vin driver */
 #define V4L2_EVENT_RCAR_VIN_CLASS      V4L2_EVENT_PRIVATE_START
 #define V4L2_EVENT_RCAR_VIN_IRQ_TIMEOUT        (V4L2_EVENT_RCAR_VIN_CLASS | 
0x1)
 
+/* private controls for rcar-vin */
+enum rcar_vin_ctrl_id {
+       V4L2_CID_RCAR_VIN_IRQ_TIMEOUT = V4L2_CID_USER_RCAR_VIN_BASE
+};
+
 #endif /* RCAR_VIN_USER_H */
diff --git a/include/uapi/linux/v4l2-controls.h 
b/include/uapi/linux/v4l2-controls.h
index 6227141..cf4f085 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -198,6 +198,12 @@ enum v4l2_colorfx {
  */
 #define V4L2_CID_USER_ATMEL_ISC_BASE           (V4L2_CID_USER_BASE + 0x10c0)
 
+/*
+ * The base for the rcar-vin driver controls.
+ * We reserve 16 controls for this driver.
+ */
+#define V4L2_CID_USER_RCAR_VIN_BASE            (V4L2_CID_USER_BASE + 0x10d0)
+
 /* MPEG-class control IDs */
 /* The MPEG controls are applicable to all codec controls
  * and the 'MPEG' part of the define is historical */
-- 
2.7.4

Reply via email to