diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-capture.c | 32 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-core.h | 5 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-mdevice.c | 164 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-mdevice.h | 10 |
4 files changed, 123 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 @@ | |||
34 | static int fimc_init_capture(struct fimc_dev *fimc) | 34 | static 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 | ||
287 | static void buffer_queue(struct vb2_buffer *vb); | 288 | static 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 | ||
470 | static int fimc_capture_set_default_format(struct fimc_dev *fimc); | 471 | static 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 | ||
403 | struct fimc_pipeline { | ||
404 | struct media_pipeline *pipe; | ||
405 | struct v4l2_subdev *sensor; | ||
406 | struct v4l2_subdev *csis; | ||
407 | }; | ||
408 | 403 | ||
409 | struct fimc_ctx; | 404 | struct 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 | */ |
40 | void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me) | 41 | void 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 | */ |
92 | int fimc_pipeline_s_power(struct fimc_dev *fimc, int state) | 114 | int 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 | */ |
122 | static int __fimc_pipeline_initialize(struct fimc_dev *fimc, | 141 | static 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 | ||
137 | int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me, | 159 | int 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 | } |
170 | EXPORT_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 | */ |
157 | int __fimc_pipeline_shutdown(struct fimc_dev *fimc) | 180 | int __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 | ||
168 | int fimc_pipeline_shutdown(struct fimc_dev *fimc) | 191 | int 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 | } |
202 | EXPORT_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 | */ |
185 | int fimc_pipeline_s_stream(struct fimc_dev *fimc, int on) | 209 | int 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 | } |
228 | EXPORT_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) | |||
677 | static int fimc_md_link_notify(struct media_pad *source, | 703 | static 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 | ||
111 | int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); | 111 | int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); |
112 | void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me); | 112 | void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me); |
113 | int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me, | 113 | int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me, |
114 | bool resume); | 114 | bool resume); |
115 | int fimc_pipeline_shutdown(struct fimc_dev *fimc); | 115 | int fimc_pipeline_shutdown(struct fimc_pipeline *p); |
116 | int fimc_pipeline_s_power(struct fimc_dev *fimc, int state); | 116 | int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state); |
117 | int fimc_pipeline_s_stream(struct fimc_dev *fimc, int state); | 117 | int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool state); |
118 | 118 | ||
119 | #endif | 119 | #endif |