From: Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx>

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
---
 drivers/media/platform/s5p-fimc/fimc-capture.c | 21 ++++++++++++---------
 drivers/media/platform/s5p-fimc/fimc-core.h    |  1 +
 drivers/media/platform/s5p-fimc/fimc-lite.c    | 22 ++++++++++++++--------
 drivers/media/platform/s5p-fimc/fimc-lite.h    |  2 ++
 drivers/media/platform/s5p-fimc/fimc-mdevice.c | 26 ++++++++++++++++++--------
 drivers/media/platform/s5p-fimc/fimc-mdevice.h |  6 ------
 include/media/s5p_fimc.h                       | 18 ++++++++++++++++++
 7 files changed, 65 insertions(+), 31 deletions(-)

diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index 4092388..ab1fa9d 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -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, shutdown, &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, initialize, &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, initialize, &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, shutdown, &fimc->pipeline);
 		clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
 	}

diff --git a/drivers/media/platform/s5p-fimc/fimc-core.h b/drivers/media/platform/s5p-fimc/fimc-core.h
index d3a3a00..6180546 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.h
+++ b/drivers/media/platform/s5p-fimc/fimc-core.h
@@ -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;
 };

 /**
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c
index 9289008..5e99713 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.c
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.c
@@ -28,11 +28,14 @@
 #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;
 module_param(debug, int, 0644);

@@ -193,7 +196,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 +310,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 +415,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 +471,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, initialize, &fimc->pipeline,
+					 &fimc->vfd.entity, true);
 		if (ret < 0) {
 			pm_runtime_put_sync(&fimc->pdev->dev);
 			fimc->ref_count--;
@@ -493,7 +498,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, shutdown, &fimc->pipeline);
 		clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
 	}

@@ -1505,7 +1510,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, initialize, &fimc->pipeline,
+			   &fimc->vfd.entity, false);
 	fimc_lite_hw_init(fimc);
 	clear_bit(ST_FLITE_SUSPENDED, &fimc->state);

@@ -1531,7 +1537,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, shutdown, &fimc->pipeline);
 }
 #endif /* CONFIG_PM_SLEEP */

diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.h b/drivers/media/platform/s5p-fimc/fimc-lite.h
index 9944dd3..b04bf3b 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.h
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.h
@@ -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;
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 3c76bd9..d97d190 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -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;
@@ -159,8 +161,8 @@ 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_initialize(struct fimc_pipeline *p,
+				    struct media_entity *me, bool prep)
 {
 	int ret;

@@ -170,7 +172,6 @@ int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,

 	return ret;
 }
-EXPORT_SYMBOL_GPL(fimc_pipeline_initialize);

 /**
  * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
@@ -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_shutdown(struct fimc_pipeline *p)
 {
 	struct media_entity *me;
 	int ret;
@@ -206,7 +207,6 @@ int fimc_pipeline_shutdown(struct fimc_pipeline *p)

 	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 = {
+	.initialize	= fimc_pipeline_initialize,
+	.shutdown	= fimc_pipeline_shutdown,
+	.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++) {
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
index d310d9c..0135386 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
@@ -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
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
index 8587aaf..6ea4017 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/s5p_fimc.h
@@ -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 a corresponding media device driver.
+ */
+struct fimc_pipeline_ops {
+	int (*initialize)(struct fimc_pipeline *p, struct media_entity *me,
+			  bool resume);
+	int (*shutdown)(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_ */
--
1.7.11.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux