[media] s5p-fimc: Add pipeline ops to separate FIMC-LITE module
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Tue, 14 Aug 2012 13:46:58 +0000 (10:46 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 1 Oct 2012 23:25:32 +0000 (20:25 -0300)
In order to reuse the FIMC-LITE module on Exynos4 and Exynos5
SoC introduce a set of callbacks for the media pipeline control
from within FIMC/FIMC-LITE video node. It lets us avoid symbol
dependencies between FIMC-LITE and the whole media device driver,
which simplifies the initialization sequences and doesn't
introduce issues preventing common kernel image for exynos4 and
exynos5 SoCs.
This patch also corrects following build errors:
drivers/built-in.o: In function `buffer_queue':
drivers/media/video/s5p-fimc/fimc-lite.c:414: undefined reference
to `fimc_pipeline_s_stream'
drivers/built-in.o: In function `fimc_lite_resume':
drivers/media/video/s5p-fimc/fimc-lite.c:1518: undefined reference
to `fimc_pipeline_initialize'
drivers/built-in.o: In function `fimc_lite_suspend':
drivers/media/video/s5p-fimc/fimc-lite.c:1544: undefined reference
to `fimc_pipeline_shutdown'
when only CONFIG_VIDEO_EXYNOS_FIMC_LITE is selected, without
CONFIG_VIDEO_S5P_FIMC.

Reported-by: Sachin Kamat <sachin.kamat@linaro.org>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/platform/s5p-fimc/fimc-capture.c
drivers/media/platform/s5p-fimc/fimc-core.h
drivers/media/platform/s5p-fimc/fimc-lite.c
drivers/media/platform/s5p-fimc/fimc-lite.h
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/s5p-fimc/fimc-mdevice.h
include/media/s5p_fimc.h

index ac2ca36039e49b7b14d87388d8781943f144507a..6792fd4236c6f0af224d2e856354ed4f577ae3bb 100644 (file)
@@ -118,7 +118,8 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
        spin_unlock_irqrestore(&fimc->slock, flags);
 
        if (streaming)
-               return fimc_pipeline_s_stream(&fimc->pipeline, 0);
+               return fimc_pipeline_call(fimc, set_stream,
+                                         &fimc->pipeline, 0);
        else
                return 0;
 }
@@ -264,7 +265,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
                fimc_activate_capture(ctx);
 
                if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
        }
 
        return 0;
@@ -288,7 +290,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc)
        int ret = fimc_stop_capture(fimc, suspend);
        if (ret)
                return ret;
-       return fimc_pipeline_shutdown(&fimc->pipeline);
+       return fimc_pipeline_call(fimc, close, &fimc->pipeline);
 }
 
 static void buffer_queue(struct vb2_buffer *vb);
@@ -304,8 +306,8 @@ int fimc_capture_resume(struct fimc_dev *fimc)
 
        INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
        vid_cap->buf_index = 0;
-       fimc_pipeline_initialize(&fimc->pipeline, &vid_cap->vfd.entity,
-                                false);
+       fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                          &vid_cap->vfd.entity, false);
        fimc_capture_hw_init(fimc);
 
        clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
@@ -422,7 +424,8 @@ static void buffer_queue(struct vb2_buffer *vb)
                spin_unlock_irqrestore(&fimc->slock, flags);
 
                if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
                return;
        }
        spin_unlock_irqrestore(&fimc->slock, flags);
@@ -502,8 +505,8 @@ static int fimc_capture_open(struct file *file)
        }
 
        if (++fimc->vid_cap.refcnt == 1) {
-               ret = fimc_pipeline_initialize(&fimc->pipeline,
-                                      &fimc->vid_cap.vfd.entity, true);
+               ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                                        &fimc->vid_cap.vfd.entity, true);
 
                if (!ret && !fimc->vid_cap.user_subdev_api)
                        ret = fimc_capture_set_default_format(fimc);
