[media] s5p-mfc: Flush DPB buffers during stream off
authorArun Kumar K <arun.kk@samsung.com>
Thu, 22 Nov 2012 09:15:55 +0000 (06:15 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 6 Jan 2013 11:54:55 +0000 (09:54 -0200)
Flushing of delay DPB buffers have to be done during stream off.
In MFC v6, it is done with a risc to host command.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Arun Mankuzhi <arun.m@samsung.com>
Acked-by: Kamil Debski <k.debski@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_common.h
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c

index a49d0e5..3930177 100644 (file)
@@ -686,6 +686,12 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
                s5p_mfc_handle_stream_complete(ctx, reason, err);
                break;
 
+       case S5P_MFC_R2H_CMD_DPB_FLUSH_RET:
+               clear_work_bit(ctx);
+               ctx->state = MFCINST_RUNNING;
+               wake_up(&ctx->queue);
+               goto irq_cleanup_hw;
+
        default:
                mfc_debug(2, "Unknown int reason\n");
                s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
index f02e049..3b9b600 100644 (file)
@@ -145,6 +145,7 @@ enum s5p_mfc_inst_state {
        MFCINST_RETURN_INST,
        MFCINST_ERROR,
        MFCINST_ABORT,
+       MFCINST_FLUSH,
        MFCINST_RES_CHANGE_INIT,
        MFCINST_RES_CHANGE_FLUSH,
        MFCINST_RES_CHANGE_END,
index 6dad9a7..4582473 100644 (file)
@@ -991,24 +991,35 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
                                        S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
                aborted = 1;
        }
-       spin_lock_irqsave(&dev->irqlock, flags);
        if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               spin_lock_irqsave(&dev->irqlock, flags);
                s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
                                &ctx->vq_dst);
                INIT_LIST_HEAD(&ctx->dst_queue);
                ctx->dst_queue_cnt = 0;
                ctx->dpb_flush_flag = 1;
                ctx->dec_dst_flag = 0;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               if (IS_MFCV6(dev) && (ctx->state == MFCINST_RUNNING)) {
+                       ctx->state = MFCINST_FLUSH;
+                       set_work_bit_irqsave(ctx);
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+                       if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))
+                               mfc_err("Err flushing buffers\n");
+               }
        }
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               spin_lock_irqsave(&dev->irqlock, flags);
                s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
                                &ctx->vq_src);
                INIT_LIST_HEAD(&ctx->src_queue);
                ctx->src_queue_cnt = 0;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
        }
        if (aborted)
                ctx->state = MFCINST_RUNNING;
-       spin_unlock_irqrestore(&dev->irqlock, flags);
        return 0;
 }
 
index bf4d2f4..5f9a5e0 100644 (file)
@@ -1253,12 +1253,14 @@ int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
 static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dpb;
-       if (flush)
-               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
-       else
-               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
-       WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+
+       if (flush) {
+               dev->curr_ctx = ctx->num;
+               s5p_mfc_clean_ctx_int_flags(ctx);
+               WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_H2R_CMD_FLUSH_V6, NULL);
+       }
 }
 
 /* Decode a single frame */
@@ -1650,6 +1652,9 @@ void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
                case MFCINST_HEAD_PARSED:
                        ret = s5p_mfc_run_init_dec_buffers(ctx);
                        break;
+               case MFCINST_FLUSH:
+                       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+                       break;
                case MFCINST_RES_CHANGE_INIT:
                        s5p_mfc_run_dec_last_frames(ctx);
                        break;