diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2011-08-26 13:51:00 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-09-06 16:44:03 -0400 |
commit | 4db5e27ed9401a635b3c10994f2971c0441e3c90 (patch) | |
tree | 29098b7f030d50914b1c611ea160dabd2d195d5f /drivers/media/video/s5p-fimc | |
parent | cf52df8acfda9442d64ab4d3d6085877f6d88d46 (diff) |
[media] s5p-fimc: Convert to use media pipeline operations
In the camera capture driver use fimc_pipeline_* calls provided by
the media device driver part, in place where v4l2_subdev_call() were
used. This way the capture driver don't need to differentiate between
various H/W pipeline setups, i.e. if the MIPI-CSI receiver subdev is
used or not.
Remove the sync_capture_fmt() function instead of which
fimc_pipeline_try_format() is introduced in the following patch adding
the FIMC capture subdev.
The TRY_FMT ioctl function is completed by a subsequent patch adding
the capture subdev, so the try_fmt routines can be reused in the subdev
and the video node ioctl handlers.
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>
Diffstat (limited to 'drivers/media/video/s5p-fimc')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-capture.c | 118 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-core.c | 125 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-core.h | 11 |
3 files changed, 130 insertions, 124 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); |
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index af808bb97b14..605eb46e44d5 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c | |||
@@ -903,6 +903,60 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f) | |||
903 | return 0; | 903 | return 0; |
904 | } | 904 | } |
905 | 905 | ||
906 | void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f) | ||
907 | { | ||
908 | struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; | ||
909 | |||
910 | frame->f_width = pixm->plane_fmt[0].bytesperline; | ||
911 | if (frame->fmt->colplanes == 1) | ||
912 | frame->f_width = (frame->f_width * 8) / frame->fmt->depth[0]; | ||
913 | frame->f_height = pixm->height; | ||
914 | frame->width = pixm->width; | ||
915 | frame->height = pixm->height; | ||
916 | frame->o_width = pixm->width; | ||
917 | frame->o_height = pixm->height; | ||
918 | frame->offs_h = 0; | ||
919 | frame->offs_v = 0; | ||
920 | } | ||
921 | |||
922 | /** | ||
923 | * fimc_adjust_mplane_format - adjust bytesperline/sizeimage for each plane | ||
924 | * @fmt: fimc pixel format description (input) | ||
925 | * @width: requested pixel width | ||
926 | * @height: requested pixel height | ||
927 | * @pix: multi-plane format to adjust | ||
928 | */ | ||
929 | void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, | ||
930 | struct v4l2_pix_format_mplane *pix) | ||
931 | { | ||
932 | u32 bytesperline = 0; | ||
933 | int i; | ||
934 | |||
935 | pix->colorspace = V4L2_COLORSPACE_JPEG; | ||
936 | pix->field = V4L2_FIELD_NONE; | ||
937 | pix->num_planes = fmt->memplanes; | ||
938 | pix->height = height; | ||
939 | pix->width = width; | ||
940 | |||
941 | for (i = 0; i < pix->num_planes; ++i) { | ||
942 | u32 bpl = pix->plane_fmt[i].bytesperline; | ||
943 | u32 *sizeimage = &pix->plane_fmt[i].sizeimage; | ||
944 | |||
945 | if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width)) | ||
946 | bpl = pix->width; /* Planar */ | ||
947 | |||
948 | if (fmt->colplanes == 1 && /* Packed */ | ||
949 | (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width)) | ||
950 | bpl = (pix->width * fmt->depth[0]) / 8; | ||
951 | |||
952 | if (i == 0) /* Same bytesperline for each plane. */ | ||
953 | bytesperline = bpl; | ||
954 | |||
955 | pix->plane_fmt[i].bytesperline = bytesperline; | ||
956 | *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8; | ||
957 | } | ||
958 | } | ||
959 | |||
906 | static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh, | 960 | static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh, |
907 | struct v4l2_format *f) | 961 | struct v4l2_format *f) |
908 | { | 962 | { |
@@ -947,43 +1001,33 @@ struct fimc_fmt *fimc_find_format(u32 *pixelformat, u32 *mbus_code, | |||
947 | return def_fmt; | 1001 | return def_fmt; |
948 | } | 1002 | } |
949 | 1003 | ||
950 | int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) | 1004 | static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) |
951 | { | 1005 | { |
952 | struct fimc_dev *fimc = ctx->fimc_dev; | 1006 | struct fimc_dev *fimc = ctx->fimc_dev; |
953 | struct samsung_fimc_variant *variant = fimc->variant; | 1007 | struct samsung_fimc_variant *variant = fimc->variant; |
954 | struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; | 1008 | struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; |
955 | struct fimc_fmt *fmt; | 1009 | struct fimc_fmt *fmt; |
956 | u32 max_width, mod_x, mod_y, mask; | 1010 | u32 max_w, mod_x, mod_y; |
957 | int i, is_output = 0; | ||
958 | 1011 | ||
959 | if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 1012 | if (!IS_M2M(f->type)) |
960 | if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) | ||
961 | return -EINVAL; | ||
962 | is_output = 1; | ||
963 | } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
964 | return -EINVAL; | 1013 | return -EINVAL; |
965 | } | ||
966 | 1014 | ||
967 | dbg("w: %d, h: %d", pix->width, pix->height); | 1015 | dbg("w: %d, h: %d", pix->width, pix->height); |
968 | 1016 | ||
969 | mask = is_output ? FMT_FLAGS_M2M : FMT_FLAGS_M2M | FMT_FLAGS_CAM; | 1017 | fmt = fimc_find_format(&pix->pixelformat, NULL, FMT_FLAGS_M2M, 0); |
970 | fmt = fimc_find_format(&pix->pixelformat, NULL, mask, -1); | 1018 | if (WARN(fmt == NULL, "Pixel format lookup failed")) |
971 | if (!fmt) { | ||
972 | v4l2_err(fimc->v4l2_dev, "Fourcc format (0x%X) invalid.\n", | ||
973 | pix->pixelformat); | ||
974 | return -EINVAL; | 1019 | return -EINVAL; |
975 | } | ||
976 | 1020 | ||
977 | if (pix->field == V4L2_FIELD_ANY) | 1021 | if (pix->field == V4L2_FIELD_ANY) |
978 | pix->field = V4L2_FIELD_NONE; | 1022 | pix->field = V4L2_FIELD_NONE; |
979 | else if (V4L2_FIELD_NONE != pix->field) | 1023 | else if (pix->field != V4L2_FIELD_NONE) |
980 | return -EINVAL; | 1024 | return -EINVAL; |
981 | 1025 | ||
982 | if (is_output) { | 1026 | if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
983 | max_width = variant->pix_limit->scaler_dis_w; | 1027 | max_w = variant->pix_limit->scaler_dis_w; |
984 | mod_x = ffs(variant->min_inp_pixsize) - 1; | 1028 | mod_x = ffs(variant->min_inp_pixsize) - 1; |
985 | } else { | 1029 | } else { |
986 | max_width = variant->pix_limit->out_rot_dis_w; | 1030 | max_w = variant->pix_limit->out_rot_dis_w; |
987 | mod_x = ffs(variant->min_out_pixsize) - 1; | 1031 | mod_x = ffs(variant->min_out_pixsize) - 1; |
988 | } | 1032 | } |
989 | 1033 | ||
@@ -996,34 +1040,12 @@ int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) | |||
996 | else | 1040 | else |
997 | mod_y = mod_x; | 1041 | mod_y = mod_x; |
998 | } | 1042 | } |
1043 | dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_w); | ||
999 | 1044 | ||
1000 | dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_width); | 1045 | v4l_bound_align_image(&pix->width, 16, max_w, mod_x, |
1001 | |||
1002 | v4l_bound_align_image(&pix->width, 16, max_width, mod_x, | ||
1003 | &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0); | 1046 | &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0); |
1004 | 1047 | ||
1005 | pix->num_planes = fmt->memplanes; | 1048 | fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp); |
1006 | pix->colorspace = V4L2_COLORSPACE_JPEG; | ||
1007 | |||
1008 | |||
1009 | for (i = 0; i < pix->num_planes; ++i) { | ||
1010 | u32 bpl = pix->plane_fmt[i].bytesperline; | ||
1011 | u32 *sizeimage = &pix->plane_fmt[i].sizeimage; | ||
1012 | |||
1013 | if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width)) | ||
1014 | bpl = pix->width; /* Planar */ | ||
1015 | |||
1016 | if (fmt->colplanes == 1 && /* Packed */ | ||
1017 | (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width)) | ||
1018 | bpl = (pix->width * fmt->depth[0]) / 8; | ||
1019 | |||
1020 | if (i == 0) /* Same bytesperline for each plane. */ | ||
1021 | mod_x = bpl; | ||
1022 | |||
1023 | pix->plane_fmt[i].bytesperline = mod_x; | ||
1024 | *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8; | ||
1025 | } | ||
1026 | |||
1027 | return 0; | 1049 | return 0; |
1028 | } | 1050 | } |
1029 | 1051 | ||
@@ -1072,15 +1094,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, | |||
1072 | (pix->width * pix->height * frame->fmt->depth[i]) / 8; | 1094 | (pix->width * pix->height * frame->fmt->depth[i]) / 8; |
1073 | } | 1095 | } |
1074 | 1096 | ||
1075 | frame->f_width = pix->plane_fmt[0].bytesperline * 8 / | 1097 | fimc_fill_frame(frame, f); |
1076 | frame->fmt->depth[0]; | ||
1077 | frame->f_height = pix->height; | ||
1078 | frame->width = pix->width; | ||
1079 | frame->height = pix->height; | ||
1080 | frame->o_width = pix->width; | ||
1081 | frame->o_height = pix->height; | ||
1082 | frame->offs_h = 0; | ||
1083 | frame->offs_v = 0; | ||
1084 | 1098 | ||
1085 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | 1099 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
1086 | fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx); | 1100 | fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx); |
@@ -1160,8 +1174,8 @@ static int fimc_m2m_cropcap(struct file *file, void *fh, | |||
1160 | 1174 | ||
1161 | cr->bounds.left = 0; | 1175 | cr->bounds.left = 0; |
1162 | cr->bounds.top = 0; | 1176 | cr->bounds.top = 0; |
1163 | cr->bounds.width = frame->f_width; | 1177 | cr->bounds.width = frame->o_width; |
1164 | cr->bounds.height = frame->f_height; | 1178 | cr->bounds.height = frame->o_height; |
1165 | cr->defrect = cr->bounds; | 1179 | cr->defrect = cr->bounds; |
1166 | 1180 | ||
1167 | return 0; | 1181 | return 0; |
@@ -1612,7 +1626,6 @@ static int fimc_probe(struct platform_device *pdev) | |||
1612 | 1626 | ||
1613 | init_waitqueue_head(&fimc->irq_queue); | 1627 | init_waitqueue_head(&fimc->irq_queue); |
1614 | spin_lock_init(&fimc->slock); | 1628 | spin_lock_init(&fimc->slock); |
1615 | |||
1616 | mutex_init(&fimc->lock); | 1629 | mutex_init(&fimc->lock); |
1617 | 1630 | ||
1618 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1631 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index f107485af7bf..2935068fda2d 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h | |||
@@ -61,6 +61,7 @@ enum fimc_dev_flags { | |||
61 | ST_CAPT_PEND, | 61 | ST_CAPT_PEND, |
62 | ST_CAPT_RUN, | 62 | ST_CAPT_RUN, |
63 | ST_CAPT_STREAM, | 63 | ST_CAPT_STREAM, |
64 | ST_CAPT_ISP_STREAM, | ||
64 | ST_CAPT_SHUT, | 65 | ST_CAPT_SHUT, |
65 | ST_CAPT_BUSY, | 66 | ST_CAPT_BUSY, |
66 | ST_CAPT_APPLY_CFG, | 67 | ST_CAPT_APPLY_CFG, |
@@ -95,6 +96,9 @@ enum fimc_color_fmt { | |||
95 | 96 | ||
96 | #define fimc_fmt_is_rgb(x) ((x) & 0x10) | 97 | #define fimc_fmt_is_rgb(x) ((x) & 0x10) |
97 | 98 | ||
99 | #define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \ | ||
100 | __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
101 | |||
98 | /* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */ | 102 | /* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */ |
99 | #define S5P_FIMC_LSB_CRCB S5P_CIOCTRL_ORDER422_2P_LSB_CRCB | 103 | #define S5P_FIMC_LSB_CRCB S5P_CIOCTRL_ORDER422_2P_LSB_CRCB |
100 | 104 | ||
@@ -293,7 +297,6 @@ struct fimc_m2m_device { | |||
293 | * struct fimc_vid_cap - camera capture device information | 297 | * struct fimc_vid_cap - camera capture device information |
294 | * @ctx: hardware context data | 298 | * @ctx: hardware context data |
295 | * @vfd: video device node for camera capture mode | 299 | * @vfd: video device node for camera capture mode |
296 | * @sd: pointer to camera sensor subdevice currently in use | ||
297 | * @vd_pad: fimc video capture node pad | 300 | * @vd_pad: fimc video capture node pad |
298 | * @fmt: Media Bus format configured at selected image sensor | 301 | * @fmt: Media Bus format configured at selected image sensor |
299 | * @pending_buf_q: the pending buffer queue head | 302 | * @pending_buf_q: the pending buffer queue head |
@@ -312,7 +315,6 @@ struct fimc_vid_cap { | |||
312 | struct fimc_ctx *ctx; | 315 | struct fimc_ctx *ctx; |
313 | struct vb2_alloc_ctx *alloc_ctx; | 316 | struct vb2_alloc_ctx *alloc_ctx; |
314 | struct video_device *vfd; | 317 | struct video_device *vfd; |
315 | struct v4l2_subdev *sd;; | ||
316 | struct media_pad vd_pad; | 318 | struct media_pad vd_pad; |
317 | struct v4l2_mbus_framefmt fmt; | 319 | struct v4l2_mbus_framefmt fmt; |
318 | struct list_head pending_buf_q; | 320 | struct list_head pending_buf_q; |
@@ -647,13 +649,13 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, | |||
647 | /* fimc-core.c */ | 649 | /* fimc-core.c */ |
648 | int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv, | 650 | int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv, |
649 | struct v4l2_fmtdesc *f); | 651 | struct v4l2_fmtdesc *f); |
650 | int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f); | ||
651 | int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr); | 652 | int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr); |
652 | int fimc_ctrls_create(struct fimc_ctx *ctx); | 653 | int fimc_ctrls_create(struct fimc_ctx *ctx); |
653 | void fimc_ctrls_delete(struct fimc_ctx *ctx); | 654 | void fimc_ctrls_delete(struct fimc_ctx *ctx); |
654 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); | 655 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); |
655 | int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f); | 656 | int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f); |
656 | 657 | void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, | |
658 | struct v4l2_pix_format_mplane *pix); | ||
657 | struct fimc_fmt *fimc_find_format(u32 *pixelformat, u32 *mbus_code, | 659 | struct fimc_fmt *fimc_find_format(u32 *pixelformat, u32 *mbus_code, |
658 | unsigned int mask, int index); | 660 | unsigned int mask, int index); |
659 | 661 | ||
@@ -664,6 +666,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, | |||
664 | struct fimc_frame *frame, struct fimc_addr *paddr); | 666 | struct fimc_frame *frame, struct fimc_addr *paddr); |
665 | void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f); | 667 | void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f); |
666 | void fimc_set_yuv_order(struct fimc_ctx *ctx); | 668 | void fimc_set_yuv_order(struct fimc_ctx *ctx); |
669 | void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f); | ||
667 | 670 | ||
668 | int fimc_register_m2m_device(struct fimc_dev *fimc, | 671 | int fimc_register_m2m_device(struct fimc_dev *fimc, |
669 | struct v4l2_device *v4l2_dev); | 672 | struct v4l2_device *v4l2_dev); |