@@ -536,7 +539,7 @@ static int fimc_capture_close(struct file *file)
        if (--fimc->vid_cap.refcnt == 0) {
                clear_bit(ST_CAPT_BUSY, &fimc->state);
                fimc_stop_capture(fimc, false);
-               fimc_pipeline_shutdown(&fimc->pipeline);
+               fimc_pipeline_call(fimc, close, &fimc->pipeline);
                clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
        }
 
index d3a3a00321c3d868d484c565fed2a87ab684c950..61805469bdd727794193d7fe25996863eb8e43fd 100644 (file)
@@ -440,6 +440,7 @@ struct fimc_dev {
        unsigned long                   state;
        struct vb2_alloc_ctx            *alloc_ctx;
        struct fimc_pipeline            pipeline;
+       const struct fimc_pipeline_ops  *pipeline_ops;
 };
 
 /**
index cd4cf12d20e3a4afb976a590f56baa9b29397b37..bef8d3ef79cc7553e288bd8e78e7046d822a8dac 100644 (file)
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
+#include <media/s5p_fimc.h>
 
 #include "fimc-mdevice.h"
 #include "fimc-core.h"
+#include "fimc-lite.h"
 #include "fimc-lite-reg.h"
 
 static int debug;
@@ -193,7 +195,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
        if (!streaming)
                return 0;
 
-       return fimc_pipeline_s_stream(&fimc->pipeline, 0);
+       return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0);
 }
 
 static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend)
@@ -307,7 +309,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
                flite_hw_capture_start(fimc);
 
                if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
        }
        if (debug > 0)
                flite_hw_dump_regs(fimc, __func__);
@@ -411,7 +414,8 @@ static void buffer_queue(struct vb2_buffer *vb)
                spin_unlock_irqrestore(&fimc->slock, flags);
 
                if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
                return;
        }
        spin_unlock_irqrestore(&fimc->slock, flags);
@@ -466,8 +470,8 @@ static int fimc_lite_open(struct file *file)
                goto done;
 
        if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) {
-               ret = fimc_pipeline_initialize(&fimc->pipeline,
-                                              &fimc->vfd.entity, true);
+               ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                                        &fimc->vfd.entity, true);
                if (ret < 0) {
                        pm_runtime_put_sync(&fimc->pdev->dev);
                        fimc->ref_count--;
@@ -493,7 +497,7 @@ static int fimc_lite_close(struct file *file)
        if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
                clear_bit(ST_FLITE_IN_USE, &fimc->state);
                fimc_lite_stop_capture(fimc, false);
-               fimc_pipeline_shutdown(&fimc->pipeline);
+               fimc_pipeline_call(fimc, close, &fimc->pipeline);
                clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
        }
 
@@ -1508,7 +1512,8 @@ static int fimc_lite_resume(struct device *dev)
                return 0;
 
        INIT_LIST_HEAD(&fimc->active_buf_q);
-       fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd.entity, false);
+       fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                          &fimc->vfd.entity, false);
        fimc_lite_hw_init(fimc);
        clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
 
@@ -1534,7 +1539,7 @@ static int fimc_lite_suspend(struct device *dev)
        if (ret < 0 || !fimc_lite_active(fimc))
                return ret;
 
-       return fimc_pipeline_shutdown(&fimc->pipeline);
+       return fimc_pipeline_call(fimc, close, &fimc->pipeline);
 }
 #endif /* CONFIG_PM_SLEEP */
 
