aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c9
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c197
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h44
3 files changed, 136 insertions, 114 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 423931c0cfe5..8312ce465f16 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -252,14 +252,9 @@ static int stop_streaming(struct vb2_queue *q)
252{ 252{
253 struct fimc_ctx *ctx = q->drv_priv; 253 struct fimc_ctx *ctx = q->drv_priv;
254 struct fimc_dev *fimc = ctx->fimc_dev; 254 struct fimc_dev *fimc = ctx->fimc_dev;
255 unsigned long flags;
256 255
257 spin_lock_irqsave(&fimc->slock, flags); 256 if (!fimc_capture_active(fimc))
258 if (!fimc_capture_running(fimc) && !fimc_capture_pending(fimc)) {
259 spin_unlock_irqrestore(&fimc->slock, flags);
260 return -EINVAL; 257 return -EINVAL;
261 }
262 spin_unlock_irqrestore(&fimc->slock, flags);
263 258
264 return fimc_stop_capture(fimc); 259 return fimc_stop_capture(fimc);
265} 260}
@@ -773,7 +768,7 @@ static int fimc_cap_s_crop(struct file *file, void *fh,
773 ctx->d_frame.width, ctx->d_frame.height, 768 ctx->d_frame.width, ctx->d_frame.height,
774 ctx->rotation); 769 ctx->rotation);
775 if (ret) { 770 if (ret) {
776 v4l2_err(&fimc->vid_cap.v4l2_dev, "Out of the scaler range"); 771 v4l2_err(&fimc->vid_cap.v4l2_dev, "Out of the scaler range\n");
777 return ret; 772 return ret;
778 } 773 }
779 774
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index fdf4270fcb62..f506197201c8 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -307,24 +307,57 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx)
307 return 0; 307 return 0;
308} 308}
309 309
310static int stop_streaming(struct vb2_queue *q) 310static void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
311{ 311{
312 struct fimc_ctx *ctx = q->drv_priv; 312 struct vb2_buffer *src_vb, *dst_vb;
313 struct fimc_dev *fimc = ctx->fimc_dev; 313 struct fimc_dev *fimc = ctx->fimc_dev;
314 314
315 if (!ctx || !ctx->m2m_ctx)
316 return;
317
318 src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
319 dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
320
321 if (src_vb && dst_vb) {
322 v4l2_m2m_buf_done(src_vb, vb_state);
323 v4l2_m2m_buf_done(dst_vb, vb_state);
324 v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
325 }
326}
327
328/* Complete the transaction which has been scheduled for execution. */
329static void fimc_m2m_shutdown(struct fimc_ctx *ctx)
330{
331 struct fimc_dev *fimc = ctx->fimc_dev;
332 int ret;
333
315 if (!fimc_m2m_pending(fimc)) 334 if (!fimc_m2m_pending(fimc))
316 return 0; 335 return;
317 336
318 set_bit(ST_M2M_SHUT, &fimc->state); 337 fimc_ctx_state_lock_set(FIMC_CTX_SHUT, ctx);
319 338
320 wait_event_timeout(fimc->irq_queue, 339 ret = wait_event_timeout(fimc->irq_queue,
321 !test_bit(ST_M2M_SHUT, &fimc->state), 340 !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
322 FIMC_SHUTDOWN_TIMEOUT); 341 FIMC_SHUTDOWN_TIMEOUT);
342 /*
343 * In case of a timeout the buffers are not released in the interrupt
344 * handler so return them here with the error flag set, if there are
345 * any on the queue.
346 */
347 if (ret == 0)
348 fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
349}
350
351static int stop_streaming(struct vb2_queue *q)
352{
353 struct fimc_ctx *ctx = q->drv_priv;
354
355 fimc_m2m_shutdown(ctx);
323 356
324 return 0; 357 return 0;
325} 358}
326 359
327static void fimc_capture_handler(struct fimc_dev *fimc) 360static void fimc_capture_irq_handler(struct fimc_dev *fimc)
328{ 361{
329 struct fimc_vid_cap *cap = &fimc->vid_cap; 362 struct fimc_vid_cap *cap = &fimc->vid_cap;
330 struct fimc_vid_buffer *v_buf; 363 struct fimc_vid_buffer *v_buf;
@@ -373,33 +406,28 @@ static irqreturn_t fimc_isr(int irq, void *priv)
373{ 406{
374 struct fimc_dev *fimc = priv; 407 struct fimc_dev *fimc = priv;
375 struct fimc_vid_cap *cap = &fimc->vid_cap; 408 struct fimc_vid_cap *cap = &fimc->vid_cap;
409 struct fimc_ctx *ctx;
376 410
377 BUG_ON(!fimc);
378 fimc_hw_clear_irq(fimc); 411 fimc_hw_clear_irq(fimc);
379 412
380 spin_lock(&fimc->slock); 413 if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
414 ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
415 if (ctx != NULL) {
416 fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
381 417
382 if (test_and_clear_bit(ST_M2M_SHUT, &fimc->state)) { 418 spin_lock(&ctx->slock);
383 wake_up(&fimc->irq_queue); 419 if (ctx->state & FIMC_CTX_SHUT) {
384 goto isr_unlock; 420 ctx->state &= ~FIMC_CTX_SHUT;
385 } else if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) { 421 wake_up(&fimc->irq_queue);
386 struct vb2_buffer *src_vb, *dst_vb; 422 }
387 struct fimc_ctx *ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev); 423 spin_unlock(&ctx->slock);
388
389 if (!ctx || !ctx->m2m_ctx)
390 goto isr_unlock;
391
392 src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
393 dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
394 if (src_vb && dst_vb) {
395 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
396 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
397 v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
398 } 424 }
399 goto isr_unlock;
400 425
426 return IRQ_HANDLED;
401 } 427 }
402 428
429 spin_lock(&fimc->slock);
430
403 if (test_bit(ST_CAPT_PEND, &fimc->state)) { 431 if (test_bit(ST_CAPT_PEND, &fimc->state)) {
404 fimc_capture_irq_handler(fimc); 432 fimc_capture_irq_handler(fimc);
405 433
@@ -409,7 +437,6 @@ static irqreturn_t fimc_isr(int irq, void *priv)
409 } 437 }
410 } 438 }
411 439
412isr_unlock:
413 spin_unlock(&fimc->slock); 440 spin_unlock(&fimc->slock);
414 return IRQ_HANDLED; 441 return IRQ_HANDLED;
415} 442}
@@ -613,26 +640,26 @@ static void fimc_dma_run(void *priv)
613 640
614 ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR); 641 ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
615 ret = fimc_prepare_config(ctx, ctx->state); 642 ret = fimc_prepare_config(ctx, ctx->state);
616 if (ret) { 643 if (ret)
617 err("Wrong parameters");
618 goto dma_unlock; 644 goto dma_unlock;
619 } 645
620 /* Reconfigure hardware if the context has changed. */ 646 /* Reconfigure hardware if the context has changed. */
621 if (fimc->m2m.ctx != ctx) { 647 if (fimc->m2m.ctx != ctx) {
622 ctx->state |= FIMC_PARAMS; 648 ctx->state |= FIMC_PARAMS;
623 fimc->m2m.ctx = ctx; 649 fimc->m2m.ctx = ctx;
624 } 650 }
625 651
652 spin_lock(&fimc->slock);
626 fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr); 653 fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
627 654
628 if (ctx->state & FIMC_PARAMS) { 655 if (ctx->state & FIMC_PARAMS) {
629 fimc_hw_set_input_path(ctx); 656 fimc_hw_set_input_path(ctx);
630 fimc_hw_set_in_dma(ctx); 657 fimc_hw_set_in_dma(ctx);
631 if (fimc_set_scaler_info(ctx)) { 658 ret = fimc_set_scaler_info(ctx);
632 err("Scaler setup error"); 659 if (ret) {
660 spin_unlock(&fimc->slock);
633 goto dma_unlock; 661 goto dma_unlock;
634 } 662 }
635
636 fimc_hw_set_prescaler(ctx); 663 fimc_hw_set_prescaler(ctx);
637 fimc_hw_set_mainscaler(ctx); 664 fimc_hw_set_mainscaler(ctx);
638 fimc_hw_set_target_format(ctx); 665 fimc_hw_set_target_format(ctx);
@@ -652,6 +679,7 @@ static void fimc_dma_run(void *priv)
652 ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP | 679 ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP |
653 FIMC_SRC_FMT | FIMC_DST_FMT); 680 FIMC_SRC_FMT | FIMC_DST_FMT);
654 fimc_hw_activate_input_dma(fimc, true); 681 fimc_hw_activate_input_dma(fimc, true);
682 spin_unlock(&fimc->slock);
655 683
656dma_unlock: 684dma_unlock:
657 spin_unlock_irqrestore(&ctx->slock, flags); 685 spin_unlock_irqrestore(&ctx->slock, flags);
@@ -659,17 +687,7 @@ dma_unlock:
659 687
660static void fimc_job_abort(void *priv) 688static void fimc_job_abort(void *priv)
661{ 689{
662 struct fimc_ctx *ctx = priv; 690 fimc_m2m_shutdown(priv);
663 struct fimc_dev *fimc = ctx->fimc_dev;
664
665 if (!fimc_m2m_pending(fimc))
666 return;
667
668 set_bit(ST_M2M_SHUT, &fimc->state);
669
670 wait_event_timeout(fimc->irq_queue,
671 !test_bit(ST_M2M_SHUT, &fimc->state),
672 FIMC_SHUTDOWN_TIMEOUT);
673} 691}
674 692
675static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, 693static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
@@ -843,7 +861,7 @@ int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
843 861
844 862
845 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 863 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
846 if (ctx->state & FIMC_CTX_CAP) 864 if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx))
847 return -EINVAL; 865 return -EINVAL;
848 is_output = 1; 866 is_output = 1;
849 } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 867 } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
@@ -920,9 +938,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
920 struct vb2_queue *vq; 938 struct vb2_queue *vq;
921 struct fimc_frame *frame; 939 struct fimc_frame *frame;
922 struct v4l2_pix_format_mplane *pix; 940 struct v4l2_pix_format_mplane *pix;
923 unsigned long flags;
924 int i, ret = 0; 941 int i, ret = 0;
925 u32 tmp;
926 942
927 ret = fimc_vidioc_try_fmt_mplane(file, priv, f); 943 ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
928 if (ret) 944 if (ret)
@@ -963,10 +979,10 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
963 frame->offs_h = 0; 979 frame->offs_h = 0;
964 frame->offs_v = 0; 980 frame->offs_v = 0;
965 981
966 spin_lock_irqsave(&ctx->slock, flags); 982 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
967 tmp = (frame == &ctx->d_frame) ? FIMC_DST_FMT : FIMC_SRC_FMT; 983 fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx);
968 ctx->state |= FIMC_PARAMS | tmp; 984 else
969 spin_unlock_irqrestore(&ctx->slock, flags); 985 fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx);
970 986
971 dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height); 987 dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height);
972 988
@@ -1009,9 +1025,9 @@ static int fimc_m2m_streamon(struct file *file, void *priv,
1009 1025
1010 /* The source and target color format need to be set */ 1026 /* The source and target color format need to be set */
1011 if (V4L2_TYPE_IS_OUTPUT(type)) { 1027 if (V4L2_TYPE_IS_OUTPUT(type)) {
1012 if (~ctx->state & FIMC_SRC_FMT) 1028 if (!fimc_ctx_state_is_set(FIMC_SRC_FMT, ctx))
1013 return -EINVAL; 1029 return -EINVAL;
1014 } else if (~ctx->state & FIMC_DST_FMT) { 1030 } else if (!fimc_ctx_state_is_set(FIMC_DST_FMT, ctx)) {
1015 return -EINVAL; 1031 return -EINVAL;
1016 } 1032 }
1017 1033
@@ -1038,7 +1054,7 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv,
1038 return 0; 1054 return 0;
1039 } 1055 }
1040 1056
1041 if (ctx->state & FIMC_CTX_CAP) { 1057 if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
1042 return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd, 1058 return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
1043 core, queryctrl, qc); 1059 core, queryctrl, qc);
1044 } 1060 }
@@ -1062,12 +1078,11 @@ int fimc_vidioc_g_ctrl(struct file *file, void *priv,
1062 ctrl->value = ctx->rotation; 1078 ctrl->value = ctx->rotation;
1063 break; 1079 break;
1064 default: 1080 default:
1065 if (ctx->state & FIMC_CTX_CAP) { 1081 if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
1066 return v4l2_subdev_call(fimc->vid_cap.sd, core, 1082 return v4l2_subdev_call(fimc->vid_cap.sd, core,
1067 g_ctrl, ctrl); 1083 g_ctrl, ctrl);
1068 } else { 1084 } else {
1069 v4l2_err(&fimc->m2m.v4l2_dev, 1085 v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
1070 "Invalid control\n");
1071 return -EINVAL; 1086 return -EINVAL;
1072 } 1087 }
1073 } 1088 }
@@ -1097,11 +1112,8 @@ int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
1097{ 1112{
1098 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; 1113 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
1099 struct fimc_dev *fimc = ctx->fimc_dev; 1114 struct fimc_dev *fimc = ctx->fimc_dev;
1100 unsigned long flags;
1101 int ret = 0; 1115 int ret = 0;
1102 1116
1103 spin_lock_irqsave(&ctx->slock, flags);
1104
1105 switch (ctrl->id) { 1117 switch (ctrl->id) {
1106 case V4L2_CID_HFLIP: 1118 case V4L2_CID_HFLIP:
1107 if (ctrl->value) 1119 if (ctrl->value)
@@ -1118,37 +1130,30 @@ int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
1118 break; 1130 break;
1119 1131
1120 case V4L2_CID_ROTATE: 1132 case V4L2_CID_ROTATE:
1121 if (!(~ctx->state & (FIMC_DST_FMT | FIMC_SRC_FMT))) { 1133 if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
1122 ret = fimc_check_scaler_ratio(ctx->s_frame.width, 1134 ret = fimc_check_scaler_ratio(ctx->s_frame.width,
1123 ctx->s_frame.height, 1135 ctx->s_frame.height, ctx->d_frame.width,
1124 ctx->d_frame.width, 1136 ctx->d_frame.height, ctrl->value);
1125 ctx->d_frame.height, 1137 }
1126 ctrl->value); 1138
1127 if (ret) { 1139 if (ret) {
1128 v4l2_err(&fimc->m2m.v4l2_dev, 1140 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
1129 "Out of scaler range"); 1141 return -EINVAL;
1130 spin_unlock_irqrestore(&ctx->slock, flags);
1131 return -EINVAL;
1132 }
1133 } 1142 }
1134 1143
1135 /* Check for the output rotator availability */ 1144 /* Check for the output rotator availability */
1136 if ((ctrl->value == 90 || ctrl->value == 270) && 1145 if ((ctrl->value == 90 || ctrl->value == 270) &&
1137 (ctx->in_path == FIMC_DMA && !variant->has_out_rot)) { 1146 (ctx->in_path == FIMC_DMA && !variant->has_out_rot))
1138 spin_unlock_irqrestore(&ctx->slock, flags);
1139 return -EINVAL; 1147 return -EINVAL;
1140 } else { 1148 ctx->rotation = ctrl->value;
1141 ctx->rotation = ctrl->value;
1142 }
1143 break; 1149 break;
1144 1150
1145 default: 1151 default:
1146 spin_unlock_irqrestore(&ctx->slock, flags);
1147 v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n"); 1152 v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
1148 return -EINVAL; 1153 return -EINVAL;
1149 } 1154 }
1150 ctx->state |= FIMC_PARAMS; 1155
1151 spin_unlock_irqrestore(&ctx->slock, flags); 1156 fimc_ctx_state_lock_set(FIMC_PARAMS, ctx);
1152 1157
1153 return 0; 1158 return 0;
1154} 1159}
@@ -1208,6 +1213,7 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1208 struct fimc_dev *fimc = ctx->fimc_dev; 1213 struct fimc_dev *fimc = ctx->fimc_dev;
1209 struct fimc_frame *f; 1214 struct fimc_frame *f;
1210 u32 min_size, halign, depth = 0; 1215 u32 min_size, halign, depth = 0;
1216 bool is_capture_ctx;
1211 int i; 1217 int i;
1212 1218
1213 if (cr->c.top < 0 || cr->c.left < 0) { 1219 if (cr->c.top < 0 || cr->c.left < 0) {
@@ -1216,10 +1222,12 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1216 return -EINVAL; 1222 return -EINVAL;
1217 } 1223 }
1218 1224
1225 is_capture_ctx = fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx);
1226
1219 if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 1227 if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1220 f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame; 1228 f = is_capture_ctx ? &ctx->s_frame : &ctx->d_frame;
1221 else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 1229 else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1222 ctx->state & FIMC_CTX_M2M) 1230 !is_capture_ctx)
1223 f = &ctx->s_frame; 1231 f = &ctx->s_frame;
1224 else 1232 else
1225 return -EINVAL; 1233 return -EINVAL;
@@ -1227,15 +1235,15 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1227 min_size = (f == &ctx->s_frame) ? 1235 min_size = (f == &ctx->s_frame) ?
1228 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; 1236 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
1229 1237
1230 if (ctx->state & FIMC_CTX_M2M) { 1238 /* Get pixel alignment constraints. */
1239 if (is_capture_ctx) {
1240 min_size = 16;
1241 halign = 4;
1242 } else {
1231 if (fimc->id == 1 && fimc->variant->pix_hoff) 1243 if (fimc->id == 1 && fimc->variant->pix_hoff)
1232 halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1; 1244 halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
1233 else 1245 else
1234 halign = ffs(min_size) - 1; 1246 halign = ffs(min_size) - 1;
1235 /* there are more strict aligment requirements at camera interface */
1236 } else {
1237 min_size = 16;
1238 halign = 4;
1239 } 1247 }
1240 1248
1241 for (i = 0; i < f->fmt->colplanes; i++) 1249 for (i = 0; i < f->fmt->colplanes; i++)
@@ -1253,8 +1261,7 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1253 cr->c.top = f->o_height - cr->c.height; 1261 cr->c.top = f->o_height - cr->c.height;
1254 1262
1255 cr->c.left = round_down(cr->c.left, min_size); 1263 cr->c.left = round_down(cr->c.left, min_size);
1256 cr->c.top = round_down(cr->c.top, 1264 cr->c.top = round_down(cr->c.top, is_capture_ctx ? 16 : 8);
1257 ctx->state & FIMC_CTX_M2M ? 8 : 16);
1258 1265
1259 dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d", 1266 dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
1260 cr->c.left, cr->c.top, cr->c.width, cr->c.height, 1267 cr->c.left, cr->c.top, cr->c.width, cr->c.height,
@@ -1263,12 +1270,10 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1263 return 0; 1270 return 0;
1264} 1271}
1265 1272
1266
1267static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) 1273static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1268{ 1274{
1269 struct fimc_ctx *ctx = file->private_data; 1275 struct fimc_ctx *ctx = file->private_data;
1270 struct fimc_dev *fimc = ctx->fimc_dev; 1276 struct fimc_dev *fimc = ctx->fimc_dev;
1271 unsigned long flags;
1272 struct fimc_frame *f; 1277 struct fimc_frame *f;
1273 int ret; 1278 int ret;
1274 1279
@@ -1279,9 +1284,8 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1279 f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? 1284 f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
1280 &ctx->s_frame : &ctx->d_frame; 1285 &ctx->s_frame : &ctx->d_frame;
1281 1286
1282 spin_lock_irqsave(&ctx->slock, flags);
1283 /* Check to see if scaling ratio is within supported range */ 1287 /* Check to see if scaling ratio is within supported range */
1284 if (!(~ctx->state & (FIMC_DST_FMT | FIMC_SRC_FMT))) { 1288 if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
1285 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 1289 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1286 ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height, 1290 ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height,
1287 ctx->d_frame.width, 1291 ctx->d_frame.width,
@@ -1293,22 +1297,19 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1293 cr->c.width, cr->c.height, 1297 cr->c.width, cr->c.height,
1294 ctx->rotation); 1298 ctx->rotation);
1295 } 1299 }
1296
1297 if (ret) { 1300 if (ret) {
1298 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range"); 1301 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
1299 spin_unlock_irqrestore(&ctx->slock, flags);
1300 return -EINVAL; 1302 return -EINVAL;
1301 } 1303 }
1302 } 1304 }
1303 1305
1304 ctx->state |= FIMC_PARAMS;
1305
1306 f->offs_h = cr->c.left; 1306 f->offs_h = cr->c.left;
1307 f->offs_v = cr->c.top; 1307 f->offs_v = cr->c.top;
1308 f->width = cr->c.width; 1308 f->width = cr->c.width;
1309 f->height = cr->c.height; 1309 f->height = cr->c.height;
1310 1310
1311 spin_unlock_irqrestore(&ctx->slock, flags); 1311 fimc_ctx_state_lock_set(FIMC_PARAMS, ctx);
1312
1312 return 0; 1313 return 0;
1313} 1314}
1314 1315
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 4829a2515076..41b135249d1f 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -14,6 +14,7 @@
14/*#define DEBUG*/ 14/*#define DEBUG*/
15 15
16#include <linux/sched.h> 16#include <linux/sched.h>
17#include <linux/spinlock.h>
17#include <linux/types.h> 18#include <linux/types.h>
18#include <linux/videodev2.h> 19#include <linux/videodev2.h>
19#include <linux/io.h> 20#include <linux/io.h>
@@ -57,7 +58,6 @@ enum fimc_dev_flags {
57 ST_IDLE, 58 ST_IDLE,
58 ST_OUTDMA_RUN, 59 ST_OUTDMA_RUN,
59 ST_M2M_PEND, 60 ST_M2M_PEND,
60 ST_M2M_SHUT,
61 /* for capture node */ 61 /* for capture node */
62 ST_CAPT_PEND, 62 ST_CAPT_PEND,
63 ST_CAPT_RUN, 63 ST_CAPT_RUN,
@@ -71,13 +71,6 @@ enum fimc_dev_flags {
71#define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state) 71#define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state)
72#define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state) 72#define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state)
73 73
74#define fimc_capture_active(dev) \
75 (test_bit(ST_CAPT_RUN, &(dev)->state) || \
76 test_bit(ST_CAPT_PEND, &(dev)->state))
77
78#define fimc_capture_streaming(dev) \
79 test_bit(ST_CAPT_STREAM, &(dev)->state)
80
81enum fimc_datapath { 74enum fimc_datapath {
82 FIMC_CAMERA, 75 FIMC_CAMERA,
83 FIMC_DMA, 76 FIMC_DMA,
@@ -119,6 +112,7 @@ enum fimc_color_fmt {
119#define FIMC_DST_FMT (1 << 4) 112#define FIMC_DST_FMT (1 << 4)
120#define FIMC_CTX_M2M (1 << 5) 113#define FIMC_CTX_M2M (1 << 5)
121#define FIMC_CTX_CAP (1 << 6) 114#define FIMC_CTX_CAP (1 << 6)
115#define FIMC_CTX_SHUT (1 << 7)
122 116
123/* Image conversion flags */ 117/* Image conversion flags */
124#define FIMC_IN_DMA_ACCESS_TILED (1 << 0) 118#define FIMC_IN_DMA_ACCESS_TILED (1 << 0)
@@ -476,6 +470,38 @@ struct fimc_ctx {
476 struct v4l2_m2m_ctx *m2m_ctx; 470 struct v4l2_m2m_ctx *m2m_ctx;
477}; 471};
478 472
473static inline bool fimc_capture_active(struct fimc_dev *fimc)
474{
475 unsigned long flags;
476 bool ret;
477
478 spin_lock_irqsave(&fimc->slock, flags);
479 ret = !!(fimc->state & (1 << ST_CAPT_RUN) ||
480 fimc->state & (1 << ST_CAPT_PEND));
481 spin_unlock_irqrestore(&fimc->slock, flags);
482 return ret;
483}
484
485static inline void fimc_ctx_state_lock_set(u32 state, struct fimc_ctx *ctx)
486{
487 unsigned long flags;
488
489 spin_lock_irqsave(&ctx->slock, flags);
490 ctx->state |= state;
491 spin_unlock_irqrestore(&ctx->slock, flags);
492}
493
494static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx)
495{
496 unsigned long flags;
497 bool ret;
498
499 spin_lock_irqsave(&ctx->slock, flags);
500 ret = (ctx->state & mask) == mask;
501 spin_unlock_irqrestore(&ctx->slock, flags);
502 return ret;
503}
504
479static inline int tiled_fmt(struct fimc_fmt *fmt) 505static inline int tiled_fmt(struct fimc_fmt *fmt)
480{ 506{
481 return fmt->fourcc == V4L2_PIX_FMT_NV12MT; 507 return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
@@ -535,7 +561,7 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
535 struct fimc_frame *frame; 561 struct fimc_frame *frame;
536 562
537 if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) { 563 if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) {
538 if (ctx->state & FIMC_CTX_M2M) 564 if (fimc_ctx_state_is_set(FIMC_CTX_M2M, ctx))
539 frame = &ctx->s_frame; 565 frame = &ctx->s_frame;
540 else 566 else
541 return ERR_PTR(-EINVAL); 567 return ERR_PTR(-EINVAL);