aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2013-05-31 10:37:22 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-06-12 20:57:59 -0400
commit403dfbec45419c1838e0ea3be16625986ec17cfd (patch)
tree5098d4c6538bcb6e8044761efb18e81598080e9f
parent4bd728a16ee8212e3e468dabb737fe9ef5cea83d (diff)
[media] exynos4-is: Use common exynos_media_pipeline data structure
This enumeration is now private to exynos4-is and the exynos5 camera subsystem driver may have the subdevs handling designed differently. 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>
-rw-r--r--drivers/media/platform/exynos4-is/fimc-capture.c67
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.h2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.c29
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.h2
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c110
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.h38
-rw-r--r--include/media/s5p_fimc.h53
7 files changed, 187 insertions, 114 deletions
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index b2f9581f1a8a..33c6a2f0ad74 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -120,8 +120,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
120 spin_unlock_irqrestore(&fimc->slock, flags); 120 spin_unlock_irqrestore(&fimc->slock, flags);
121 121
122 if (streaming) 122 if (streaming)
123 return fimc_pipeline_call(fimc, set_stream, 123 return fimc_pipeline_call(&cap->ve, set_stream, 0);
124 &fimc->pipeline, 0);
125 else 124 else
126 return 0; 125 return 0;
127} 126}
@@ -179,8 +178,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
179 178
180void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) 179void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
181{ 180{
182 struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
183 struct fimc_vid_cap *cap = &fimc->vid_cap; 181 struct fimc_vid_cap *cap = &fimc->vid_cap;
182 struct fimc_pipeline *p = to_fimc_pipeline(cap->ve.pipe);
183 struct v4l2_subdev *csis = p->subdevs[IDX_CSIS];
184 struct fimc_frame *f = &cap->ctx->d_frame; 184 struct fimc_frame *f = &cap->ctx->d_frame;
185 struct fimc_vid_buffer *v_buf; 185 struct fimc_vid_buffer *v_buf;
186 struct timeval *tv; 186 struct timeval *tv;
@@ -288,8 +288,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
288 fimc_activate_capture(ctx); 288 fimc_activate_capture(ctx);
289 289
290 if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) 290 if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
291 return fimc_pipeline_call(fimc, set_stream, 291 return fimc_pipeline_call(&vid_cap->ve, set_stream, 1);
292 &fimc->pipeline, 1);
293 } 292 }
294 293
295 return 0; 294 return 0;
@@ -313,7 +312,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc)
313 int ret = fimc_stop_capture(fimc, suspend); 312 int ret = fimc_stop_capture(fimc, suspend);
314 if (ret) 313 if (ret)
315 return ret; 314 return ret;
316 return fimc_pipeline_call(fimc, close, &fimc->pipeline); 315 return fimc_pipeline_call(&fimc->vid_cap.ve, close);
317} 316}
318 317
319static void buffer_queue(struct vb2_buffer *vb); 318static void buffer_queue(struct vb2_buffer *vb);
@@ -330,8 +329,7 @@ int fimc_capture_resume(struct fimc_dev *fimc)
330 329
331 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); 330 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
332 vid_cap->buf_index = 0; 331 vid_cap->buf_index = 0;
333 fimc_pipeline_call(fimc, open, &fimc->pipeline, 332 fimc_pipeline_call(ve, open, &ve->vdev.entity, false);
334 &ve->vdev.entity, false);
335 fimc_capture_hw_init(fimc); 333 fimc_capture_hw_init(fimc);
336 334
337 clear_bit(ST_CAPT_SUSPENDED, &fimc->state); 335 clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
@@ -455,7 +453,7 @@ static void buffer_queue(struct vb2_buffer *vb)
455 if (test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) 453 if (test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
456 return; 454 return;
457 455
458 ret = fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 1); 456 ret = fimc_pipeline_call(ve, set_stream, 1);
459 if (ret < 0) 457 if (ret < 0)
460 v4l2_err(&ve->vdev, "stream on failed: %d\n", ret); 458 v4l2_err(&ve->vdev, "stream on failed: %d\n", ret);
461 return; 459 return;
@@ -503,8 +501,8 @@ static int fimc_capture_open(struct file *file)
503 if (v4l2_fh_is_singular_file(file)) { 501 if (v4l2_fh_is_singular_file(file)) {
504 fimc_md_graph_lock(ve); 502 fimc_md_graph_lock(ve);
505 503
506 ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, 504 ret = fimc_pipeline_call(ve, open, &ve->vdev.entity, true);
507 &fimc->vid_cap.ve.vdev.entity, true); 505
508 if (ret == 0) 506 if (ret == 0)
509 ret = fimc_capture_set_default_format(fimc); 507 ret = fimc_capture_set_default_format(fimc);
510 508
@@ -555,8 +553,7 @@ static int fimc_capture_release(struct file *file)
555 553
556 if (close) { 554 if (close) {
557 clear_bit(ST_CAPT_BUSY, &fimc->state); 555 clear_bit(ST_CAPT_BUSY, &fimc->state);
558 fimc_stop_capture(fimc, false); 556 fimc_pipeline_call(&vc->ve, close);
559 fimc_pipeline_call(fimc, close, &fimc->pipeline);
560 clear_bit(ST_CAPT_SUSPENDED, &fimc->state); 557 clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
561 558
562 fimc_md_graph_lock(&vc->ve); 559 fimc_md_graph_lock(&vc->ve);
@@ -786,7 +783,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
786 bool set) 783 bool set)
787{ 784{
788 struct fimc_dev *fimc = ctx->fimc_dev; 785 struct fimc_dev *fimc = ctx->fimc_dev;
789 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; 786 struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe);
787 struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR];
790 struct v4l2_subdev_format sfmt; 788 struct v4l2_subdev_format sfmt;
791 struct v4l2_mbus_framefmt *mf = &sfmt.format; 789 struct v4l2_mbus_framefmt *mf = &sfmt.format;
792 struct media_entity *me; 790 struct media_entity *me;
@@ -926,6 +924,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
926 struct fimc_ctx *ctx = fimc->vid_cap.ctx; 924 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
927 struct exynos_video_entity *ve = &fimc->vid_cap.ve; 925 struct exynos_video_entity *ve = &fimc->vid_cap.ve;
928 struct v4l2_mbus_framefmt mf; 926 struct v4l2_mbus_framefmt mf;
927 struct v4l2_subdev *sensor;
929 struct fimc_fmt *ffmt = NULL; 928 struct fimc_fmt *ffmt = NULL;
930 int ret = 0; 929 int ret = 0;
931 930
@@ -959,9 +958,18 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
959 958
960 fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); 959 fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
961 960
962 if (ffmt->flags & FMT_FLAGS_COMPRESSED) 961 if (ffmt->flags & FMT_FLAGS_COMPRESSED) {
963 fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], 962 fimc_md_graph_lock(ve);
964 pix->plane_fmt, ffmt->memplanes, true); 963
964 sensor = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR);
965 if (sensor)
966 fimc_get_sensor_frame_desc(sensor, pix->plane_fmt,
967 ffmt->memplanes, true);
968 else
969 ret = -EPIPE;
970
971 fimc_md_graph_unlock(ve);
972 }
965 973
966 return ret; 974 return ret;
967} 975}
@@ -986,6 +994,7 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc,
986 struct fimc_ctx *ctx = fimc->vid_cap.ctx; 994 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
987 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 995 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
988 struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.ci_fmt; 996 struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.ci_fmt;
997 struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe);
989 struct fimc_frame *ff = &ctx->d_frame; 998 struct fimc_frame *ff = &ctx->d_frame;
990 struct fimc_fmt *s_fmt = NULL; 999 struct fimc_fmt *s_fmt = NULL;
991 int ret, i; 1000 int ret, i;
@@ -1027,7 +1036,7 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc,
1027 fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); 1036 fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
1028 1037
1029 if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) { 1038 if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
1030 ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], 1039 ret = fimc_get_sensor_frame_desc(p->subdevs[IDX_SENSOR],
1031 pix->plane_fmt, ff->fmt->memplanes, 1040 pix->plane_fmt, ff->fmt->memplanes,
1032 true); 1041 true);
1033 if (ret < 0) 1042 if (ret < 0)
@@ -1078,14 +1087,20 @@ static int fimc_cap_enum_input(struct file *file, void *priv,
1078 struct v4l2_input *i) 1087 struct v4l2_input *i)
1079{ 1088{
1080 struct fimc_dev *fimc = video_drvdata(file); 1089 struct fimc_dev *fimc = video_drvdata(file);
1081 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; 1090 struct exynos_video_entity *ve = &fimc->vid_cap.ve;
1091 struct v4l2_subdev *sd;
1082 1092
1083 if (i->index != 0) 1093 if (i->index != 0)
1084 return -EINVAL; 1094 return -EINVAL;
1085 1095
1086 i->type = V4L2_INPUT_TYPE_CAMERA; 1096 i->type = V4L2_INPUT_TYPE_CAMERA;
1097 fimc_md_graph_lock(ve);
1098 sd = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR);
1099 fimc_md_graph_unlock(ve);
1100
1087 if (sd) 1101 if (sd)
1088 strlcpy(i->name, sd->name, sizeof(i->name)); 1102 strlcpy(i->name, sd->name, sizeof(i->name));
1103
1089 return 0; 1104 return 0;
1090} 1105}
1091 1106
@@ -1111,6 +1126,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
1111 struct v4l2_subdev_format sink_fmt, src_fmt; 1126 struct v4l2_subdev_format sink_fmt, src_fmt;
1112 struct fimc_vid_cap *vc = &fimc->vid_cap; 1127 struct fimc_vid_cap *vc = &fimc->vid_cap;
1113 struct v4l2_subdev *sd = &vc->subdev; 1128 struct v4l2_subdev *sd = &vc->subdev;
1129 struct fimc_pipeline *p = to_fimc_pipeline(vc->ve.pipe);
1114 struct media_pad *sink_pad, *src_pad; 1130 struct media_pad *sink_pad, *src_pad;
1115 int i, ret; 1131 int i, ret;
1116 1132
@@ -1164,7 +1180,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
1164 src_fmt.format.code != sink_fmt.format.code) 1180 src_fmt.format.code != sink_fmt.format.code)
1165 return -EPIPE; 1181 return -EPIPE;
1166 1182
1167 if (sd == fimc->pipeline.subdevs[IDX_SENSOR] && 1183 if (sd == p->subdevs[IDX_SENSOR] &&
1168 fimc_user_defined_mbus_fmt(src_fmt.format.code)) { 1184 fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
1169 struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES]; 1185 struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
1170 struct fimc_frame *frame = &vc->ctx->d_frame; 1186 struct fimc_frame *frame = &vc->ctx->d_frame;
@@ -1188,7 +1204,6 @@ static int fimc_cap_streamon(struct file *file, void *priv,
1188 enum v4l2_buf_type type) 1204 enum v4l2_buf_type type)
1189{ 1205{
1190 struct fimc_dev *fimc = video_drvdata(file); 1206 struct fimc_dev *fimc = video_drvdata(file);
1191 struct fimc_pipeline *p = &fimc->pipeline;
1192 struct fimc_vid_cap *vc = &fimc->vid_cap; 1207 struct fimc_vid_cap *vc = &fimc->vid_cap;
1193 struct media_entity *entity = &vc->ve.vdev.entity; 1208 struct media_entity *entity = &vc->ve.vdev.entity;
1194 struct fimc_source_info *si = NULL; 1209 struct fimc_source_info *si = NULL;
@@ -1198,11 +1213,11 @@ static int fimc_cap_streamon(struct file *file, void *priv,
1198 if (fimc_capture_active(fimc)) 1213 if (fimc_capture_active(fimc))
1199 return -EBUSY; 1214 return -EBUSY;
1200 1215
1201 ret = media_entity_pipeline_start(entity, p->m_pipeline); 1216 ret = media_entity_pipeline_start(entity, &vc->ve.pipe->mp);
1202 if (ret < 0) 1217 if (ret < 0)
1203 return ret; 1218 return ret;
1204 1219
1205 sd = p->subdevs[IDX_SENSOR]; 1220 sd = __fimc_md_get_subdev(vc->ve.pipe, IDX_SENSOR);
1206 if (sd) 1221 if (sd)
1207 si = v4l2_get_subdev_hostdata(sd); 1222 si = v4l2_get_subdev_hostdata(sd);
1208 1223
@@ -1821,12 +1836,12 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd)
1821 if (ret) 1836 if (ret)
1822 return ret; 1837 return ret;
1823 1838
1824 fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); 1839 fimc->vid_cap.ve.pipe = v4l2_get_subdev_hostdata(sd);
1825 1840
1826 ret = fimc_register_capture_device(fimc, sd->v4l2_dev); 1841 ret = fimc_register_capture_device(fimc, sd->v4l2_dev);
1827 if (ret) { 1842 if (ret) {
1828 fimc_unregister_m2m_device(fimc); 1843 fimc_unregister_m2m_device(fimc);
1829 fimc->pipeline_ops = NULL; 1844 fimc->vid_cap.ve.pipe = NULL;
1830 } 1845 }
1831 1846
1832 return ret; 1847 return ret;
@@ -1847,7 +1862,7 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd)
1847 video_unregister_device(vdev); 1862 video_unregister_device(vdev);
1848 media_entity_cleanup(&vdev->entity); 1863 media_entity_cleanup(&vdev->entity);
1849 fimc_ctrls_delete(fimc->vid_cap.ctx); 1864 fimc_ctrls_delete(fimc->vid_cap.ctx);
1850 fimc->pipeline_ops = NULL; 1865 fimc->vid_cap.ve.pipe = NULL;
1851 } 1866 }
1852 kfree(fimc->vid_cap.ctx); 1867 kfree(fimc->vid_cap.ctx);
1853 fimc->vid_cap.ctx = NULL; 1868 fimc->vid_cap.ctx = NULL;
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
index e3da4ffd7a5e..c48a79254d83 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.h
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -435,8 +435,6 @@ struct fimc_dev {
435 struct fimc_vid_cap vid_cap; 435 struct fimc_vid_cap vid_cap;
436 unsigned long state; 436 unsigned long state;
437 struct vb2_alloc_ctx *alloc_ctx; 437 struct vb2_alloc_ctx *alloc_ctx;
438 struct fimc_pipeline pipeline;
439 const struct fimc_pipeline_ops *pipeline_ops;
440}; 438};
441 439
442/** 440/**
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 0f372bfffaf0..24e2a0f8797a 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -210,7 +210,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
210 if (!streaming) 210 if (!streaming)
211 return 0; 211 return 0;
212 212
213 return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0); 213 return fimc_pipeline_call(&fimc->ve, set_stream, 0);
214} 214}
215 215
216static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend) 216static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend)
@@ -324,8 +324,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
324 flite_hw_capture_start(fimc); 324 flite_hw_capture_start(fimc);
325 325
326 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) 326 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
327 fimc_pipeline_call(fimc, set_stream, 327 fimc_pipeline_call(&fimc->ve, set_stream, 1);
328 &fimc->pipeline, 1);
329 } 328 }
330 if (debug > 0) 329 if (debug > 0)
331 flite_hw_dump_regs(fimc, __func__); 330 flite_hw_dump_regs(fimc, __func__);
@@ -429,8 +428,7 @@ static void buffer_queue(struct vb2_buffer *vb)
429 spin_unlock_irqrestore(&fimc->slock, flags); 428 spin_unlock_irqrestore(&fimc->slock, flags);
430 429
431 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) 430 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
432 fimc_pipeline_call(fimc, set_stream, 431 fimc_pipeline_call(&fimc->ve, set_stream, 1);
433 &fimc->pipeline, 1);
434 return; 432 return;
435 } 433 }
436 spin_unlock_irqrestore(&fimc->slock, flags); 434 spin_unlock_irqrestore(&fimc->slock, flags);
@@ -482,8 +480,7 @@ static int fimc_lite_open(struct file *file)
482 480
483 mutex_lock(&me->parent->graph_mutex); 481 mutex_lock(&me->parent->graph_mutex);
484 482
485 ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, 483 ret = fimc_pipeline_call(&fimc->ve, open, me, true);
486 me, true);
487 484
488 /* Mark video pipeline ending at this video node as in use. */ 485 /* Mark video pipeline ending at this video node as in use. */
489 if (ret == 0) 486 if (ret == 0)
@@ -518,9 +515,10 @@ static int fimc_lite_release(struct file *file)
518 media_entity_pipeline_stop(entity); 515 media_entity_pipeline_stop(entity);
519 fimc->streaming = false; 516 fimc->streaming = false;
520 } 517 }
521 clear_bit(ST_FLITE_IN_USE, &fimc->state);
522 fimc_lite_stop_capture(fimc, false); 518 fimc_lite_stop_capture(fimc, false);
523 fimc_pipeline_call(fimc, close, &fimc->pipeline); 519 fimc_pipeline_call(&fimc->ve, close);
520 clear_bit(ST_FLITE_IN_USE, &fimc->state);
521
524 mutex_lock(&entity->parent->graph_mutex); 522 mutex_lock(&entity->parent->graph_mutex);
525 entity->use_count--; 523 entity->use_count--;
526 mutex_unlock(&entity->parent->graph_mutex); 524 mutex_unlock(&entity->parent->graph_mutex);
@@ -801,13 +799,12 @@ static int fimc_lite_streamon(struct file *file, void *priv,
801{ 799{
802 struct fimc_lite *fimc = video_drvdata(file); 800 struct fimc_lite *fimc = video_drvdata(file);
803 struct media_entity *entity = &fimc->ve.vdev.entity; 801 struct media_entity *entity = &fimc->ve.vdev.entity;
804 struct fimc_pipeline *p = &fimc->pipeline;
805 int ret; 802 int ret;
806 803
807 if (fimc_lite_active(fimc)) 804 if (fimc_lite_active(fimc))
808 return -EBUSY; 805 return -EBUSY;
809 806
810 ret = media_entity_pipeline_start(entity, p->m_pipeline); 807 ret = media_entity_pipeline_start(entity, &fimc->ve.pipe->mp);
811 if (ret < 0) 808 if (ret < 0)
812 return ret; 809 return ret;
813 810
@@ -1282,12 +1279,12 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
1282 return ret; 1279 return ret;
1283 1280
1284 video_set_drvdata(vfd, fimc); 1281 video_set_drvdata(vfd, fimc);
1285 fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); 1282 fimc->ve.pipe = v4l2_get_subdev_hostdata(sd);
1286 1283
1287 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); 1284 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1288 if (ret < 0) { 1285 if (ret < 0) {
1289 media_entity_cleanup(&vfd->entity); 1286 media_entity_cleanup(&vfd->entity);
1290 fimc->pipeline_ops = NULL; 1287 fimc->ve.pipe = NULL;
1291 return ret; 1288 return ret;
1292 } 1289 }
1293 1290
@@ -1306,7 +1303,7 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
1306 if (video_is_registered(&fimc->ve.vdev)) { 1303 if (video_is_registered(&fimc->ve.vdev)) {
1307 video_unregister_device(&fimc->ve.vdev); 1304 video_unregister_device(&fimc->ve.vdev);
1308 media_entity_cleanup(&fimc->ve.vdev.entity); 1305 media_entity_cleanup(&fimc->ve.vdev.entity);
1309 fimc->pipeline_ops = NULL; 1306 fimc->ve.pipe = NULL;
1310 } 1307 }
1311} 1308}
1312 1309
@@ -1552,7 +1549,7 @@ static int fimc_lite_resume(struct device *dev)
1552 return 0; 1549 return 0;
1553 1550
1554 INIT_LIST_HEAD(&fimc->active_buf_q); 1551 INIT_LIST_HEAD(&fimc->active_buf_q);
1555 fimc_pipeline_call(fimc, open, &fimc->pipeline, 1552 fimc_pipeline_call(&fimc->ve, open,
1556 &fimc->ve.vdev.entity, false); 1553 &fimc->ve.vdev.entity, false);
1557 fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP); 1554 fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP);
1558 clear_bit(ST_FLITE_SUSPENDED, &fimc->state); 1555 clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
@@ -1579,7 +1576,7 @@ static int fimc_lite_suspend(struct device *dev)
1579 if (ret < 0 || !fimc_lite_active(fimc)) 1576 if (ret < 0 || !fimc_lite_active(fimc))
1580 return ret; 1577 return ret;
1581 1578
1582 return fimc_pipeline_call(fimc, close, &fimc->pipeline); 1579 return fimc_pipeline_call(&fimc->ve, close);
1583} 1580}
1584#endif /* CONFIG_PM_SLEEP */ 1581#endif /* CONFIG_PM_SLEEP */
1585 1582
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h
index 25abba98d7e9..c7aa08477830 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.h
+++ b/drivers/media/platform/exynos4-is/fimc-lite.h
@@ -140,8 +140,6 @@ struct fimc_lite {
140 struct v4l2_ctrl_handler ctrl_handler; 140 struct v4l2_ctrl_handler ctrl_handler;
141 struct v4l2_ctrl *test_pattern; 141 struct v4l2_ctrl *test_pattern;
142 int index; 142 int index;
143 struct fimc_pipeline pipeline;
144 const struct fimc_pipeline_ops *pipeline_ops;
145 143
146 struct mutex lock; 144 struct mutex lock;
147 spinlock_t slock; 145 spinlock_t slock;
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 1b4bb25d0a55..2020e44f63b1 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -46,7 +46,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
46 * Caller holds the graph mutex. 46 * Caller holds the graph mutex.
47 */ 47 */
48static void fimc_pipeline_prepare(struct fimc_pipeline *p, 48static void fimc_pipeline_prepare(struct fimc_pipeline *p,
49 struct media_entity *me) 49 struct media_entity *me)
50{ 50{
51 struct v4l2_subdev *sd; 51 struct v4l2_subdev *sd;
52 int i; 52 int i;
@@ -168,10 +168,11 @@ error:
168 * 168 *
169 * Called with the graph mutex held. 169 * Called with the graph mutex held.
170 */ 170 */
171static int __fimc_pipeline_open(struct fimc_pipeline *p, 171static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
172 struct media_entity *me, bool prepare) 172 struct media_entity *me, bool prepare)
173{ 173{
174 struct fimc_md *fmd = entity_to_fimc_mdev(me); 174 struct fimc_md *fmd = entity_to_fimc_mdev(me);
175 struct fimc_pipeline *p = to_fimc_pipeline(ep);
175 struct v4l2_subdev *sd; 176 struct v4l2_subdev *sd;
176 int ret; 177 int ret;
177 178
@@ -214,8 +215,9 @@ err_wbclk:
214 * 215 *
215 * Disable power of all subdevs and turn the external sensor clock off. 216 * Disable power of all subdevs and turn the external sensor clock off.
216 */ 217 */
217static int __fimc_pipeline_close(struct fimc_pipeline *p) 218static int __fimc_pipeline_close(struct exynos_media_pipeline *ep)
218{ 219{
220 struct fimc_pipeline *p = to_fimc_pipeline(ep);
219 struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL; 221 struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL;
220 struct fimc_md *fmd; 222 struct fimc_md *fmd;
221 int ret = 0; 223 int ret = 0;
@@ -242,12 +244,13 @@ static int __fimc_pipeline_close(struct fimc_pipeline *p)
242 * @pipeline: video pipeline structure 244 * @pipeline: video pipeline structure
243 * @on: passed as the s_stream() callback argument 245 * @on: passed as the s_stream() callback argument
244 */ 246 */
245static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) 247static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
246{ 248{
247 static const u8 seq[2][IDX_MAX] = { 249 static const u8 seq[2][IDX_MAX] = {
248 { IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE }, 250 { IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE },
249 { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP }, 251 { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP },
250 }; 252 };
253 struct fimc_pipeline *p = to_fimc_pipeline(ep);
251 int i, ret = 0; 254 int i, ret = 0;
252 255
253 if (p->subdevs[IDX_SENSOR] == NULL) 256 if (p->subdevs[IDX_SENSOR] == NULL)
@@ -271,12 +274,38 @@ error:
271} 274}
272 275
273/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */ 276/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */
274static const struct fimc_pipeline_ops fimc_pipeline_ops = { 277static const struct exynos_media_pipeline_ops fimc_pipeline_ops = {
275 .open = __fimc_pipeline_open, 278 .open = __fimc_pipeline_open,
276 .close = __fimc_pipeline_close, 279 .close = __fimc_pipeline_close,
277 .set_stream = __fimc_pipeline_s_stream, 280 .set_stream = __fimc_pipeline_s_stream,
278}; 281};
279 282
283static struct exynos_media_pipeline *fimc_md_pipeline_create(
284 struct fimc_md *fmd)
285{
286 struct fimc_pipeline *p;
287
288 p = kzalloc(sizeof(*p), GFP_KERNEL);
289 if (!p)
290 return NULL;
291
292 list_add_tail(&p->list, &fmd->pipelines);
293
294 p->ep.ops = &fimc_pipeline_ops;
295 return &p->ep;
296}
297
298static void fimc_md_pipelines_free(struct fimc_md *fmd)
299{
300 while (!list_empty(&fmd->pipelines)) {
301 struct fimc_pipeline *p;
302
303 p = list_entry(fmd->pipelines.next, typeof(*p), list);
304 list_del(&p->list);
305 kfree(p);
306 }
307}
308
280/* 309/*
281 * Sensor subdevice helper functions 310 * Sensor subdevice helper functions
282 */ 311 */
@@ -592,6 +621,7 @@ static int register_fimc_lite_entity(struct fimc_md *fmd,
592 struct fimc_lite *fimc_lite) 621 struct fimc_lite *fimc_lite)
593{ 622{
594 struct v4l2_subdev *sd; 623 struct v4l2_subdev *sd;
624 struct exynos_media_pipeline *ep;
595 int ret; 625 int ret;
596 626
597 if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS || 627 if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS ||
@@ -600,7 +630,12 @@ static int register_fimc_lite_entity(struct fimc_md *fmd,
600 630
601 sd = &fimc_lite->subdev; 631 sd = &fimc_lite->subdev;
602 sd->grp_id = GRP_ID_FLITE; 632 sd->grp_id = GRP_ID_FLITE;
603 v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); 633
634 ep = fimc_md_pipeline_create(fmd);
635 if (!ep)
636 return -ENOMEM;
637
638 v4l2_set_subdev_hostdata(sd, ep);
604 639
605 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); 640 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
606 if (!ret) 641 if (!ret)
@@ -614,6 +649,7 @@ static int register_fimc_lite_entity(struct fimc_md *fmd,
614static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) 649static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc)
615{ 650{
616 struct v4l2_subdev *sd; 651 struct v4l2_subdev *sd;
652 struct exynos_media_pipeline *ep;
617 int ret; 653 int ret;
618 654
619 if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id])) 655 if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id]))
@@ -621,7 +657,12 @@ static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc)
621 657
622 sd = &fimc->vid_cap.subdev; 658 sd = &fimc->vid_cap.subdev;
623 sd->grp_id = GRP_ID_FIMC; 659 sd->grp_id = GRP_ID_FIMC;
624 v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); 660
661 ep = fimc_md_pipeline_create(fmd);
662 if (!ep)
663 return -ENOMEM;
664
665 v4l2_set_subdev_hostdata(sd, ep);
625 666
626 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); 667 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
627 if (!ret) { 668 if (!ret) {
@@ -797,17 +838,19 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
797 int i; 838 int i;
798 839
799 for (i = 0; i < FIMC_MAX_DEVS; i++) { 840 for (i = 0; i < FIMC_MAX_DEVS; i++) {
800 if (fmd->fimc[i] == NULL) 841 struct fimc_dev *dev = fmd->fimc[i];
842 if (dev == NULL)
801 continue; 843 continue;
802 v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev); 844 v4l2_device_unregister_subdev(&dev->vid_cap.subdev);
803 fmd->fimc[i]->pipeline_ops = NULL; 845 dev->vid_cap.ve.pipe = NULL;
804 fmd->fimc[i] = NULL; 846 fmd->fimc[i] = NULL;
805 } 847 }
806 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { 848 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
807 if (fmd->fimc_lite[i] == NULL) 849 struct fimc_lite *dev = fmd->fimc_lite[i];
850 if (dev == NULL)
808 continue; 851 continue;
809 v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev); 852 v4l2_device_unregister_subdev(&dev->subdev);
810 fmd->fimc_lite[i]->pipeline_ops = NULL; 853 dev->ve.pipe = NULL;
811 fmd->fimc_lite[i] = NULL; 854 fmd->fimc_lite[i] = NULL;
812 } 855 }
813 for (i = 0; i < CSIS_MAX_ENTITIES; i++) { 856 for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
@@ -1234,38 +1277,22 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
1234static int fimc_md_link_notify(struct media_pad *source, 1277static int fimc_md_link_notify(struct media_pad *source,
1235 struct media_pad *sink, u32 flags) 1278 struct media_pad *sink, u32 flags)
1236{ 1279{
1237 struct fimc_lite *fimc_lite = NULL; 1280 struct exynos_video_entity *ve;
1238 struct fimc_dev *fimc = NULL; 1281 struct video_device *vdev;
1239 struct fimc_pipeline *pipeline; 1282 struct fimc_pipeline *pipeline;
1240 struct v4l2_subdev *sd;
1241 int i, ret = 0; 1283 int i, ret = 0;
1242 1284
1243 if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) 1285 if (media_entity_type(sink->entity) != MEDIA_ENT_T_DEVNODE_V4L)
1244 return 0; 1286 return 0;
1245 1287
1246 sd = media_entity_to_v4l2_subdev(sink->entity); 1288 vdev = media_entity_to_video_device(sink->entity);
1247 1289 ve = vdev_to_exynos_video_entity(vdev);
1248 switch (sd->grp_id) { 1290 pipeline = to_fimc_pipeline(ve->pipe);
1249 case GRP_ID_FLITE: 1291
1250 fimc_lite = v4l2_get_subdevdata(sd); 1292 if (!(flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) {
1251 if (WARN_ON(fimc_lite == NULL)) 1293 if (sink->entity->use_count > 0)
1252 return 0; 1294 ret = __fimc_pipeline_close(ve->pipe);
1253 pipeline = &fimc_lite->pipeline;
1254 break;
1255 case GRP_ID_FIMC:
1256 fimc = v4l2_get_subdevdata(sd);
1257 if (WARN_ON(fimc == NULL))
1258 return 0;
1259 pipeline = &fimc->pipeline;
1260 break;
1261 default:
1262 return 0;
1263 }
1264 1295
1265 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1266 if (sink->entity->use_count > 0) {
1267 ret = __fimc_pipeline_close(pipeline);
1268 }
1269 for (i = 0; i < IDX_MAX; i++) 1296 for (i = 0; i < IDX_MAX; i++)
1270 pipeline->subdevs[i] = NULL; 1297 pipeline->subdevs[i] = NULL;
1271 } else if (sink->entity->use_count > 0) { 1298 } else if (sink->entity->use_count > 0) {
@@ -1274,8 +1301,7 @@ static int fimc_md_link_notify(struct media_pad *source,
1274 * the pipeline is already in use, i.e. its video node is open. 1301 * the pipeline is already in use, i.e. its video node is open.
1275 * Recreate the controls destroyed during the link deactivation. 1302 * Recreate the controls destroyed during the link deactivation.
1276 */ 1303 */
1277 ret = __fimc_pipeline_open(pipeline, 1304 ret = __fimc_pipeline_open(ve->pipe, sink->entity, true);
1278 source->entity, true);
1279 } 1305 }
1280 1306
1281 return ret ? -EPIPE : ret; 1307 return ret ? -EPIPE : ret;
@@ -1358,6 +1384,7 @@ static int fimc_md_probe(struct platform_device *pdev)
1358 1384
1359 spin_lock_init(&fmd->slock); 1385 spin_lock_init(&fmd->slock);
1360 fmd->pdev = pdev; 1386 fmd->pdev = pdev;
1387 INIT_LIST_HEAD(&fmd->pipelines);
1361 1388
1362 strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", 1389 strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
1363 sizeof(fmd->media_dev.model)); 1390 sizeof(fmd->media_dev.model));
@@ -1445,6 +1472,7 @@ static int fimc_md_remove(struct platform_device *pdev)
1445 return 0; 1472 return 0;
1446 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); 1473 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1447 fimc_md_unregister_entities(fmd); 1474 fimc_md_unregister_entities(fmd);
1475 fimc_md_pipelines_free(fmd);
1448 media_device_unregister(&fmd->media_dev); 1476 media_device_unregister(&fmd->media_dev);
1449 fimc_md_put_clocks(fmd); 1477 fimc_md_put_clocks(fmd);
1450 return 0; 1478 return 0;
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 3e9680c9de8b..a704eea2cfbd 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -18,6 +18,7 @@
18#include <media/media-entity.h> 18#include <media/media-entity.h>
19#include <media/v4l2-device.h> 19#include <media/v4l2-device.h>
20#include <media/v4l2-subdev.h> 20#include <media/v4l2-subdev.h>
21#include <media/s5p_fimc.h>
21 22
22#include "fimc-core.h" 23#include "fimc-core.h"
23#include "fimc-lite.h" 24#include "fimc-lite.h"
@@ -40,6 +41,29 @@ enum {
40 FIMC_MAX_WBCLKS 41 FIMC_MAX_WBCLKS
41}; 42};
42 43
44enum fimc_subdev_index {
45 IDX_SENSOR,
46 IDX_CSIS,
47 IDX_FLITE,
48 IDX_IS_ISP,
49 IDX_FIMC,
50 IDX_MAX,
51};
52
53/*
54 * This structure represents a chain of media entities, including a data
55 * source entity (e.g. an image sensor subdevice), a data capture entity
56 * - a video capture device node and any remaining entities.
57 */
58struct fimc_pipeline {
59 struct exynos_media_pipeline ep;
60 struct list_head list;
61 struct media_entity *vdev_entity;
62 struct v4l2_subdev *subdevs[IDX_MAX];
63};
64
65#define to_fimc_pipeline(_ep) container_of(_ep, struct fimc_pipeline, ep)
66
43struct fimc_csis_info { 67struct fimc_csis_info {
44 struct v4l2_subdev *sd; 68 struct v4l2_subdev *sd;
45 int id; 69 int id;
@@ -104,7 +128,9 @@ struct fimc_md {
104 struct pinctrl_state *state_idle; 128 struct pinctrl_state *state_idle;
105 } pinctl; 129 } pinctl;
106 bool user_subdev_api; 130 bool user_subdev_api;
131
107 spinlock_t slock; 132 spinlock_t slock;
133 struct list_head pipelines;
108}; 134};
109 135
110#define is_subdev_pad(pad) (pad == NULL || \ 136#define is_subdev_pad(pad) (pad == NULL || \
@@ -149,4 +175,16 @@ static inline bool fimc_md_is_isp_available(struct device_node *node)
149#define fimc_md_is_isp_available(node) (false) 175#define fimc_md_is_isp_available(node) (false)
150#endif /* CONFIG_OF */ 176#endif /* CONFIG_OF */
151 177
178static inline struct v4l2_subdev *__fimc_md_get_subdev(
179 struct exynos_media_pipeline *ep,
180 unsigned int index)
181{
182 struct fimc_pipeline *p = to_fimc_pipeline(ep);
183
184 if (!p || index >= IDX_MAX)
185 return NULL;
186 else
187 return p->subdevs[index];
188}
189
152#endif 190#endif
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
index f5313b402eb7..0afadb663bbd 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/s5p_fimc.h
@@ -141,41 +141,40 @@ struct fimc_fmt {
141#define FMT_FLAGS_YUV (1 << 7) 141#define FMT_FLAGS_YUV (1 << 7)
142}; 142};
143 143
144enum fimc_subdev_index { 144struct exynos_media_pipeline;
145 IDX_SENSOR,
146 IDX_CSIS,
147 IDX_FLITE,
148 IDX_IS_ISP,
149 IDX_FIMC,
150 IDX_MAX,
151};
152
153struct media_pipeline;
154struct v4l2_subdev;
155 145
156struct fimc_pipeline { 146/*
157 struct v4l2_subdev *subdevs[IDX_MAX]; 147 * Media pipeline operations to be called from within a video node, i.e. the
158 struct media_pipeline *m_pipeline; 148 * last entity within the pipeline. Implemented by related media device driver.
149 */
150struct exynos_media_pipeline_ops {
151 int (*prepare)(struct exynos_media_pipeline *p,
152 struct media_entity *me);
153 int (*unprepare)(struct exynos_media_pipeline *p);
154 int (*open)(struct exynos_media_pipeline *p, struct media_entity *me,
155 bool resume);
156 int (*close)(struct exynos_media_pipeline *p);
157 int (*set_stream)(struct exynos_media_pipeline *p, bool state);
159}; 158};
160 159
161struct exynos_video_entity { 160struct exynos_video_entity {
162 struct video_device vdev; 161 struct video_device vdev;
162 struct exynos_media_pipeline *pipe;
163}; 163};
164 164
165/* 165struct exynos_media_pipeline {
166 * Media pipeline operations to be called from within the fimc(-lite) 166 struct media_pipeline mp;
167 * video node when it is the last entity of the pipeline. Implemented 167 const struct exynos_media_pipeline_ops *ops;
168 * by corresponding media device driver.
169 */
170struct fimc_pipeline_ops {
171 int (*open)(struct fimc_pipeline *p, struct media_entity *me,
172 bool resume);
173 int (*close)(struct fimc_pipeline *p);
174 int (*set_stream)(struct fimc_pipeline *p, bool state);
175}; 168};
176 169
177#define fimc_pipeline_call(f, op, p, args...) \ 170static inline struct exynos_video_entity *vdev_to_exynos_video_entity(
178 (!(f) ? -ENODEV : (((f)->pipeline_ops && (f)->pipeline_ops->op) ? \ 171 struct video_device *vdev)
179 (f)->pipeline_ops->op((p), ##args) : -ENOIOCTLCMD)) 172{
173 return container_of(vdev, struct exynos_video_entity, vdev);
174}
175
176#define fimc_pipeline_call(ent, op, args...) \
177 (!(ent) ? -ENOENT : (((ent)->pipe->ops && (ent)->pipe->ops->op) ? \
178 (ent)->pipe->ops->op(((ent)->pipe), ##args) : -ENOIOCTLCMD)) \
180 179
181#endif /* S5P_FIMC_H_ */ 180#endif /* S5P_FIMC_H_ */