diff options
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-capture.c')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-capture.c | 118 |
1 files changed, 54 insertions, 64 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 32c285489be7..f0fed6124dc0 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c | |||
@@ -68,7 +68,7 @@ static int fimc_init_capture(struct fimc_dev *fimc) | |||
68 | return ret; | 68 | return ret; |
69 | } | 69 | } |
70 | 70 | ||
71 | static void fimc_capture_state_cleanup(struct fimc_dev *fimc) | 71 | static int fimc_capture_state_cleanup(struct fimc_dev *fimc) |
72 | { | 72 | { |
73 | struct fimc_vid_cap *cap = &fimc->vid_cap; | 73 | struct fimc_vid_cap *cap = &fimc->vid_cap; |
74 | struct fimc_vid_buffer *buf; | 74 | struct fimc_vid_buffer *buf; |
@@ -76,7 +76,8 @@ static void fimc_capture_state_cleanup(struct fimc_dev *fimc) | |||
76 | 76 | ||
77 | spin_lock_irqsave(&fimc->slock, flags); | 77 | spin_lock_irqsave(&fimc->slock, flags); |
78 | fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND | | 78 | fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND | |
79 | 1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM); | 79 | 1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM | |
80 | 1 << ST_CAPT_ISP_STREAM); | ||
80 | 81 | ||
81 | fimc->vid_cap.active_buf_cnt = 0; | 82 | fimc->vid_cap.active_buf_cnt = 0; |
82 | 83 | ||
@@ -92,6 +93,11 @@ static void fimc_capture_state_cleanup(struct fimc_dev *fimc) | |||
92 | } | 93 | } |
93 | 94 | ||
94 | spin_unlock_irqrestore(&fimc->slock, flags); | 95 | spin_unlock_irqrestore(&fimc->slock, flags); |
96 | |||
97 | if (test_bit(ST_CAPT_ISP_STREAM, &fimc->state)) | ||
98 | return fimc_pipeline_s_stream(fimc, 0); | ||
99 | else | ||
100 | return 0; | ||
95 | } | 101 | } |
96 | 102 | ||
97 | static int fimc_stop_capture(struct fimc_dev *fimc) | 103 | static int fimc_stop_capture(struct fimc_dev *fimc) |
@@ -111,11 +117,7 @@ static int fimc_stop_capture(struct fimc_dev *fimc) | |||
111 | !test_bit(ST_CAPT_SHUT, &fimc->state), | 117 | !test_bit(ST_CAPT_SHUT, &fimc->state), |
112 | FIMC_SHUTDOWN_TIMEOUT); | 118 | FIMC_SHUTDOWN_TIMEOUT); |
113 | 119 | ||
114 | v4l2_subdev_call(cap->sd, video, s_stream, 0); | 120 | return fimc_capture_state_cleanup(fimc); |
115 | |||
116 | fimc_capture_state_cleanup(fimc); | ||
117 | dbg("state: 0x%lx", fimc->state); | ||
118 | return 0; | ||
119 | } | 121 | } |
120 | 122 | ||
121 | 123 | ||
@@ -138,9 +140,14 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) | |||
138 | 140 | ||
139 | min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1; | 141 | min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1; |
140 | 142 | ||
141 | if (fimc->vid_cap.active_buf_cnt >= min_bufs) | 143 | if (vid_cap->active_buf_cnt >= min_bufs && |
144 | !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) { | ||
142 | fimc_activate_capture(ctx); | 145 | fimc_activate_capture(ctx); |
143 | 146 | ||
147 | if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) | ||
148 | fimc_pipeline_s_stream(fimc, 1); | ||
149 | } | ||
150 | |||
144 | return 0; | 151 | return 0; |
145 | error: | 152 | error: |
146 | fimc_capture_state_cleanup(fimc); | 153 | fimc_capture_state_cleanup(fimc); |
@@ -202,11 +209,11 @@ static int buffer_prepare(struct vb2_buffer *vb) | |||
202 | struct fimc_ctx *ctx = vq->drv_priv; | 209 | struct fimc_ctx *ctx = vq->drv_priv; |
203 | int i; | 210 | int i; |
204 | 211 | ||
205 | if (!ctx->d_frame.fmt || vq->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | 212 | if (ctx->d_frame.fmt == NULL) |
206 | return -EINVAL; | 213 | return -EINVAL; |
207 | 214 | ||
208 | for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) { | 215 | for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) { |
209 | unsigned long size = get_plane_size(&ctx->d_frame, i); | 216 | unsigned long size = ctx->d_frame.payload[i]; |
210 | 217 | ||
211 | if (vb2_plane_size(vb, i) < size) { | 218 | if (vb2_plane_size(vb, i) < size) { |
212 | v4l2_err(ctx->fimc_dev->vid_cap.vfd, | 219 | v4l2_err(ctx->fimc_dev->vid_cap.vfd, |
@@ -214,7 +221,6 @@ static int buffer_prepare(struct vb2_buffer *vb) | |||
214 | vb2_plane_size(vb, i), size); | 221 | vb2_plane_size(vb, i), size); |
215 | return -EINVAL; | 222 | return -EINVAL; |
216 | } | 223 | } |
217 | |||
218 | vb2_set_plane_payload(vb, i, size); | 224 | vb2_set_plane_payload(vb, i, size); |
219 | } | 225 | } |
220 | 226 | ||
@@ -223,10 +229,10 @@ static int buffer_prepare(struct vb2_buffer *vb) | |||
223 | 229 | ||
224 | static void buffer_queue(struct vb2_buffer *vb) | 230 | static void buffer_queue(struct vb2_buffer *vb) |
225 | { | 231 | { |
226 | struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
227 | struct fimc_dev *fimc = ctx->fimc_dev; | ||
228 | struct fimc_vid_buffer *buf | 232 | struct fimc_vid_buffer *buf |
229 | = container_of(vb, struct fimc_vid_buffer, vb); | 233 | = container_of(vb, struct fimc_vid_buffer, vb); |
234 | struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
235 | struct fimc_dev *fimc = ctx->fimc_dev; | ||
230 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; | 236 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; |
231 | unsigned long flags; | 237 | unsigned long flags; |
232 | int min_bufs; | 238 | int min_bufs; |
@@ -252,11 +258,17 @@ static void buffer_queue(struct vb2_buffer *vb) | |||
252 | 258 | ||
253 | min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1; | 259 | min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1; |
254 | 260 | ||
261 | |||
255 | if (vb2_is_streaming(&vid_cap->vbq) && | 262 | if (vb2_is_streaming(&vid_cap->vbq) && |
256 | vid_cap->active_buf_cnt >= min_bufs && | 263 | vid_cap->active_buf_cnt >= min_bufs && |
257 | !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) | 264 | !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) { |
258 | fimc_activate_capture(ctx); | 265 | fimc_activate_capture(ctx); |
266 | spin_unlock_irqrestore(&fimc->slock, flags); | ||
259 | 267 | ||
268 | if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) | ||
269 | fimc_pipeline_s_stream(fimc, 1); | ||
270 | return; | ||
271 | } | ||
260 | spin_unlock_irqrestore(&fimc->slock, flags); | 272 | spin_unlock_irqrestore(&fimc->slock, flags); |
261 | } | 273 | } |
262 | 274 | ||
@@ -321,15 +333,21 @@ static int fimc_capture_open(struct file *file) | |||
321 | if (fimc_m2m_active(fimc)) | 333 | if (fimc_m2m_active(fimc)) |
322 | return -EBUSY; | 334 | return -EBUSY; |
323 | 335 | ||
324 | ret = pm_runtime_get_sync(&fimc->pdev->dev); | 336 | pm_runtime_get_sync(&fimc->pdev->dev); |
325 | if (ret < 0) { | 337 | |
326 | v4l2_fh_release(file); | 338 | if (++fimc->vid_cap.refcnt == 1) { |
327 | return ret; | 339 | ret = fimc_pipeline_initialize(fimc, |
328 | } | 340 | &fimc->vid_cap.vfd->entity, true); |
329 | 341 | if (ret < 0) { | |
330 | if (++fimc->vid_cap.refcnt == 1) | 342 | dev_err(&fimc->pdev->dev, |
343 | "Video pipeline initialization failed\n"); | ||
344 | pm_runtime_put_sync(&fimc->pdev->dev); | ||
345 | fimc->vid_cap.refcnt--; | ||
346 | v4l2_fh_release(file); | ||
347 | return ret; | ||
348 | } | ||
331 | ret = fimc_capture_ctrls_create(fimc); | 349 | ret = fimc_capture_ctrls_create(fimc); |
332 | 350 | } | |
333 | return ret; | 351 | return ret; |
334 | } | 352 | } |
335 | 353 | ||
@@ -341,6 +359,7 @@ static int fimc_capture_close(struct file *file) | |||
341 | 359 | ||
342 | if (--fimc->vid_cap.refcnt == 0) { | 360 | if (--fimc->vid_cap.refcnt == 0) { |
343 | fimc_stop_capture(fimc); | 361 | fimc_stop_capture(fimc); |
362 | fimc_pipeline_shutdown(fimc); | ||
344 | fimc_ctrls_delete(fimc->vid_cap.ctx); | 363 | fimc_ctrls_delete(fimc->vid_cap.ctx); |
345 | vb2_queue_release(&fimc->vid_cap.vbq); | 364 | vb2_queue_release(&fimc->vid_cap.vbq); |
346 | } | 365 | } |
@@ -405,41 +424,11 @@ static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv, | |||
405 | return 0; | 424 | return 0; |
406 | } | 425 | } |
407 | 426 | ||
408 | /* Synchronize formats of the camera interface input and attached sensor. */ | ||
409 | static int sync_capture_fmt(struct fimc_ctx *ctx) | ||
410 | { | ||
411 | struct fimc_frame *frame = &ctx->s_frame; | ||
412 | struct fimc_dev *fimc = ctx->fimc_dev; | ||
413 | struct v4l2_mbus_framefmt *fmt = &fimc->vid_cap.fmt; | ||
414 | int ret; | ||
415 | 427 | ||
416 | fmt->width = ctx->d_frame.o_width; | ||
417 | fmt->height = ctx->d_frame.o_height; | ||
418 | 428 | ||
419 | ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_mbus_fmt, fmt); | ||
420 | if (ret == -ENOIOCTLCMD) { | ||
421 | err("s_mbus_fmt failed"); | ||
422 | return ret; | ||
423 | } | ||
424 | dbg("w: %d, h: %d, code= %d", fmt->width, fmt->height, fmt->code); | ||
425 | 429 | ||
426 | frame->fmt = fimc_find_format(NULL, &fmt->code, FMT_FLAGS_CAM, -1); | ||
427 | if (!frame->fmt) { | ||
428 | err("fimc source format not found\n"); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | 430 | ||
432 | frame->f_width = fmt->width; | ||
433 | frame->f_height = fmt->height; | ||
434 | frame->width = fmt->width; | ||
435 | frame->height = fmt->height; | ||
436 | frame->o_width = fmt->width; | ||
437 | frame->o_height = fmt->height; | ||
438 | frame->offs_h = 0; | ||
439 | frame->offs_v = 0; | ||
440 | 431 | ||
441 | return 0; | ||
442 | } | ||
443 | 432 | ||
444 | static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, | 433 | static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, |
445 | struct v4l2_format *f) | 434 | struct v4l2_format *f) |
@@ -459,7 +448,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, | |||
459 | struct fimc_dev *fimc = video_drvdata(file); | 448 | struct fimc_dev *fimc = video_drvdata(file); |
460 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; | 449 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; |
461 | 450 | ||
462 | return fimc_try_fmt_mplane(ctx, f); | 451 | return 0; |
463 | } | 452 | } |
464 | 453 | ||
465 | static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, | 454 | static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, |
@@ -475,10 +464,6 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, | |||
475 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | 464 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
476 | return -EINVAL; | 465 | return -EINVAL; |
477 | 466 | ||
478 | ret = fimc_try_fmt_mplane(ctx, f); | ||
479 | if (ret) | ||
480 | return ret; | ||
481 | |||
482 | if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc)) | 467 | if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc)) |
483 | return -EBUSY; | 468 | return -EBUSY; |
484 | 469 | ||
@@ -508,7 +493,6 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, | |||
508 | 493 | ||
509 | ctx->state |= (FIMC_PARAMS | FIMC_DST_FMT); | 494 | ctx->state |= (FIMC_PARAMS | FIMC_DST_FMT); |
510 | 495 | ||
511 | ret = sync_capture_fmt(ctx); | ||
512 | return ret; | 496 | return ret; |
513 | } | 497 | } |
514 | 498 | ||
@@ -516,12 +500,14 @@ static int fimc_cap_enum_input(struct file *file, void *priv, | |||
516 | struct v4l2_input *i) | 500 | struct v4l2_input *i) |
517 | { | 501 | { |
518 | struct fimc_dev *fimc = video_drvdata(file); | 502 | struct fimc_dev *fimc = video_drvdata(file); |
503 | struct v4l2_subdev *sd = fimc->pipeline.sensor; | ||
519 | 504 | ||
520 | if (i->index != 0) | 505 | if (i->index != 0) |
521 | return -EINVAL; | 506 | return -EINVAL; |
522 | 507 | ||
523 | |||
524 | i->type = V4L2_INPUT_TYPE_CAMERA; | 508 | i->type = V4L2_INPUT_TYPE_CAMERA; |
509 | if (sd) | ||
510 | strlcpy(i->name, sd->name, sizeof(i->name)); | ||
525 | return 0; | 511 | return 0; |
526 | } | 512 | } |
527 | 513 | ||
@@ -541,14 +527,16 @@ static int fimc_cap_streamon(struct file *file, void *priv, | |||
541 | { | 527 | { |
542 | struct fimc_dev *fimc = video_drvdata(file); | 528 | struct fimc_dev *fimc = video_drvdata(file); |
543 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; | 529 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; |
530 | struct fimc_pipeline *p = &fimc->pipeline; | ||
544 | 531 | ||
545 | if (fimc_capture_active(fimc) || !fimc->vid_cap.sd) | 532 | if (fimc_capture_active(fimc)) |
546 | return -EBUSY; | 533 | return -EBUSY; |
547 | 534 | ||
548 | if (!(ctx->state & FIMC_DST_FMT)) { | 535 | if (!(ctx->state & FIMC_DST_FMT)) { |
549 | v4l2_err(fimc->vid_cap.vfd, "Format is not set\n"); | 536 | v4l2_err(fimc->vid_cap.vfd, "Format is not set\n"); |
550 | return -EINVAL; | 537 | return -EINVAL; |
551 | } | 538 | } |
539 | media_entity_pipeline_start(&p->sensor->entity, p->pipe); | ||
552 | 540 | ||
553 | return vb2_streamon(&fimc->vid_cap.vbq, type); | 541 | return vb2_streamon(&fimc->vid_cap.vbq, type); |
554 | } | 542 | } |
@@ -557,8 +545,13 @@ static int fimc_cap_streamoff(struct file *file, void *priv, | |||
557 | enum v4l2_buf_type type) | 545 | enum v4l2_buf_type type) |
558 | { | 546 | { |
559 | struct fimc_dev *fimc = video_drvdata(file); | 547 | struct fimc_dev *fimc = video_drvdata(file); |
548 | struct v4l2_subdev *sd = fimc->pipeline.sensor; | ||
549 | int ret; | ||
560 | 550 | ||
561 | return vb2_streamoff(&fimc->vid_cap.vbq, type); | 551 | ret = vb2_streamoff(&fimc->vid_cap.vbq, type); |
552 | if (ret == 0) | ||
553 | media_entity_pipeline_stop(&sd->entity); | ||
554 | return ret; | ||
562 | } | 555 | } |
563 | 556 | ||
564 | static int fimc_cap_reqbufs(struct file *file, void *priv, | 557 | static int fimc_cap_reqbufs(struct file *file, void *priv, |
@@ -664,7 +657,6 @@ static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) | |||
664 | return 0; | 657 | return 0; |
665 | } | 658 | } |
666 | 659 | ||
667 | |||
668 | static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = { | 660 | static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = { |
669 | .vidioc_querycap = fimc_vidioc_querycap_capture, | 661 | .vidioc_querycap = fimc_vidioc_querycap_capture, |
670 | 662 | ||
@@ -770,8 +762,6 @@ int fimc_register_capture_device(struct fimc_dev *fimc, | |||
770 | vid_cap->active_buf_cnt = 0; | 762 | vid_cap->active_buf_cnt = 0; |
771 | vid_cap->reqbufs_count = 0; | 763 | vid_cap->reqbufs_count = 0; |
772 | vid_cap->refcnt = 0; | 764 | vid_cap->refcnt = 0; |
773 | /* Default color format for image sensor */ | ||
774 | vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8; | ||
775 | 765 | ||
776 | INIT_LIST_HEAD(&vid_cap->pending_buf_q); | 766 | INIT_LIST_HEAD(&vid_cap->pending_buf_q); |
777 | INIT_LIST_HEAD(&vid_cap->active_buf_q); | 767 | INIT_LIST_HEAD(&vid_cap->active_buf_q); |