From: Arun Kumar K Date: Thu, 22 Nov 2012 09:15:55 +0000 (-0300) Subject: [media] s5p-mfc: Flush DPB buffers during stream off X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=8f23cc0222a9fe9c43f679dcb3d38604b30cf7c8;p=GitHub%2Fexynos8895%2Fandroid_kernel_samsung_universal8895.git [media] s5p-mfc: Flush DPB buffers during stream off 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 Signed-off-by: Arun Mankuzhi Acked-by: Kamil Debski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index a49d0e5db93a..3930177db125 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -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); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index f02e0497ca98..3b9b600a6182 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -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, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 6dad9a74f61c..4582473978ca 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -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; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index bf4d2f44f009..5f9a5e073456 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -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;