RE: [PATCH,RESEND] v4l/s5p-mfc: added support for end of stream handling in MFC encoder
Hi Andrzej, Thank you for your patch. Best wishes, -- Kamil Debski Linux Platform Group Samsung Poland R&D Center > From: Andrzej Hajda [mailto:a.ha...@samsung.com] > Sent: 10 August 2012 14:47 > > s5p-mfc encoder after receiving V4L2_ENC_CMD_STOP command > will instruct MFC device to release all encoded frames. > After dequeuing last encoded frame driver will generate > V4L2_EVENT_EOS event. > > Signed-off-by: Andrzej Hajda > Signed-off-by: Kyungmin Park Acked-by: Kamil Debski > --- > I have removed bank2 alignement fix from this patch. > It is is already done by patch 's5p-mfc: Fix second memory bank alignment'. > --- > drivers/media/video/s5p-mfc/s5p_mfc.c| 43 +++ > drivers/media/video/s5p-mfc/s5p_mfc_common.h |5 +- > drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c |6 +- > drivers/media/video/s5p-mfc/s5p_mfc_dec.c|4 +- > drivers/media/video/s5p-mfc/s5p_mfc_enc.c| 106 +- > drivers/media/video/s5p-mfc/s5p_mfc_opr.c| 48 +--- > 6 files changed, 177 insertions(+), 35 deletions(-) > > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p- > mfc/s5p_mfc.c > index 9bb68e7..dc9355c 100644 > --- a/drivers/media/video/s5p-mfc/s5p_mfc.c > +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c > @@ -19,6 +19,7 @@ > #include > #include > #include > +#include > #include > #include > #include "regs-mfc.h" > @@ -539,6 +540,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx > *ctx, > } > } > > +static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, > + unsigned int reason, unsigned int err) > +{ > + struct s5p_mfc_dev *dev = ctx->dev; > + struct s5p_mfc_buf *mb_entry; > + > + mfc_debug(2, "Stream completed"); > + > + s5p_mfc_clear_int_flags(dev); > + ctx->int_type = reason; > + ctx->int_err = err; > + ctx->state = MFCINST_FINISHED; > + > + spin_lock(&dev->irqlock); > + if (!list_empty(&ctx->dst_queue)) { > + mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, > + list); > + list_del(&mb_entry->list); > + ctx->dst_queue_cnt--; > + vb2_set_plane_payload(mb_entry->b, 0, 0); > + vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE); > + } > + spin_unlock(&dev->irqlock); > + > + clear_work_bit(ctx); > + > + if (test_and_clear_bit(0, &dev->hw_lock) == 0) > + WARN_ON(1); > + > + s5p_mfc_clock_off(); > + wake_up(&ctx->queue); > + s5p_mfc_try_run(dev); > +} > + > /* Interrupt processing */ > static irqreturn_t s5p_mfc_irq(int irq, void *priv) > { > @@ -614,6 +649,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) > case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: > s5p_mfc_handle_init_buffers(ctx, reason, err); > break; > + > + case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET: > + s5p_mfc_handle_stream_complete(ctx, reason, err); > + break; > + > default: > mfc_debug(2, "Unknown int reason\n"); > s5p_mfc_clear_int_flags(dev); > @@ -882,9 +922,12 @@ static unsigned int s5p_mfc_poll(struct file *file, > goto end; > } > mutex_unlock(&dev->mfc_mutex); > + poll_wait(file, &ctx->fh.wait, wait); > poll_wait(file, &src_q->done_wq, wait); > poll_wait(file, &dst_q->done_wq, wait); > mutex_lock(&dev->mfc_mutex); > + if (v4l2_event_pending(&ctx->fh)) > + rc |= POLLPRI; > spin_lock_irqsave(&src_q->done_lock, flags); > if (!list_empty(&src_q->done_list)) > src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer, > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h > b/drivers/media/video/s5p-mfc/s5p_mfc_common.h > index bd5706a..8871f0d 100644 > --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h > +++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h > @@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg { > MFC_DEC_RES_CHANGE, > }; > > +#define MFC_BUF_FLAG_USED(1 << 0) > +#define MFC_BUF_FLAG_EOS (1 << 1) > + > struct s5p_mfc_ctx; > > /** > @@ -161,7 +164,7 @@ struct s5p_mfc_buf { > } raw; > size_t stream; > } cookie; > - int used; > + int flags; > }; > > /** > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c > b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c > index 08a5cfe..002af2b 100644 > --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c > +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c > @@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) > release_firmware(fw_blob); > return -EIO; > } > - dev->bank2 = bank2_base_phys; > + /* Valid buffers passed to MFC encoder with LAST_FRAME command > + * should not have address of bank2 - MFC will treat
[PATCH,RESEND] v4l/s5p-mfc: added support for end of stream handling in MFC encoder
s5p-mfc encoder after receiving V4L2_ENC_CMD_STOP command will instruct MFC device to release all encoded frames. After dequeuing last encoded frame driver will generate V4L2_EVENT_EOS event. Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park --- I have removed bank2 alignement fix from this patch. It is is already done by patch 's5p-mfc: Fix second memory bank alignment'. --- drivers/media/video/s5p-mfc/s5p_mfc.c| 43 +++ drivers/media/video/s5p-mfc/s5p_mfc_common.h |5 +- drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c |6 +- drivers/media/video/s5p-mfc/s5p_mfc_dec.c|4 +- drivers/media/video/s5p-mfc/s5p_mfc_enc.c| 106 +- drivers/media/video/s5p-mfc/s5p_mfc_opr.c| 48 +--- 6 files changed, 177 insertions(+), 35 deletions(-) diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c index 9bb68e7..dc9355c 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include "regs-mfc.h" @@ -539,6 +540,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, } } +static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, +unsigned int reason, unsigned int err) +{ + struct s5p_mfc_dev *dev = ctx->dev; + struct s5p_mfc_buf *mb_entry; + + mfc_debug(2, "Stream completed"); + + s5p_mfc_clear_int_flags(dev); + ctx->int_type = reason; + ctx->int_err = err; + ctx->state = MFCINST_FINISHED; + + spin_lock(&dev->irqlock); + if (!list_empty(&ctx->dst_queue)) { + mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, + list); + list_del(&mb_entry->list); + ctx->dst_queue_cnt--; + vb2_set_plane_payload(mb_entry->b, 0, 0); + vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE); + } + spin_unlock(&dev->irqlock); + + clear_work_bit(ctx); + + if (test_and_clear_bit(0, &dev->hw_lock) == 0) + WARN_ON(1); + + s5p_mfc_clock_off(); + wake_up(&ctx->queue); + s5p_mfc_try_run(dev); +} + /* Interrupt processing */ static irqreturn_t s5p_mfc_irq(int irq, void *priv) { @@ -614,6 +649,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: s5p_mfc_handle_init_buffers(ctx, reason, err); break; + + case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET: + s5p_mfc_handle_stream_complete(ctx, reason, err); + break; + default: mfc_debug(2, "Unknown int reason\n"); s5p_mfc_clear_int_flags(dev); @@ -882,9 +922,12 @@ static unsigned int s5p_mfc_poll(struct file *file, goto end; } mutex_unlock(&dev->mfc_mutex); + poll_wait(file, &ctx->fh.wait, wait); poll_wait(file, &src_q->done_wq, wait); poll_wait(file, &dst_q->done_wq, wait); mutex_lock(&dev->mfc_mutex); + if (v4l2_event_pending(&ctx->fh)) + rc |= POLLPRI; spin_lock_irqsave(&src_q->done_lock, flags); if (!list_empty(&src_q->done_list)) src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer, diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h index bd5706a..8871f0d 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h @@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg { MFC_DEC_RES_CHANGE, }; +#define MFC_BUF_FLAG_USED (1 << 0) +#define MFC_BUF_FLAG_EOS (1 << 1) + struct s5p_mfc_ctx; /** @@ -161,7 +164,7 @@ struct s5p_mfc_buf { } raw; size_t stream; } cookie; - int used; + int flags; }; /** diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c index 08a5cfe..002af2b 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c @@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) release_firmware(fw_blob); return -EIO; } - dev->bank2 = bank2_base_phys; + /* Valid buffers passed to MFC encoder with LAST_FRAME command +* should not have address of bank2 - MFC will treat it as a null frame. +* To avoid such situation we set bank2 address below the pool address. +*/ + dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER); memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); wmb(); release_firmware(fw_blob); diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/medi
[PATCH,RESEND] v4l/s5p-mfc: added support for end of stream handling in MFC encoder
s5p-mfc encoder after receiving V4L2_ENC_CMD_STOP command will instruct MFC device to release all encoded frames. After dequeuing last encoded frame driver will generate V4L2_EVENT_EOS event. Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park --- drivers/media/video/s5p-mfc/s5p_mfc.c| 43 +++ drivers/media/video/s5p-mfc/s5p_mfc_common.h |5 +- drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c |8 ++- drivers/media/video/s5p-mfc/s5p_mfc_dec.c|4 +- drivers/media/video/s5p-mfc/s5p_mfc_enc.c| 106 +- drivers/media/video/s5p-mfc/s5p_mfc_opr.c| 48 +--- 6 files changed, 178 insertions(+), 36 deletions(-) diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c index 9bb68e7..dc9355c 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include "regs-mfc.h" @@ -539,6 +540,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, } } +static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, +unsigned int reason, unsigned int err) +{ + struct s5p_mfc_dev *dev = ctx->dev; + struct s5p_mfc_buf *mb_entry; + + mfc_debug(2, "Stream completed"); + + s5p_mfc_clear_int_flags(dev); + ctx->int_type = reason; + ctx->int_err = err; + ctx->state = MFCINST_FINISHED; + + spin_lock(&dev->irqlock); + if (!list_empty(&ctx->dst_queue)) { + mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, + list); + list_del(&mb_entry->list); + ctx->dst_queue_cnt--; + vb2_set_plane_payload(mb_entry->b, 0, 0); + vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE); + } + spin_unlock(&dev->irqlock); + + clear_work_bit(ctx); + + if (test_and_clear_bit(0, &dev->hw_lock) == 0) + WARN_ON(1); + + s5p_mfc_clock_off(); + wake_up(&ctx->queue); + s5p_mfc_try_run(dev); +} + /* Interrupt processing */ static irqreturn_t s5p_mfc_irq(int irq, void *priv) { @@ -614,6 +649,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: s5p_mfc_handle_init_buffers(ctx, reason, err); break; + + case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET: + s5p_mfc_handle_stream_complete(ctx, reason, err); + break; + default: mfc_debug(2, "Unknown int reason\n"); s5p_mfc_clear_int_flags(dev); @@ -882,9 +922,12 @@ static unsigned int s5p_mfc_poll(struct file *file, goto end; } mutex_unlock(&dev->mfc_mutex); + poll_wait(file, &ctx->fh.wait, wait); poll_wait(file, &src_q->done_wq, wait); poll_wait(file, &dst_q->done_wq, wait); mutex_lock(&dev->mfc_mutex); + if (v4l2_event_pending(&ctx->fh)) + rc |= POLLPRI; spin_lock_irqsave(&src_q->done_lock, flags); if (!list_empty(&src_q->done_list)) src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer, diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h index bd5706a..8871f0d 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h @@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg { MFC_DEC_RES_CHANGE, }; +#define MFC_BUF_FLAG_USED (1 << 0) +#define MFC_BUF_FLAG_EOS (1 << 1) + struct s5p_mfc_ctx; /** @@ -161,7 +164,7 @@ struct s5p_mfc_buf { } raw; size_t stream; } cookie; - int used; + int flags; }; /** diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c index 08a5cfe..84c5b8f 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c @@ -78,7 +78,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) } dev->bank1 = s5p_mfc_bitproc_phys; b_base = vb2_dma_contig_memops.alloc( - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER); + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER); if (IS_ERR(b_base)) { vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); s5p_mfc_bitproc_phys = 0; @@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) release_firmware(fw_blob); return -EIO; } - dev->bank2 = bank2_base_phys; + /* Valid buffers passed to MFC encoder with LAST_FRAME command +* should not have address of bank2 - MFC will treat it as a null frame. +