[media] v4l: vsp1: Implement atomic update for the DRM driver
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Thu, 10 Sep 2015 12:28:39 +0000 (09:28 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Fri, 19 Feb 2016 11:31:19 +0000 (09:31 -0200)
Add two API functions named vsp1_du_atomic_begin() and
vsp1_du_atomic_flush() to signal the start and end of an atomic update.
The vsp1_du_setup_rpf() function is renamed to vsp1_du_atomic_update()
for consistency.

With this new API, the driver will reprogram all modified inputs
atomically before restarting the video stream.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/platform/vsp1/vsp1_drm.c
drivers/media/platform/vsp1/vsp1_drm.h
include/media/vsp1.h

index a918bb4..8c76086 100644 (file)
@@ -254,7 +254,26 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
 EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
 
 /**
- * vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline
+ * vsp1_du_atomic_begin - Prepare for an atomic update
+ * @dev: the VSP device
+ */
+void vsp1_du_atomic_begin(struct device *dev)
+{
+       struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+       struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pipe->irqlock, flags);
+
+       vsp1->drm->num_inputs = pipe->num_inputs;
+       vsp1->drm->update = false;
+
+       spin_unlock_irqrestore(&pipe->irqlock, flags);
+}
+EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
+
+/**
+ * vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline
  * @dev: the VSP device
  * @rpf_index: index of the RPF to setup (0-based)
  * @pixelformat: V4L2 pixel format for the RPF memory input
@@ -288,10 +307,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
  *
  * Return 0 on success or a negative error code on failure.
  */
-int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
-                     u32 pixelformat, unsigned int pitch,
-                     dma_addr_t mem[2], const struct v4l2_rect *src,
-                     const struct v4l2_rect *dst)
+int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
+                         u32 pixelformat, unsigned int pitch,
+                         dma_addr_t mem[2], const struct v4l2_rect *src,
+                         const struct v4l2_rect *dst)
 {
        struct vsp1_device *vsp1 = dev_get_drvdata(dev);
        struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
@@ -301,7 +320,6 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
        struct vsp1_rwpf_memory memory;
        struct vsp1_rwpf *rpf;
        unsigned long flags;
-       bool start_stop = false;
        int ret;
 
        if (rpf_index >= vsp1->pdata.rpf_count)
@@ -322,16 +340,11 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
                        vsp1->bru->inputs[rpf_index].rpf = NULL;
                        pipe->inputs[rpf_index] = NULL;
 
-                       vsp1->drm->update = true;
-                       start_stop = --pipe->num_inputs == 0;
+                       pipe->num_inputs--;
                }
 
                spin_unlock_irqrestore(&pipe->irqlock, flags);
 
-               /* Stop the pipeline if we're the last user. */
-               if (start_stop)
-                       vsp1_pipeline_stop(pipe);
-
                return 0;
        }
 
@@ -459,19 +472,42 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
        if (!pipe->inputs[rpf->entity.index]) {
                vsp1->bru->inputs[rpf_index].rpf = rpf;
                pipe->inputs[rpf->entity.index] = rpf;
-               start_stop = pipe->num_inputs++ == 0;
+               pipe->num_inputs++;
        }
 
-       /* Start the pipeline if it's currently stopped. */
+       spin_unlock_irqrestore(&pipe->irqlock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
+
+/**
+ * vsp1_du_atomic_flush - Commit an atomic update
+ * @dev: the VSP device
+ */
+void vsp1_du_atomic_flush(struct device *dev)
+{
+       struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+       struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
+       unsigned long flags;
+       bool stop = false;
+
+       spin_lock_irqsave(&pipe->irqlock, flags);
+
        vsp1->drm->update = true;
-       if (start_stop)
+
+       /* Start or stop the pipeline if needed. */
+       if (!vsp1->drm->num_inputs && pipe->num_inputs)
                vsp1_drm_pipeline_run(pipe);
+       else if (vsp1->drm->num_inputs && !pipe->num_inputs)
+               stop = true;
 
        spin_unlock_irqrestore(&pipe->irqlock, flags);
 
-       return 0;
+       if (stop)
+               vsp1_pipeline_stop(pipe);
 }
-EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf);
+EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
 
 /* -----------------------------------------------------------------------------
  * Initialization
index 2ad320a..25d7f01 100644 (file)
 
 #include "vsp1_pipe.h"
 
+/**
+ * vsp1_drm - State for the API exposed to the DRM driver
+ * @pipe: the VSP1 pipeline used for display
+ * @num_inputs: number of active pipeline inputs at the beginning of an update
+ * @update: the pipeline configuration has been updated
+ */
 struct vsp1_drm {
        struct vsp1_pipeline pipe;
+       unsigned int num_inputs;
        bool update;
 };
 
index 2c1aea7..cc54175 100644 (file)
@@ -23,8 +23,11 @@ int vsp1_du_init(struct device *dev);
 int vsp1_du_setup_lif(struct device *dev, unsigned int width,
                      unsigned int height);
 
-int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat,
-                     unsigned int pitch, dma_addr_t mem[2],
-                     const struct v4l2_rect *src, const struct v4l2_rect *dst);
+int vsp1_du_atomic_begin(struct device *dev);
+int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat,
+                         unsigned int pitch, dma_addr_t mem[2],
+                         const struct v4l2_rect *src,
+                         const struct v4l2_rect *dst);
+int vsp1_du_atomic_flush(struct device *dev);
 
 #endif /* __MEDIA_VSP1_H__ */