index 9944dd36ec7c9288597f91d3f9e0629f4301f240..b04bf3b8369f95ce6b5ed545d8829177f40f29ba 100644 (file)
@@ -108,6 +108,7 @@ struct flite_buffer {
  * @test_pattern: test pattern controls
  * @index: FIMC-LITE platform device index
  * @pipeline: video capture pipeline data structure
+ * @pipeline_ops: media pipeline ops for the video node driver
  * @slock: spinlock protecting this data structure and the hw registers
  * @lock: mutex serializing video device and the subdev operations
  * @clock: FIMC-LITE gate clock
@@ -142,6 +143,7 @@ struct fimc_lite {
        struct v4l2_ctrl        *test_pattern;
        u32                     index;
        struct fimc_pipeline    pipeline;
+       const struct fimc_pipeline_ops *pipeline_ops;
 
        struct mutex            lock;
        spinlock_t              slock;
index e2aa8d99d8584fb34ce0e5182892720d53e1363b..223fcfe2e1b3dc28b6960e495a4214a9c8919045 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <media/v4l2-ctrls.h>
 #include <media/media-device.h>
+#include <media/s5p_fimc.h>
 
 #include "fimc-core.h"
 #include "fimc-lite.h"
@@ -38,7 +39,8 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
  *
  * Caller holds the graph mutex.
  */
-void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me)
+static void fimc_pipeline_prepare(struct fimc_pipeline *p,
+                                 struct media_entity *me)
 {
        struct media_pad *pad = &me->pads[0];
        struct v4l2_subdev *sd;
@@ -114,7 +116,7 @@ static int __subdev_set_power(struct v4l2_subdev *sd, int on)
  *
  * Needs to be called with the graph mutex held.
  */
-int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
+static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
 {
        unsigned int i;
        int ret;
@@ -134,15 +136,15 @@ int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
 }
 
 /**
- * __fimc_pipeline_initialize - update the pipeline information, enable power
- *                              of all pipeline subdevs and the sensor clock
+ * __fimc_pipeline_open - update the pipeline information, enable power
+ *                        of all pipeline subdevs and the sensor clock
  * @me: media entity to start graph walk with
  * @prep: true to acquire sensor (and csis) subdevs
  *
  * This function must be called with the graph mutex held.
  */
-static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
-                                     struct media_entity *me, bool prep)
+static int __fimc_pipeline_open(struct fimc_pipeline *p,
+                               struct media_entity *me, bool prep)
 {
        int ret;
 
@@ -159,28 +161,27 @@ static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
        return fimc_pipeline_s_power(p, 1);
 }
 
-int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
-                            bool prep)
+static int fimc_pipeline_open(struct fimc_pipeline *p,
+                             struct media_entity *me, bool prep)
 {
        int ret;
 
        mutex_lock(&me->parent->graph_mutex);
-       ret =  __fimc_pipeline_initialize(p, me, prep);
+       ret =  __fimc_pipeline_open(p, me, prep);
        mutex_unlock(&me->parent->graph_mutex);
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(fimc_pipeline_initialize);
 
 /**
- * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
+ * __fimc_pipeline_close - disable the sensor clock and pipeline power
  * @fimc: fimc device terminating the pipeline
  *
  * Disable power of all subdevs in the pipeline and turn off the external
  * sensor clock.
  * Called with the graph mutex held.
  */
-static int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
+static int __fimc_pipeline_close(struct fimc_pipeline *p)
 {
        int ret = 0;
 
@@ -191,7 +192,7 @@ static int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
        return ret == -ENXIO ? 0 : ret;
 }
 
-int fimc_pipeline_shutdown(struct fimc_pipeline *p)
+static int fimc_pipeline_close(struct fimc_pipeline *p)
 {
        struct media_entity *me;
        int ret;
@@ -201,12 +202,11 @@ int fimc_pipeline_shutdown(struct fimc_pipeline *p)
 
        me = &p->subdevs[IDX_SENSOR]->entity;
        mutex_lock(&me->parent->graph_mutex);
-       ret = __fimc_pipeline_shutdown(p);
+       ret = __fimc_pipeline_close(p);
        mutex_unlock(&me->parent->graph_mutex);
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(fimc_pipeline_shutdown);
 
 /**
  * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs
@@ -232,7 +232,13 @@ int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
        return 0;
 
 }
-EXPORT_SYMBOL_GPL(fimc_pipeline_s_stream);
+
+/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */
+static const struct fimc_pipeline_ops fimc_pipeline_ops = {
+       .open           = fimc_pipeline_open,
+       .close          = fimc_pipeline_close,
+       .set_stream     = fimc_pipeline_s_stream,
+};
 
 /*
  * Sensor subdevice helper functions
@@ -347,6 +353,7 @@ static int fimc_register_callback(struct device *dev, void *p)
        if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
                return 0;
 
+       fimc->pipeline_ops = &fimc_pipeline_ops;
        fmd->fimc[fimc->pdev->id] = fimc;
        sd->grp_id = FIMC_GROUP_ID;
 
@@ -372,6 +379,7 @@ static int fimc_lite_register_callback(struct device *dev, void *p)
        if (fimc->index >= FIMC_LITE_MAX_DEVS)
                return 0;
 
+       fimc->pipeline_ops = &fimc_pipeline_ops;
        fmd->fimc_lite[fimc->index] = fimc;
        sd->grp_id = FLITE_GROUP_ID;
 
@@ -473,12 +481,14 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
                if (fmd->fimc[i] == NULL)
                        continue;
                v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
+               fmd->fimc[i]->pipeline_ops = NULL;
                fmd->fimc[i] = NULL;
        }
        for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
                if (fmd->fimc_lite[i] == NULL)
                        continue;
                v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev);
+               fmd->fimc[i]->pipeline_ops = NULL;
                fmd->fimc_lite[i] = NULL;
        }
        for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
@@ -832,7 +842,7 @@ static int fimc_md_link_notify(struct media_pad *source,
        }
 
        if (!(flags & MEDIA_LNK_FL_ENABLED)) {
-               ret = __fimc_pipeline_shutdown(pipeline);
+               ret = __fimc_pipeline_close(pipeline);
                pipeline->subdevs[IDX_SENSOR] = NULL;
                pipeline->subdevs[IDX_CSIS] = NULL;
 
@@ -851,8 +861,8 @@ static int fimc_md_link_notify(struct media_pad *source,
        if (fimc) {
                mutex_lock(&fimc->lock);
                if (fimc->vid_cap.refcnt > 0) {
-                       ret = __fimc_pipeline_initialize(pipeline,
-                                                        source->entity, true);
+                       ret = __fimc_pipeline_open(pipeline,
+                                                  source->entity, true);
                if (!ret)
                        ret = fimc_capture_ctrls_create(fimc);
                }
@@ -860,8 +870,8 @@ static int fimc_md_link_notify(struct media_pad *source,
        } else {
                mutex_lock(&fimc_lite->lock);
                if (fimc_lite->ref_count > 0) {
-                       ret = __fimc_pipeline_initialize(pipeline,
-                                                        source->entity, true);
+                       ret = __fimc_pipeline_open(pipeline,
+                                                  source->entity, true);
                }
                mutex_unlock(&fimc_lite->lock);
        }
index d310d9cc3e1a0e2eb2ba08f44158eec7d8058098..0135386457ee985fe3c37ccbd8af8c5c0edc67c8 100644 (file)
@@ -108,11 +108,5 @@ static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
 }
 
 int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
-void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me);
-int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
-                            bool resume);
-int fimc_pipeline_shutdown(struct fimc_pipeline *p);
-int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state);
-int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool state);
 
 #endif
index 8587aaf7364678cbb5a816cd194b568699717b4e..09421a611d73df78ed1d3d6af80571e0511956ce 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef S5P_FIMC_H_
 #define S5P_FIMC_H_
 
+#include <media/media-entity.h>
+
 enum cam_bus_type {
        FIMC_ITU_601 = 1,
        FIMC_ITU_656,
@@ -80,4 +82,20 @@ struct fimc_pipeline {
        struct media_pipeline *m_pipeline;
 };
 
+/*
+ * Media pipeline operations to be called from within the fimc(-lite)
+ * video node when it is the last entity of the pipeline. Implemented
+ * by corresponding media device driver.
+ */
+struct fimc_pipeline_ops {
+       int (*open)(struct fimc_pipeline *p, struct media_entity *me,
+                         bool resume);
+       int (*close)(struct fimc_pipeline *p);
+       int (*set_stream)(struct fimc_pipeline *p, bool state);
+};
+
+#define fimc_pipeline_call(f, op, p, args...)                          \
+       (!(f) ? -ENODEV : (((f)->pipeline_ops && (f)->pipeline_ops->op) ? \
+                           (f)->pipeline_ops->op((p), ##args) : -ENOIOCTLCMD))
+
 #endif /* S5P_FIMC_H_ */