[RFC 01/12] media: s5p-fimc: modify existing mdev to use common pipeline
Shaik Ameer Basha
shaik.ameer at samsung.com
Wed Mar 6 22:53:47 EST 2013
This patch modifies the current fimc_pipeline to exynos_pipeline,
which can be used across multiple media device drivers.
Signed-off-by: Shaik Ameer Basha <shaik.ameer at samsung.com>
---
drivers/media/platform/s5p-fimc/fimc-capture.c | 96 +++++++-----
drivers/media/platform/s5p-fimc/fimc-core.h | 4 +-
drivers/media/platform/s5p-fimc/fimc-lite.c | 73 ++++------
drivers/media/platform/s5p-fimc/fimc-lite.h | 4 +-
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 186 ++++++++++++++++++++++--
drivers/media/platform/s5p-fimc/fimc-mdevice.h | 41 +++---
include/media/s5p_fimc.h | 66 ++++++---
7 files changed, 326 insertions(+), 144 deletions(-)
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index 4cbaf46..106466e 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -27,24 +27,26 @@
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
-#include "fimc-mdevice.h"
#include "fimc-core.h"
#include "fimc-reg.h"
static int fimc_capture_hw_init(struct fimc_dev *fimc)
{
struct fimc_ctx *ctx = fimc->vid_cap.ctx;
- struct fimc_pipeline *p = &fimc->pipeline;
+ struct exynos_pipeline *p = &fimc->pipeline;
struct fimc_sensor_info *sensor;
unsigned long flags;
+ struct v4l2_subdev *sd;
int ret = 0;
- if (p->subdevs[IDX_SENSOR] == NULL || ctx == NULL)
+ sd = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, p);
+ if (sd == NULL || ctx == NULL)
return -ENXIO;
if (ctx->s_frame.fmt == NULL)
return -EINVAL;
- sensor = v4l2_get_subdev_hostdata(p->subdevs[IDX_SENSOR]);
+ sensor = v4l2_get_subdev_hostdata(sd);
spin_lock_irqsave(&fimc->slock, flags);
fimc_prepare_dma_offset(ctx, &ctx->d_frame);
@@ -118,7 +120,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
spin_unlock_irqrestore(&fimc->slock, flags);
if (streaming)
- return fimc_pipeline_call(fimc, set_stream,
+ return exynos_pipeline_call(fimc, set_stream,
&fimc->pipeline, 0);
else
return 0;
@@ -177,13 +179,16 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
{
- struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
+ struct v4l2_subdev *csis;
struct fimc_vid_cap *cap = &fimc->vid_cap;
struct fimc_frame *f = &cap->ctx->d_frame;
struct fimc_vid_buffer *v_buf;
struct timeval *tv;
struct timespec ts;
+ csis = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_csis, &fimc->pipeline);
+
if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
wake_up(&fimc->irq_queue);
goto done;
@@ -286,7 +291,7 @@ 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_call(fimc, set_stream,
+ exynos_pipeline_call(fimc, set_stream,
&fimc->pipeline, 1);
}
@@ -311,7 +316,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc)
int ret = fimc_stop_capture(fimc, suspend);
if (ret)
return ret;
- return fimc_pipeline_call(fimc, close, &fimc->pipeline);
+ return exynos_pipeline_call(fimc, close, &fimc->pipeline);
}
static void buffer_queue(struct vb2_buffer *vb);
@@ -327,7 +332,7 @@ int fimc_capture_resume(struct fimc_dev *fimc)
INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
vid_cap->buf_index = 0;
- fimc_pipeline_call(fimc, open, &fimc->pipeline,
+ exynos_pipeline_call(fimc, open, &fimc->pipeline,
&vid_cap->vfd.entity, false);
fimc_capture_hw_init(fimc);
@@ -447,7 +452,7 @@ 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_call(fimc, set_stream,
+ exynos_pipeline_call(fimc, set_stream,
&fimc->pipeline, 1);
return;
}
@@ -486,9 +491,12 @@ static struct vb2_ops fimc_capture_qops = {
int fimc_capture_ctrls_create(struct fimc_dev *fimc)
{
struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
- struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR];
+ struct v4l2_subdev *sensor;
int ret;
+ sensor = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline);
+
if (WARN_ON(vid_cap->ctx == NULL))
return -ENXIO;
if (vid_cap->ctx->ctrls.ready)
@@ -513,7 +521,7 @@ static int fimc_capture_open(struct file *file)
dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
- fimc_md_graph_lock(fimc);
+ exynos_pipeline_graph_lock(fimc->pipeline_ops, &fimc->pipeline);
mutex_lock(&fimc->lock);
if (fimc_m2m_active(fimc))
@@ -531,7 +539,7 @@ static int fimc_capture_open(struct file *file)
}
if (++fimc->vid_cap.refcnt == 1) {
- ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
+ ret = exynos_pipeline_call(fimc, open, &fimc->pipeline,
&fimc->vid_cap.vfd.entity, true);
if (!ret && !fimc->vid_cap.user_subdev_api)
@@ -549,7 +557,7 @@ static int fimc_capture_open(struct file *file)
}
unlock:
mutex_unlock(&fimc->lock);
- fimc_md_graph_unlock(fimc);
+ exynos_pipeline_graph_unlock(fimc->pipeline_ops, &fimc->pipeline);
return ret;
}
@@ -565,7 +573,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_call(fimc, close, &fimc->pipeline);
+ exynos_pipeline_call(fimc, close, &fimc->pipeline);
clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
}
@@ -826,7 +834,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
bool set)
{
struct fimc_dev *fimc = ctx->fimc_dev;
- struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
+ struct v4l2_subdev *sd;
struct v4l2_subdev_format sfmt;
struct v4l2_mbus_framefmt *mf = &sfmt.format;
struct media_entity *me;
@@ -835,6 +843,9 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
int ret, i = 1;
u32 fcc;
+ sd = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline);
+
if (WARN_ON(!sd || !tfmt))
return -EINVAL;
@@ -968,7 +979,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
struct fimc_fmt *ffmt = NULL;
int ret = 0;
- fimc_md_graph_lock(fimc);
+ exynos_pipeline_graph_lock(fimc->pipeline_ops, &fimc->pipeline);
mutex_lock(&fimc->lock);
if (fimc_jpeg_fourcc(pix->pixelformat)) {
@@ -1000,11 +1011,13 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
if (ffmt->flags & FMT_FLAGS_COMPRESSED)
- fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
- pix->plane_fmt, ffmt->memplanes, true);
+ fimc_get_sensor_frame_desc(
+ exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline),
+ pix->plane_fmt, ffmt->memplanes, true);
unlock:
mutex_unlock(&fimc->lock);
- fimc_md_graph_unlock(fimc);
+ exynos_pipeline_graph_unlock(fimc->pipeline_ops, &fimc->pipeline);
return ret;
}
@@ -1070,9 +1083,10 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc,
fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
- ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
- pix->plane_fmt, ff->fmt->memplanes,
- true);
+ ret = fimc_get_sensor_frame_desc(
+ exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline),
+ pix->plane_fmt, ff->fmt->memplanes, true);
if (ret < 0)
return ret;
}
@@ -1105,7 +1119,7 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
struct fimc_dev *fimc = video_drvdata(file);
int ret;
- fimc_md_graph_lock(fimc);
+ exynos_pipeline_graph_lock(fimc->pipeline_ops, &fimc->pipeline);
mutex_lock(&fimc->lock);
/*
* The graph is walked within __fimc_capture_set_format() to set
@@ -1118,7 +1132,7 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
ret = __fimc_capture_set_format(fimc, f);
mutex_unlock(&fimc->lock);
- fimc_md_graph_unlock(fimc);
+ exynos_pipeline_graph_unlock(fimc->pipeline_ops, &fimc->pipeline);
return ret;
}
@@ -1126,7 +1140,10 @@ static int fimc_cap_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
struct fimc_dev *fimc = video_drvdata(file);
- struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
+ struct v4l2_subdev *sd;
+
+ sd = exynos_pipeline_get_subdev(fimc->pipeline_ops, get_subdev_sensor,
+ &fimc->pipeline);
if (i->index != 0)
return -EINVAL;
@@ -1205,8 +1222,9 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
src_fmt.format.code != sink_fmt.format.code)
return -EPIPE;
- if (sd == fimc->pipeline.subdevs[IDX_SENSOR] &&
- fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
+ if (sd == exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline) &&
+ fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
struct fimc_frame *frame = &vid_cap->ctx->d_frame;
unsigned int i;
@@ -1229,14 +1247,17 @@ static int fimc_cap_streamon(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct fimc_dev *fimc = video_drvdata(file);
- struct fimc_pipeline *p = &fimc->pipeline;
- struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR];
+ struct exynos_pipeline *p = &fimc->pipeline;
+ struct v4l2_subdev *sd;
int ret;
+ sd = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, p);
+
if (fimc_capture_active(fimc))
return -EBUSY;
- ret = media_entity_pipeline_start(&sd->entity, p->m_pipeline);
+ ret = media_entity_pipeline_start(&sd->entity, &p->m_pipeline);
if (ret < 0)
return ret;
@@ -1254,9 +1275,12 @@ static int fimc_cap_streamoff(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct fimc_dev *fimc = video_drvdata(file);
- struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
+ struct v4l2_subdev *sd;
int ret;
+ sd = exynos_pipeline_get_subdev(fimc->pipeline_ops, get_subdev_sensor,
+ &fimc->pipeline);
+
ret = vb2_streamoff(&fimc->vid_cap.vbq, type);
if (ret == 0)
media_entity_pipeline_stop(&sd->entity);
@@ -1489,18 +1513,13 @@ void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
{
struct fimc_sensor_info *sensor;
struct fimc_vid_buffer *buf;
- struct fimc_md *fmd;
struct fimc_dev *fimc;
- unsigned long flags;
if (sd == NULL)
return;
sensor = v4l2_get_subdev_hostdata(sd);
- fmd = entity_to_fimc_mdev(&sd->entity);
-
- spin_lock_irqsave(&fmd->slock, flags);
- fimc = sensor ? sensor->host : NULL;
+ fimc = sensor ? (struct fimc_dev *)sensor->host : NULL;
if (fimc && arg && notification == S5P_FIMC_TX_END_NOTIFY &&
test_bit(ST_CAPT_PEND, &fimc->state)) {
@@ -1515,7 +1534,6 @@ void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
fimc_deactivate_capture(fimc);
spin_unlock_irqrestore(&fimc->slock, irq_flags);
}
- spin_unlock_irqrestore(&fmd->slock, flags);
}
static int fimc_subdev_enum_mbus_code(struct v4l2_subdev *sd,
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.h b/drivers/media/platform/s5p-fimc/fimc-core.h
index 412d507..57bf708 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.h
+++ b/drivers/media/platform/s5p-fimc/fimc-core.h
@@ -447,8 +447,8 @@ struct fimc_dev {
struct fimc_vid_cap vid_cap;
unsigned long state;
struct vb2_alloc_ctx *alloc_ctx;
- struct fimc_pipeline pipeline;
- const struct fimc_pipeline_ops *pipeline_ops;
+ struct exynos_pipeline pipeline;
+ const struct exynos_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 3266c3f..122cf95 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.c
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.c
@@ -11,6 +11,7 @@
#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
#include <linux/bug.h>
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
@@ -31,8 +32,6 @@
#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"
@@ -123,12 +122,13 @@ static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat,
static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output)
{
- struct fimc_pipeline *pipeline = &fimc->pipeline;
struct v4l2_subdev *sensor;
- struct fimc_sensor_info *si;
+ struct fimc_source_info *src_info;
unsigned long flags;
- sensor = isp_output ? fimc->sensor : pipeline->subdevs[IDX_SENSOR];
+ sensor = isp_output ? fimc->sensor :
+ exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline);
if (sensor == NULL)
return -ENXIO;
@@ -137,10 +137,10 @@ static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output)
return -EINVAL;
/* Get sensor configuration data from the sensor subdev */
- si = v4l2_get_subdev_hostdata(sensor);
+ src_info = v4l2_get_subdev_hostdata(sensor);
spin_lock_irqsave(&fimc->slock, flags);
- flite_hw_set_camera_bus(fimc, &si->pdata);
+ flite_hw_set_camera_bus(fimc, src_info);
flite_hw_set_source_format(fimc, &fimc->inp_frame);
flite_hw_set_window_offset(fimc, &fimc->inp_frame);
flite_hw_set_output_dma(fimc, &fimc->out_frame, !isp_output);
@@ -200,7 +200,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
if (!streaming)
return 0;
- return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0);
+ return exynos_pipeline_call(fimc, set_stream, &fimc->pipeline, 0);
}
static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend)
@@ -314,7 +314,7 @@ 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_call(fimc, set_stream,
+ exynos_pipeline_call(fimc, set_stream,
&fimc->pipeline, 1);
}
if (debug > 0)
@@ -419,7 +419,7 @@ 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_call(fimc, set_stream,
+ exynos_pipeline_call(fimc, set_stream,
&fimc->pipeline, 1);
return;
}
@@ -482,7 +482,7 @@ static int fimc_lite_open(struct file *file)
if (++fimc->ref_count == 1 &&
atomic_read(&fimc->out_path) == FIMC_IO_DMA) {
- ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
+ ret = exynos_pipeline_call(fimc, open, &fimc->pipeline,
&fimc->vfd.entity, true);
if (ret < 0) {
pm_runtime_put_sync(&fimc->pdev->dev);
@@ -510,7 +510,7 @@ static int fimc_lite_close(struct file *file)
atomic_read(&fimc->out_path) == FIMC_IO_DMA) {
clear_bit(ST_FLITE_IN_USE, &fimc->state);
fimc_lite_stop_capture(fimc, false);
- fimc_pipeline_call(fimc, close, &fimc->pipeline);
+ exynos_pipeline_call(fimc, close, &fimc->pipeline);
clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
}
@@ -801,14 +801,17 @@ static int fimc_lite_streamon(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct fimc_lite *fimc = video_drvdata(file);
- struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR];
- struct fimc_pipeline *p = &fimc->pipeline;
+ struct v4l2_subdev *sensor;
+ struct exynos_pipeline *p = &fimc->pipeline;
int ret;
+ sensor = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline);
+
if (fimc_lite_active(fimc))
return -EBUSY;
- ret = media_entity_pipeline_start(&sensor->entity, p->m_pipeline);
+ ret = media_entity_pipeline_start(&sensor->entity, &p->m_pipeline);
if (ret < 0)
return ret;
@@ -825,9 +828,12 @@ static int fimc_lite_streamoff(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct fimc_lite *fimc = video_drvdata(file);
- struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
+ struct v4l2_subdev *sd;
int ret;
+ sd = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, &fimc->pipeline);
+
ret = vb2_streamoff(&fimc->vb_queue, type);
if (ret == 0)
media_entity_pipeline_stop(&sd->entity);
@@ -976,29 +982,6 @@ static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = {
.vidioc_streamoff = fimc_lite_streamoff,
};
-/* Called with the media graph mutex held */
-static struct v4l2_subdev *__find_remote_sensor(struct media_entity *me)
-{
- struct media_pad *pad = &me->pads[0];
- struct v4l2_subdev *sd;
-
- while (pad->flags & MEDIA_PAD_FL_SINK) {
- /* source pad */
- pad = media_entity_remote_source(pad);
- if (pad == NULL ||
- media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
- break;
-
- sd = media_entity_to_v4l2_subdev(pad->entity);
-
- if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR)
- return sd;
- /* sink pad */
- pad = &sd->entity.pads[0];
- }
- return NULL;
-}
-
/* Capture subdev media entity operations */
static int fimc_lite_link_setup(struct media_entity *entity,
const struct media_pad *local,
@@ -1241,6 +1224,8 @@ static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd,
static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on)
{
struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
+ struct exynos_pipeline *ep;
+ struct exynos_pipeline_ops *ep_ops;
unsigned long flags;
int ret;
@@ -1251,7 +1236,10 @@ static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on)
* The pipeline links are protected through entity.stream_count
* so there is no need to take the media graph mutex here.
*/
- fimc->sensor = __find_remote_sensor(&sd->entity);
+ ep_ops = v4l2_get_subdev_hostdata(sd);
+ ep = media_pipe_to_exynos_pipeline(sd->entity.pipe);
+ fimc->sensor = exynos_pipeline_get_subdev(fimc->pipeline_ops,
+ get_subdev_sensor, ep);
if (atomic_read(&fimc->out_path) != FIMC_IO_ISP)
return -ENOIOCTLCMD;
@@ -1338,6 +1326,7 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
video_set_drvdata(vfd, fimc);
fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd);
+ fimc->pipeline_ops->init(&fimc->pipeline);
ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
@@ -1606,7 +1595,7 @@ static int fimc_lite_resume(struct device *dev)
return 0;
INIT_LIST_HEAD(&fimc->active_buf_q);
- fimc_pipeline_call(fimc, open, &fimc->pipeline,
+ exynos_pipeline_call(fimc, open, &fimc->pipeline,
&fimc->vfd.entity, false);
fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP);
clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
@@ -1633,7 +1622,7 @@ static int fimc_lite_suspend(struct device *dev)
if (ret < 0 || !fimc_lite_active(fimc))
return ret;
- return fimc_pipeline_call(fimc, close, &fimc->pipeline);
+ return exynos_pipeline_call(fimc, close, &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 7085761..66d6eeb 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.h
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.h
@@ -145,8 +145,8 @@ struct fimc_lite {
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *test_pattern;
u32 index;
- struct fimc_pipeline pipeline;
- const struct fimc_pipeline_ops *pipeline_ops;
+ struct exynos_pipeline pipeline;
+ const struct exynos_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 fc93fad..938cc56 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -36,6 +36,8 @@
#include "fimc-mdevice.h"
#include "mipi-csis.h"
+static struct fimc_md *g_fimc_mdev;
+
static int __fimc_md_set_camclk(struct fimc_md *fmd,
struct fimc_sensor_info *s_info,
bool on);
@@ -143,6 +145,73 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
}
/**
+ * __fimc_pipeline_init
+ * allocate the fimc_pipeline structure and do the basic initialization
+ */
+static int __fimc_pipeline_init(struct exynos_pipeline *ep)
+{
+ struct fimc_pipeline *p;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->is_init = true;
+ p->fmd = g_fimc_mdev;
+ ep->priv = (void *)p;
+ return 0;
+}
+
+/**
+ * __fimc_pipeline_deinit
+ * free the allocated resources for fimc_pipeline
+ */
+static int __fimc_pipeline_deinit(struct exynos_pipeline *ep)
+{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
+
+ if (!p || !p->is_init)
+ return -EINVAL;
+
+ p->is_init = false;
+ kfree(p);
+
+ return 0;
+}
+
+/**
+ * __fimc_pipeline_get_subdev_sensor
+ * if valid pipeline, returns the sensor subdev pointer
+ * else returns NULL
+ */
+static struct v4l2_subdev *__fimc_pipeline_get_subdev_sensor(
+ struct exynos_pipeline *ep)
+{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
+
+ if (!p || !p->is_init)
+ return NULL;
+
+ return p->subdevs[IDX_SENSOR];
+}
+
+/**
+ * __fimc_pipeline_get_subdev_csis
+ * if valid pipeline, returns the csis subdev pointer
+ * else returns NULL
+ */
+static struct v4l2_subdev *__fimc_pipeline_get_subdev_csis(
+ struct exynos_pipeline *ep)
+{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
+
+ if (!p || !p->is_init)
+ return NULL;
+
+ return p->subdevs[IDX_CSIS];
+}
+
+/**
* __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
@@ -150,11 +219,15 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
*
* Called with the graph mutex held.
*/
-static int __fimc_pipeline_open(struct fimc_pipeline *p,
+static int __fimc_pipeline_open(struct exynos_pipeline *ep,
struct media_entity *me, bool prep)
{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
int ret;
+ if (!p || !p->is_init)
+ return -EINVAL;
+
if (prep)
fimc_pipeline_prepare(p, me);
@@ -174,17 +247,20 @@ static int __fimc_pipeline_open(struct fimc_pipeline *p,
*
* Disable power of all subdevs and turn the external sensor clock off.
*/
-static int __fimc_pipeline_close(struct fimc_pipeline *p)
+static int __fimc_pipeline_close(struct exynos_pipeline *ep)
{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
int ret = 0;
- if (!p || !p->subdevs[IDX_SENSOR])
+ if (!p || !p->is_init)
return -EINVAL;
- if (p->subdevs[IDX_SENSOR]) {
- ret = fimc_pipeline_s_power(p, 0);
- fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false);
- }
+ if (!p->subdevs[IDX_SENSOR])
+ return -EINVAL;
+
+ ret = fimc_pipeline_s_power(p, 0);
+ fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false);
+
return ret == -ENXIO ? 0 : ret;
}
@@ -193,10 +269,14 @@ static int __fimc_pipeline_close(struct fimc_pipeline *p)
* @pipeline: video pipeline structure
* @on: passed as the s_stream call argument
*/
-static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
+static int __fimc_pipeline_s_stream(struct exynos_pipeline *ep, bool on)
{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
int i, ret;
+ if (!p || !p->is_init)
+ return -EINVAL;
+
if (p->subdevs[IDX_SENSOR] == NULL)
return -ENODEV;
@@ -213,11 +293,47 @@ static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
}
+static void __fimc_pipeline_graph_lock(struct exynos_pipeline *ep)
+{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
+ struct fimc_md *fmd = p->fmd;
+
+ mutex_lock(&fmd->media_dev.graph_mutex);
+}
+
+static void __fimc_pipeline_graph_unlock(struct exynos_pipeline *ep)
+{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
+ struct fimc_md *fmd = p->fmd;
+
+ mutex_unlock(&fmd->media_dev.graph_mutex);
+}
+
+static void __fimc_pipeline_register_notify_callback(
+ struct exynos_pipeline *ep,
+ void (*notify_cb)(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg))
+{
+ struct fimc_pipeline *p = (struct fimc_pipeline *)ep->priv;
+
+ if (!notify_cb)
+ return;
+
+ p->sensor_notify = notify_cb;
+}
+
/* 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,
+static const struct exynos_pipeline_ops fimc_pipeline_ops = {
+ .init = __fimc_pipeline_init,
+ .deinit = __fimc_pipeline_deinit,
+ .open = __fimc_pipeline_open,
+ .close = __fimc_pipeline_close,
+ .set_stream = __fimc_pipeline_s_stream,
+ .get_subdev_sensor = __fimc_pipeline_get_subdev_sensor,
+ .get_subdev_csis = __fimc_pipeline_get_subdev_csis,
+ .graph_lock = __fimc_pipeline_graph_lock,
+ .graph_unlock = __fimc_pipeline_graph_unlock,
+ .register_notify_cb = __fimc_pipeline_register_notify_callback,
};
/*
@@ -769,7 +885,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
if (!WARN_ON(s_info == NULL)) {
unsigned long irq_flags;
spin_lock_irqsave(&fmd->slock, irq_flags);
- s_info->host = fmd->fimc[i];
+ s_info->host = (void *)fmd->fimc[i];
spin_unlock_irqrestore(&fmd->slock, irq_flags);
}
}
@@ -1051,7 +1167,8 @@ static int fimc_md_link_notify(struct media_pad *source,
{
struct fimc_lite *fimc_lite = NULL;
struct fimc_dev *fimc = NULL;
- struct fimc_pipeline *pipeline;
+ struct exynos_pipeline *pipeline;
+ struct fimc_pipeline *p;
struct v4l2_subdev *sd;
struct mutex *lock;
int ret = 0;
@@ -1081,12 +1198,16 @@ static int fimc_md_link_notify(struct media_pad *source,
return 0;
}
+ p = (struct fimc_pipeline *)pipeline->priv;
+ if (!p || !p->is_init)
+ return -EINVAL;
+
if (!(flags & MEDIA_LNK_FL_ENABLED)) {
int i;
mutex_lock(lock);
ret = __fimc_pipeline_close(pipeline);
for (i = 0; i < IDX_MAX; i++)
- pipeline->subdevs[i] = NULL;
+ p->subdevs[i] = NULL;
if (fimc)
fimc_ctrls_delete(fimc->vid_cap.ctx);
mutex_unlock(lock);
@@ -1154,6 +1275,37 @@ static ssize_t fimc_md_sysfs_store(struct device *dev,
static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
fimc_md_sysfs_show, fimc_md_sysfs_store);
+/**
+ * fimc_md_sensor_notify - v4l2_device notification from a sensor subdev
+ * @sd: pointer to a subdev generating the notification
+ * @notification: the notification type, must be S5P_FIMC_TX_END_NOTIFY
+ * @arg: pointer to an u32 type integer that stores the frame payload value
+ *
+ * Passes the sensor notification to the capture device
+ */
+void fimc_md_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
+ void *arg)
+{
+ struct fimc_md *fmd;
+ struct exynos_pipeline *ep;
+ struct fimc_pipeline *p;
+ unsigned long flags;
+
+ if (sd == NULL)
+ return;
+
+ ep = media_pipe_to_exynos_pipeline(sd->entity.pipe);
+ p = (struct fimc_pipeline *)ep->priv;
+
+ spin_lock_irqsave(&fmd->slock, flags);
+
+ if (p->sensor_notify)
+ p->sensor_notify(sd, notification, arg);
+
+ spin_unlock_irqrestore(&fmd->slock, flags);
+}
+
+
static int fimc_md_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1175,7 +1327,7 @@ static int fimc_md_probe(struct platform_device *pdev)
v4l2_dev = &fmd->v4l2_dev;
v4l2_dev->mdev = &fmd->media_dev;
- v4l2_dev->notify = fimc_sensor_notify;
+ v4l2_dev->notify = fimc_md_sensor_notify;
strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
@@ -1194,6 +1346,7 @@ static int fimc_md_probe(struct platform_device *pdev)
goto err_clk;
fmd->user_subdev_api = (dev->of_node != NULL);
+ g_fimc_mdev = fmd;
/* Protect the media graph while we're registering entities */
mutex_lock(&fmd->media_dev.graph_mutex);
@@ -1252,6 +1405,7 @@ static int fimc_md_remove(struct platform_device *pdev)
if (!fmd)
return 0;
+ g_fimc_mdev = NULL;
device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
fimc_md_unregister_entities(fmd);
media_device_unregister(&fmd->media_dev);
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
index f3e0251..1ea7acf 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
@@ -37,6 +37,15 @@
#define FIMC_MAX_SENSORS 8
#define FIMC_MAX_CAMCLKS 2
+enum fimc_subdev_index {
+ IDX_SENSOR,
+ IDX_CSIS,
+ IDX_FLITE,
+ IDX_IS_ISP,
+ IDX_FIMC,
+ IDX_MAX,
+};
+
struct fimc_csis_info {
struct v4l2_subdev *sd;
int id;
@@ -49,20 +58,6 @@ struct fimc_camclk_info {
};
/**
- * struct fimc_sensor_info - image data source subdev information
- * @pdata: sensor's atrributes passed as media device's platform data
- * @subdev: image sensor v4l2 subdev
- * @host: fimc device the sensor is currently linked to
- *
- * This data structure applies to image sensor and the writeback subdevs.
- */
-struct fimc_sensor_info {
- struct fimc_source_info pdata;
- struct v4l2_subdev *subdev;
- struct fimc_dev *host;
-};
-
-/**
* struct fimc_md - fimc media device information
* @csis: MIPI CSIS subdevs data
* @sensor: array of registered sensor subdevs
@@ -89,6 +84,14 @@ struct fimc_md {
spinlock_t slock;
};
+struct fimc_pipeline {
+ int is_init;
+ struct fimc_md *fmd;
+ struct v4l2_subdev *subdevs[IDX_MAX];
+ void (*sensor_notify)(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg);
+};
+
#define is_subdev_pad(pad) (pad == NULL || \
media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
@@ -103,16 +106,6 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
container_of(me->parent, struct fimc_md, media_dev);
}
-static inline void fimc_md_graph_lock(struct fimc_dev *fimc)
-{
- mutex_lock(&fimc->vid_cap.vfd.entity.parent->graph_mutex);
-}
-
-static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
-{
- mutex_unlock(&fimc->vid_cap.vfd.entity.parent->graph_mutex);
-}
-
int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
#endif
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
index e2434bb..007e998 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/s5p_fimc.h
@@ -13,6 +13,7 @@
#define S5P_FIMC_H_
#include <media/media-entity.h>
+#include <media/v4l2-subdev.h>
/*
* Enumeration of data inputs to the camera subsystem.
@@ -75,6 +76,20 @@ struct fimc_source_info {
};
/**
+ * struct fimc_sensor_info - image data source subdev information
+ * @pdata: sensor's atrributes passed as media device's platform data
+ * @subdev: image sensor v4l2 subdev
+ * @host: capture device the sensor is currently linked to
+ *
+ * This data structure applies to image sensor and the writeback subdevs.
+ */
+struct fimc_sensor_info {
+ struct fimc_source_info pdata;
+ struct v4l2_subdev *subdev;
+ void *host;
+};
+
+/**
* struct s5p_platform_fimc - camera host interface platform data
*
* @source_info: properties of an image source for the host interface setup
@@ -93,21 +108,10 @@ struct s5p_platform_fimc {
*/
#define S5P_FIMC_TX_END_NOTIFY _IO('e', 0)
-enum fimc_subdev_index {
- IDX_SENSOR,
- IDX_CSIS,
- IDX_FLITE,
- IDX_IS_ISP,
- IDX_FIMC,
- IDX_MAX,
-};
-
-struct media_pipeline;
-struct v4l2_subdev;
-struct fimc_pipeline {
- struct v4l2_subdev *subdevs[IDX_MAX];
- struct media_pipeline *m_pipeline;
+struct exynos_pipeline {
+ struct media_pipeline m_pipeline;
+ void *priv;
};
/*
@@ -115,15 +119,39 @@ struct fimc_pipeline {
* 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,
+struct exynos_pipeline_ops {
+ int (*init) (struct exynos_pipeline *p);
+ int (*deinit) (struct exynos_pipeline *p);
+ int (*open)(struct exynos_pipeline *p, struct media_entity *me,
bool resume);
- int (*close)(struct fimc_pipeline *p);
- int (*set_stream)(struct fimc_pipeline *p, bool state);
+ int (*close)(struct exynos_pipeline *p);
+ int (*set_stream)(struct exynos_pipeline *p, bool state);
+ void (*graph_lock)(struct exynos_pipeline *p);
+ void (*graph_unlock)(struct exynos_pipeline *p);
+ struct v4l2_subdev *(*get_subdev_sensor)(struct exynos_pipeline *p);
+ struct v4l2_subdev *(*get_subdev_csis)(struct exynos_pipeline *p);
+ void (*register_notify_cb)(struct exynos_pipeline *p,
+ void (*cb)(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg));
+
};
-#define fimc_pipeline_call(f, op, p, args...) \
+#define exynos_pipeline_call(f, op, p, args...) \
(!(f) ? -ENODEV : (((f)->pipeline_ops && (f)->pipeline_ops->op) ? \
(f)->pipeline_ops->op((p), ##args) : -ENOIOCTLCMD))
+#define exynos_pipeline_get_subdev(ops, op, p) \
+ ((ops && ops->op) ? ops->op(p) : NULL)
+
+#define exynos_pipeline_graph_lock(ops, p) \
+ ((ops && ops->graph_lock) ? \
+ ops->graph_lock(p) : -ENOIOCTLCMD)
+
+#define exynos_pipeline_graph_unlock(ops, p) \
+ ((ops && ops->graph_unlock) ? \
+ ops->graph_unlock(p) : -ENOIOCTLCMD)
+
+#define media_pipe_to_exynos_pipeline(mp) \
+ container_of(mp, struct exynos_pipeline, m_pipeline)
+
#endif /* S5P_FIMC_H_ */
--
1.7.9.5
More information about the devicetree-discuss
mailing list