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;
}
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;
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);
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);
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);
}
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);
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);
}
unsigned long state;
struct vb2_alloc_ctx *alloc_ctx;
struct fimc_pipeline pipeline;
+ const struct fimc_pipeline_ops *pipeline_ops;
};
/**
#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;
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)
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__);
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);
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--;
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);
}
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);
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 */
* @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
struct v4l2_ctrl *test_pattern;
u32 index;
struct fimc_pipeline pipeline;
+ const struct fimc_pipeline_ops *pipeline_ops;
struct mutex lock;
spinlock_t slock;
#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"
*
* 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;
*
* 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;
}
/**
- * __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;
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;
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;
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
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
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;
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;
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++) {
}
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;
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);
}
} 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);
}
}
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
#ifndef S5P_FIMC_H_
#define S5P_FIMC_H_
+#include <media/media-entity.h>
+
enum cam_bus_type {
FIMC_ITU_601 = 1,
FIMC_ITU_656,
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_ */