aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-04-27 08:33:10 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-20 08:22:47 -0400
commit0f735f5236643cbbeb833fa0946bd52c20d00966 (patch)
tree6876c402947a40d1b35c19811e500246ccf19c61
parent2b511edb986fc11b8fa2b5e124c885a99aded257 (diff)
[media] s5p-fimc: Rework the video pipeline control functions
There is getting more entities to manage within single video pipeline in newer SoCs. To simplify code put subdevs' pointer into an array rather than adding new member in struct fimc_pipeline for each subdev. This allows to easier handle subdev operations in proper order. Additionally walk graph in one direction only in fimc_pipeline_prepare() function to make sure we properly gather only media entities that below to single data pipeline. This avoids wrong initialization in case where, for example there are multiple active links from s5p-mipi-csis subdev output pad. struct fimc_pipeline declaration is moved to the driver's public header to allow other drivers to reuse the fimc-lite driver added in subsequent patches. 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/video/s5p-fimc/fimc-capture.c32
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h5
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.c164
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.h10
-rw-r--r--include/media/s5p_fimc.h16
5 files changed, 139 insertions, 88 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 52a5fb469b45..7c884bb7104f 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -34,16 +34,17 @@
34static int fimc_init_capture(struct fimc_dev *fimc) 34static int fimc_init_capture(struct fimc_dev *fimc)
35{ 35{
36 struct fimc_ctx *ctx = fimc->vid_cap.ctx; 36 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
37 struct fimc_pipeline *p = &fimc->pipeline;
37 struct fimc_sensor_info *sensor; 38 struct fimc_sensor_info *sensor;
38 unsigned long flags; 39 unsigned long flags;
39 int ret = 0; 40 int ret = 0;
40 41
41 if (fimc->pipeline.sensor == NULL || ctx == NULL) 42 if (p->subdevs[IDX_SENSOR] == NULL || ctx == NULL)
42 return -ENXIO; 43 return -ENXIO;
43 if (ctx->s_frame.fmt == NULL) 44 if (ctx->s_frame.fmt == NULL)
44 return -EINVAL; 45 return -EINVAL;
45 46
46 sensor = v4l2_get_subdev_hostdata(fimc->pipeline.sensor); 47 sensor = v4l2_get_subdev_hostdata(p->subdevs[IDX_SENSOR]);
47 48
48 spin_lock_irqsave(&fimc->slock, flags); 49 spin_lock_irqsave(&fimc->slock, flags);
49 fimc_prepare_dma_offset(ctx, &ctx->d_frame); 50 fimc_prepare_dma_offset(ctx, &ctx->d_frame);
@@ -109,7 +110,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
109 spin_unlock_irqrestore(&fimc->slock, flags); 110 spin_unlock_irqrestore(&fimc->slock, flags);
110 111
111 if (streaming) 112 if (streaming)
112 return fimc_pipeline_s_stream(fimc, 0); 113 return fimc_pipeline_s_stream(&fimc->pipeline, 0);
113 else 114 else
114 return 0; 115 return 0;
115} 116}
@@ -254,7 +255,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
254 fimc_activate_capture(ctx); 255 fimc_activate_capture(ctx);
255 256
256 if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) 257 if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
257 fimc_pipeline_s_stream(fimc, 1); 258 fimc_pipeline_s_stream(&fimc->pipeline, 1);
258 } 259 }
259 260
260 return 0; 261 return 0;
@@ -281,7 +282,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc)
281 int ret = fimc_stop_capture(fimc, suspend); 282 int ret = fimc_stop_capture(fimc, suspend);
282 if (ret) 283 if (ret)
283 return ret; 284 return ret;
284 return fimc_pipeline_shutdown(fimc); 285 return fimc_pipeline_shutdown(&fimc->pipeline);
285} 286}
286 287
287static void buffer_queue(struct vb2_buffer *vb); 288static void buffer_queue(struct vb2_buffer *vb);
@@ -297,7 +298,7 @@ int fimc_capture_resume(struct fimc_dev *fimc)
297 298
298 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); 299 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
299 vid_cap->buf_index = 0; 300 vid_cap->buf_index = 0;
300 fimc_pipeline_initialize(fimc, &fimc->vid_cap.vfd->entity, 301 fimc_pipeline_initialize(&fimc->pipeline, &vid_cap->vfd->entity,
301 false); 302 false);
302 fimc_init_capture(fimc); 303 fimc_init_capture(fimc);
303 304
@@ -414,7 +415,7 @@ static void buffer_queue(struct vb2_buffer *vb)
414 spin_unlock_irqrestore(&fimc->slock, flags); 415 spin_unlock_irqrestore(&fimc->slock, flags);
415 416
416 if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) 417 if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
417 fimc_pipeline_s_stream(fimc, 1); 418 fimc_pipeline_s_stream(&fimc->pipeline, 1);
418 return; 419 return;
419 } 420 }
420 spin_unlock_irqrestore(&fimc->slock, flags); 421 spin_unlock_irqrestore(&fimc->slock, flags);
@@ -464,7 +465,7 @@ int fimc_capture_ctrls_create(struct fimc_dev *fimc)
464 return ret; 465 return ret;
465 466
466 return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrl_handler, 467 return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrl_handler,
467 fimc->pipeline.sensor->ctrl_handler); 468 fimc->pipeline.subdevs[IDX_SENSOR]->ctrl_handler);
468} 469}
469 470
470static int fimc_capture_set_default_format(struct fimc_dev *fimc); 471static int fimc_capture_set_default_format(struct fimc_dev *fimc);
@@ -487,7 +488,7 @@ static int fimc_capture_open(struct file *file)
487 pm_runtime_get_sync(&fimc->pdev->dev); 488 pm_runtime_get_sync(&fimc->pdev->dev);
488 489
489 if (++fimc->vid_cap.refcnt == 1) { 490 if (++fimc->vid_cap.refcnt == 1) {
490 ret = fimc_pipeline_initialize(fimc, 491 ret = fimc_pipeline_initialize(&fimc->pipeline,
491 &fimc->vid_cap.vfd->entity, true); 492 &fimc->vid_cap.vfd->entity, true);
492 if (ret < 0) { 493 if (ret < 0) {
493 dev_err(&fimc->pdev->dev, 494 dev_err(&fimc->pdev->dev,
@@ -515,7 +516,7 @@ static int fimc_capture_close(struct file *file)
515 if (--fimc->vid_cap.refcnt == 0) { 516 if (--fimc->vid_cap.refcnt == 0) {
516 clear_bit(ST_CAPT_BUSY, &fimc->state); 517 clear_bit(ST_CAPT_BUSY, &fimc->state);
517 fimc_stop_capture(fimc, false); 518 fimc_stop_capture(fimc, false);
518 fimc_pipeline_shutdown(fimc); 519 fimc_pipeline_shutdown(&fimc->pipeline);
519 clear_bit(ST_CAPT_SUSPENDED, &fimc->state); 520 clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
520 } 521 }
521 522
@@ -736,8 +737,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
736 bool set) 737 bool set)
737{ 738{
738 struct fimc_dev *fimc = ctx->fimc_dev; 739 struct fimc_dev *fimc = ctx->fimc_dev;
739 struct v4l2_subdev *sd = fimc->pipeline.sensor; 740 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
740 struct v4l2_subdev *csis = fimc->pipeline.csis; 741 struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
741 struct v4l2_subdev_format sfmt; 742 struct v4l2_subdev_format sfmt;
742 struct v4l2_mbus_framefmt *mf = &sfmt.format; 743 struct v4l2_mbus_framefmt *mf = &sfmt.format;
743 struct fimc_fmt *ffmt = NULL; 744 struct fimc_fmt *ffmt = NULL;
@@ -945,7 +946,7 @@ static int fimc_cap_enum_input(struct file *file, void *priv,
945 struct v4l2_input *i) 946 struct v4l2_input *i)
946{ 947{
947 struct fimc_dev *fimc = video_drvdata(file); 948 struct fimc_dev *fimc = video_drvdata(file);
948 struct v4l2_subdev *sd = fimc->pipeline.sensor; 949 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
949 950
950 if (i->index != 0) 951 if (i->index != 0)
951 return -EINVAL; 952 return -EINVAL;
@@ -1037,7 +1038,8 @@ static int fimc_cap_streamon(struct file *file, void *priv,
1037 if (fimc_capture_active(fimc)) 1038 if (fimc_capture_active(fimc))
1038 return -EBUSY; 1039 return -EBUSY;
1039 1040
1040 media_entity_pipeline_start(&p->sensor->entity, p->pipe); 1041 media_entity_pipeline_start(&p->subdevs[IDX_SENSOR]->entity,
1042 p->m_pipeline);
1041 1043
1042 if (fimc->vid_cap.user_subdev_api) { 1044 if (fimc->vid_cap.user_subdev_api) {
1043 ret = fimc_pipeline_validate(fimc); 1045 ret = fimc_pipeline_validate(fimc);
@@ -1051,7 +1053,7 @@ static int fimc_cap_streamoff(struct file *file, void *priv,
1051 enum v4l2_buf_type type) 1053 enum v4l2_buf_type type)
1052{ 1054{
1053 struct fimc_dev *fimc = video_drvdata(file); 1055 struct fimc_dev *fimc = video_drvdata(file);
1054 struct v4l2_subdev *sd = fimc->pipeline.sensor; 1056 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
1055 int ret; 1057 int ret;
1056 1058
1057 ret = vb2_streamoff(&fimc->vid_cap.vbq, type); 1059 ret = vb2_streamoff(&fimc->vid_cap.vbq, type);
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 34fbba424692..8b073979cee8 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -400,11 +400,6 @@ struct samsung_fimc_driverdata {
400 int num_entities; 400 int num_entities;
401}; 401};
402 402
403struct fimc_pipeline {
404 struct media_pipeline *pipe;
405 struct v4l2_subdev *sensor;
406 struct v4l2_subdev *csis;
407};
408 403
409struct fimc_ctx; 404struct fimc_ctx;
410 405
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
index c319842c762d..212474130dfb 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -25,6 +25,7 @@
25#include <media/media-device.h> 25#include <media/media-device.h>
26 26
27#include "fimc-core.h" 27#include "fimc-core.h"
28#include "fimc-lite.h"
28#include "fimc-mdevice.h" 29#include "fimc-mdevice.h"
29#include "mipi-csis.h" 30#include "mipi-csis.h"
30 31
@@ -37,22 +38,43 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
37 * 38 *
38 * Caller holds the graph mutex. 39 * Caller holds the graph mutex.
39 */ 40 */
40void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me) 41void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me)
41{ 42{
42 struct media_entity_graph graph; 43 struct media_pad *pad = &me->pads[0];
43 struct v4l2_subdev *sd; 44 struct v4l2_subdev *sd;
45 int i;
44 46
45 media_entity_graph_walk_start(&graph, me); 47 for (i = 0; i < IDX_MAX; i++)
48 p->subdevs[i] = NULL;
46 49
47 while ((me = media_entity_graph_walk_next(&graph))) { 50 while (1) {
48 if (media_entity_type(me) != MEDIA_ENT_T_V4L2_SUBDEV) 51 if (!(pad->flags & MEDIA_PAD_FL_SINK))
49 continue; 52 break;
50 sd = media_entity_to_v4l2_subdev(me); 53
54 /* source pad */
55 pad = media_entity_remote_source(pad);
56 if (pad == NULL ||
57 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
58 break;
51 59
52 if (sd->grp_id == SENSOR_GROUP_ID) 60 sd = media_entity_to_v4l2_subdev(pad->entity);
53 fimc->pipeline.sensor = sd; 61
54 else if (sd->grp_id == CSIS_GROUP_ID) 62 switch (sd->grp_id) {
55 fimc->pipeline.csis = sd; 63 case SENSOR_GROUP_ID:
64 p->subdevs[IDX_SENSOR] = sd;
65 break;
66 case CSIS_GROUP_ID:
67 p->subdevs[IDX_CSIS] = sd;
68 break;
69 case FIMC_GROUP_ID:
70 /* No need to control FIMC subdev through subdev ops */
71 break;
72 default:
73 pr_warn("%s: Unknown subdev grp_id: %#x\n",
74 __func__, sd->grp_id);
75 }
76 /* sink pad */
77 pad = &sd->entity.pads[0];
56 } 78 }
57} 79}
58 80
@@ -85,30 +107,27 @@ static int __subdev_set_power(struct v4l2_subdev *sd, int on)
85/** 107/**
86 * fimc_pipeline_s_power - change power state of all pipeline subdevs 108 * fimc_pipeline_s_power - change power state of all pipeline subdevs
87 * @fimc: fimc device terminating the pipeline 109 * @fimc: fimc device terminating the pipeline
88 * @state: 1 to enable power or 0 for power down 110 * @state: true to power on, false to power off
89 * 111 *
90 * Need to be called with the graph mutex held. 112 * Needs to be called with the graph mutex held.
91 */ 113 */
92int fimc_pipeline_s_power(struct fimc_dev *fimc, int state) 114int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
93{ 115{
94 int ret = 0; 116 unsigned int i;
117 int ret;
95 118
96 if (fimc->pipeline.sensor == NULL) 119 if (p->subdevs[IDX_SENSOR] == NULL)
97 return -ENXIO; 120 return -ENXIO;
98 121
99 if (state) { 122 for (i = 0; i < IDX_MAX; i++) {
100 ret = __subdev_set_power(fimc->pipeline.csis, 1); 123 unsigned int idx = state ? (IDX_MAX - 1) - i : i;
101 if (ret && ret != -ENXIO) 124
125 ret = __subdev_set_power(p->subdevs[idx], state);
126 if (ret < 0 && ret != -ENXIO)
102 return ret; 127 return ret;
103 return __subdev_set_power(fimc->pipeline.sensor, 1);
104 } 128 }
105 129
106 ret = __subdev_set_power(fimc->pipeline.sensor, 0); 130 return 0;
107 if (ret)
108 return ret;
109 ret = __subdev_set_power(fimc->pipeline.csis, 0);
110
111 return ret == -ENXIO ? 0 : ret;
112} 131}
113 132
114/** 133/**
@@ -119,32 +138,36 @@ int fimc_pipeline_s_power(struct fimc_dev *fimc, int state)
119 * 138 *
120 * This function must be called with the graph mutex held. 139 * This function must be called with the graph mutex held.
121 */ 140 */
122static int __fimc_pipeline_initialize(struct fimc_dev *fimc, 141static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
123 struct media_entity *me, bool prep) 142 struct media_entity *me, bool prep)
124{ 143{
125 int ret; 144 int ret;
126 145
127 if (prep) 146 if (prep)
128 fimc_pipeline_prepare(fimc, me); 147 fimc_pipeline_prepare(p, me);
129 if (fimc->pipeline.sensor == NULL) 148
149 if (p->subdevs[IDX_SENSOR] == NULL)
130 return -EINVAL; 150 return -EINVAL;
131 ret = fimc_md_set_camclk(fimc->pipeline.sensor, true); 151
152 ret = fimc_md_set_camclk(p->subdevs[IDX_SENSOR], true);
132 if (ret) 153 if (ret)
133 return ret; 154 return ret;
134 return fimc_pipeline_s_power(fimc, 1); 155
156 return fimc_pipeline_s_power(p, 1);
135} 157}
136 158
137int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me, 159int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
138 bool prep) 160 bool prep)
139{ 161{
140 int ret; 162 int ret;
141 163
142 mutex_lock(&me->parent->graph_mutex); 164 mutex_lock(&me->parent->graph_mutex);
143 ret = __fimc_pipeline_initialize(fimc, me, prep); 165 ret = __fimc_pipeline_initialize(p, me, prep);
144 mutex_unlock(&me->parent->graph_mutex); 166 mutex_unlock(&me->parent->graph_mutex);
145 167
146 return ret; 168 return ret;
147} 169}
170EXPORT_SYMBOL_GPL(fimc_pipeline_initialize);
148 171
149/** 172/**
150 * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power 173 * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
@@ -154,52 +177,55 @@ int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me,
154 * sensor clock. 177 * sensor clock.
155 * Called with the graph mutex held. 178 * Called with the graph mutex held.
156 */ 179 */
157int __fimc_pipeline_shutdown(struct fimc_dev *fimc) 180int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
158{ 181{
159 int ret = 0; 182 int ret = 0;
160 183
161 if (fimc->pipeline.sensor) { 184 if (p->subdevs[IDX_SENSOR]) {
162 ret = fimc_pipeline_s_power(fimc, 0); 185 ret = fimc_pipeline_s_power(p, 0);
163 fimc_md_set_camclk(fimc->pipeline.sensor, false); 186 fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false);
164 } 187 }
165 return ret == -ENXIO ? 0 : ret; 188 return ret == -ENXIO ? 0 : ret;
166} 189}
167 190
168int fimc_pipeline_shutdown(struct fimc_dev *fimc) 191int fimc_pipeline_shutdown(struct fimc_pipeline *p)
169{ 192{
170 struct media_entity *me = &fimc->vid_cap.vfd->entity; 193 struct media_entity *me = &p->subdevs[IDX_SENSOR]->entity;
171 int ret; 194 int ret;
172 195
173 mutex_lock(&me->parent->graph_mutex); 196 mutex_lock(&me->parent->graph_mutex);
174 ret = __fimc_pipeline_shutdown(fimc); 197 ret = __fimc_pipeline_shutdown(p);
175 mutex_unlock(&me->parent->graph_mutex); 198 mutex_unlock(&me->parent->graph_mutex);
176 199
177 return ret; 200 return ret;
178} 201}
202EXPORT_SYMBOL_GPL(fimc_pipeline_shutdown);
179 203
180/** 204/**
181 * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs 205 * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs
182 * @fimc: fimc device terminating the pipeline 206 * @pipeline: video pipeline structure
183 * @on: passed as the s_stream call argument 207 * @on: passed as the s_stream call argument
184 */ 208 */
185int fimc_pipeline_s_stream(struct fimc_dev *fimc, int on) 209int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
186{ 210{
187 struct fimc_pipeline *p = &fimc->pipeline; 211 int i, ret;
188 int ret = 0;
189 212
190 if (p->sensor == NULL) 213 if (p->subdevs[IDX_SENSOR] == NULL)
191 return -ENODEV; 214 return -ENODEV;
192 215
193 if ((on && p->csis) || !on) 216 for (i = 0; i < IDX_MAX; i++) {
194 ret = v4l2_subdev_call(on ? p->csis : p->sensor, 217 unsigned int idx = on ? (IDX_MAX - 1) - i : i;
195 video, s_stream, on); 218
196 if (ret < 0 && ret != -ENOIOCTLCMD) 219 ret = v4l2_subdev_call(p->subdevs[idx], video, s_stream, on);
197 return ret; 220
198 if ((!on && p->csis) || on) 221 if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
199 ret = v4l2_subdev_call(on ? p->sensor : p->csis, 222 return ret;
200 video, s_stream, on); 223 }
201 return ret == -ENOIOCTLCMD ? 0 : ret; 224
225 return 0;
226
202} 227}
228EXPORT_SYMBOL_GPL(fimc_pipeline_s_stream);
203 229
204/* 230/*
205 * Sensor subdevice helper functions 231 * Sensor subdevice helper functions
@@ -677,6 +703,7 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
677static int fimc_md_link_notify(struct media_pad *source, 703static int fimc_md_link_notify(struct media_pad *source,
678 struct media_pad *sink, u32 flags) 704 struct media_pad *sink, u32 flags)
679{ 705{
706 struct fimc_pipeline *pipeline;
680 struct v4l2_subdev *sd; 707 struct v4l2_subdev *sd;
681 struct fimc_dev *fimc; 708 struct fimc_dev *fimc;
682 int ret = 0; 709 int ret = 0;
@@ -685,16 +712,26 @@ static int fimc_md_link_notify(struct media_pad *source,
685 return 0; 712 return 0;
686 713
687 sd = media_entity_to_v4l2_subdev(sink->entity); 714 sd = media_entity_to_v4l2_subdev(sink->entity);
688 fimc = v4l2_get_subdevdata(sd);
689 715
690 if (!(flags & MEDIA_LNK_FL_ENABLED)) { 716 switch (sd->grp_id) {
691 ret = __fimc_pipeline_shutdown(fimc); 717 case FIMC_GROUP_ID:
692 fimc->pipeline.sensor = NULL; 718 fimc = v4l2_get_subdevdata(sd);
693 fimc->pipeline.csis = NULL; 719 pipeline = &fimc->pipeline;
720 break;
721 default:
722 return 0;
723 }
694 724
695 mutex_lock(&fimc->lock); 725 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
696 fimc_ctrls_delete(fimc->vid_cap.ctx); 726 ret = __fimc_pipeline_shutdown(pipeline);
697 mutex_unlock(&fimc->lock); 727 pipeline->subdevs[IDX_SENSOR] = NULL;
728 pipeline->subdevs[IDX_CSIS] = NULL;
729
730 if (fimc) {
731 mutex_lock(&fimc->lock);
732 fimc_ctrls_delete(fimc->vid_cap.ctx);
733 mutex_unlock(&fimc->lock);
734 }
698 return ret; 735 return ret;
699 } 736 }
700 /* 737 /*
@@ -704,7 +741,8 @@ static int fimc_md_link_notify(struct media_pad *source,
704 */ 741 */
705 mutex_lock(&fimc->lock); 742 mutex_lock(&fimc->lock);
706 if (fimc->vid_cap.refcnt > 0) { 743 if (fimc->vid_cap.refcnt > 0) {
707 ret = __fimc_pipeline_initialize(fimc, source->entity, true); 744 ret = __fimc_pipeline_initialize(pipeline,
745 source->entity, true);
708 if (!ret) 746 if (!ret)
709 ret = fimc_capture_ctrls_create(fimc); 747 ret = fimc_capture_ctrls_create(fimc);
710 } 748 }
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.h b/drivers/media/video/s5p-fimc/fimc-mdevice.h
index 4f3b69c682cb..c5ac3e64b0d9 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.h
@@ -109,11 +109,11 @@ static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
109} 109}
110 110
111int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); 111int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
112void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me); 112void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me);
113int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me, 113int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
114 bool resume); 114 bool resume);
115int fimc_pipeline_shutdown(struct fimc_dev *fimc); 115int fimc_pipeline_shutdown(struct fimc_pipeline *p);
116int fimc_pipeline_s_power(struct fimc_dev *fimc, int state); 116int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state);
117int fimc_pipeline_s_stream(struct fimc_dev *fimc, int state); 117int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool state);
118 118
119#endif 119#endif
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
index 688fb3f1dc35..8587aaf73646 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/s5p_fimc.h
@@ -64,4 +64,20 @@ struct s5p_platform_fimc {
64 */ 64 */
65#define S5P_FIMC_TX_END_NOTIFY _IO('e', 0) 65#define S5P_FIMC_TX_END_NOTIFY _IO('e', 0)
66 66
67enum fimc_subdev_index {
68 IDX_SENSOR,
69 IDX_CSIS,
70 IDX_FLITE,
71 IDX_FIMC,
72 IDX_MAX,
73};
74
75struct media_pipeline;
76struct v4l2_subdev;
77
78struct fimc_pipeline {
79 struct v4l2_subdev *subdevs[IDX_MAX];
80 struct media_pipeline *m_pipeline;
81};
82
67#endif /* S5P_FIMC_H_ */ 83#endif /* S5P_FIMC_H_ */