@@ -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);
}
@@ -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;
};
/**
@@ -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 */
@@ -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;
@@ -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++) {
@@ -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
@@ -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_ */