RE: [PATCH,RESEND] v4l/s5p-mfc: added support for end of stream handling in MFC encoder

2012-08-10 Thread Kamil Debski
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

2012-08-10 Thread Andrzej Hajda
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

2012-08-08 Thread Andrzej Hajda
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.
+