Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-09-11 Thread Sylwester Nawrocki
Hi Shaik,

On 09/10/2013 02:37 PM, Shaik Ameer Basha wrote:
 Hi Sylwester,
 
 Almost all of the comments are already addressed.
 Will try to post the v3 by tomorrow.
 
 I have one doubt?
 Do I need to rebase this driver on m2m-helpers-v2 or once the driver
 is merged we can take this up?

Sorry, I didn't even post an RFC for those helpers, I'll try to do it
today. Nevertheless this is something that isn't yet in mainline nor
in any stable branch, so don't worry about it. It can be handled easily
by a follow up patch, it would be mostly code deletion anyway.

--
Regards,
Sylwester
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-09-10 Thread Shaik Ameer Basha
Hi Sylwester,

Almost all of the comments are already addressed.
Will try to post the v3 by tomorrow.

I have one doubt?
Do I need to rebase this driver on m2m-helpers-v2 or once the driver
is merged we can take this up?

Regards,
Shaik Ameer Basha


On Thu, Aug 29, 2013 at 6:51 PM, Sylwester Nawrocki
s.nawro...@samsung.com wrote:
 On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
 This patch adds the memory to memory (m2m) interface functionality
 for the M-Scaler driver.

 Signed-off-by: Shaik Ameer Basha shaik.am...@samsung.com
 ---
  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
 +
  1 file changed, 763 insertions(+)
  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c

 diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
 b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 new file mode 100644
 index 000..fecbb57
 --- /dev/null
 +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 @@ -0,0 +1,763 @@
 +/*
 + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.

 2013 - 2014 ??

 + *   http://www.samsung.com
 + *
 + * Samsung EXYNOS5 SoC series M-Scaler driver
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published
 + * by the Free Software Foundation, either version 2 of the License,
 + * or (at your option) any later version.
 + */
 +
 +#include linux/module.h
 +#include linux/pm_runtime.h
 +#include linux/slab.h
 +
 +#include media/v4l2-ioctl.h
 +
 +#include mscl-core.h
 +
 +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
 +{
 + struct mscl_ctx *curr_ctx;
 + struct mscl_dev *mscl = ctx-mscl_dev;
 + int ret;
 +
 + curr_ctx = v4l2_m2m_get_curr_priv(mscl-m2m.m2m_dev);
 + if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
 + return 0;
 +
 + mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
 + ret = wait_event_timeout(mscl-irq_queue,
 + !mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
 + MSCL_SHUTDOWN_TIMEOUT);
 +
 + return ret == 0 ? -ETIMEDOUT : ret;
 +}
 +
 +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
 +{
 + struct mscl_ctx *ctx = q-drv_priv;
 + int ret;
 +
 + ret = pm_runtime_get_sync(ctx-mscl_dev-pdev-dev);
 +
 + return ret  0 ? 0 : ret;
 +}
 +
 +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
 +{
 + struct mscl_ctx *ctx = q-drv_priv;
 + int ret;
 +
 + ret = mscl_m2m_ctx_stop_req(ctx);
 + if (ret == -ETIMEDOUT)
 + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +
 + pm_runtime_put(ctx-mscl_dev-pdev-dev);
 +
 + return 0;
 +}
 +
 +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
 +{
 + struct vb2_buffer *src_vb, *dst_vb;
 +
 + if (!ctx || !ctx-m2m_ctx)
 + return;
 +
 + src_vb = v4l2_m2m_src_buf_remove(ctx-m2m_ctx);
 + dst_vb = v4l2_m2m_dst_buf_remove(ctx-m2m_ctx);
 +
 + if (src_vb  dst_vb) {
 + v4l2_m2m_buf_done(src_vb, vb_state);
 + v4l2_m2m_buf_done(dst_vb, vb_state);
 +
 + v4l2_m2m_job_finish(ctx-mscl_dev-m2m.m2m_dev,
 + ctx-m2m_ctx);
 + }
 +}
 +
 +

 Stray empty line.

 +static void mscl_m2m_job_abort(void *priv)
 +{
 + struct mscl_ctx *ctx = priv;
 + int ret;
 +
 + ret = mscl_m2m_ctx_stop_req(ctx);
 + if (ret == -ETIMEDOUT)
 + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +}
 +
 +static int mscl_get_bufs(struct mscl_ctx *ctx)
 +{
 + struct mscl_frame *s_frame, *d_frame;
 + struct vb2_buffer *src_vb, *dst_vb;
 + int ret;
 +
 + s_frame = ctx-s_frame;
 + d_frame = ctx-d_frame;
 +
 + src_vb = v4l2_m2m_next_src_buf(ctx-m2m_ctx);
 + ret = mscl_prepare_addr(ctx, src_vb, s_frame, s_frame-addr);
 + if (ret)

 How about using if (ret  0) pattern consistently ?

 + return ret;
 +
 + dst_vb = v4l2_m2m_next_dst_buf(ctx-m2m_ctx);
 + ret = mscl_prepare_addr(ctx, dst_vb, d_frame, d_frame-addr);
 + if (ret)
 + return ret;
 +
 + dst_vb-v4l2_buf.timestamp = src_vb-v4l2_buf.timestamp;
 +
 + return 0;
 +}
 +
 +static void mscl_m2m_device_run(void *priv)
 +{
 + struct mscl_ctx *ctx = priv;
 + struct mscl_dev *mscl;
 + unsigned long flags;
 + int ret;
 + bool is_set = false;

 Unneeded initialization. And I can see a room for improvement WRT
 the variable's name.

 +
 + if (WARN(!ctx, null hardware context\n))
 + return;
 +
 + mscl = ctx-mscl_dev;
 + spin_lock_irqsave(mscl-slock, flags);
 +
 + set_bit(ST_M2M_PEND, mscl-state);
 +
 + /* Reconfigure hardware if the context has changed. */
 + if (mscl-m2m.ctx != ctx) {
 + dev_dbg(mscl-pdev-dev,
 + mscl-m2m.ctx = 0x%p, current_ctx = 0x%p,
 + mscl-m2m.ctx, ctx);
 + ctx-state |= 

Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-08-29 Thread Sylwester Nawrocki
On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
 This patch adds the memory to memory (m2m) interface functionality
 for the M-Scaler driver.
 
 Signed-off-by: Shaik Ameer Basha shaik.am...@samsung.com
 ---
  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
 +
  1 file changed, 763 insertions(+)
  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c
 
 diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
 b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 new file mode 100644
 index 000..fecbb57
 --- /dev/null
 +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 @@ -0,0 +1,763 @@
 +/*
 + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.

2013 - 2014 ??

 + *   http://www.samsung.com
 + *
 + * Samsung EXYNOS5 SoC series M-Scaler driver
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published
 + * by the Free Software Foundation, either version 2 of the License,
 + * or (at your option) any later version.
 + */
 +
 +#include linux/module.h
 +#include linux/pm_runtime.h
 +#include linux/slab.h
 +
 +#include media/v4l2-ioctl.h
 +
 +#include mscl-core.h
 +
 +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
 +{
 + struct mscl_ctx *curr_ctx;
 + struct mscl_dev *mscl = ctx-mscl_dev;
 + int ret;
 +
 + curr_ctx = v4l2_m2m_get_curr_priv(mscl-m2m.m2m_dev);
 + if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
 + return 0;
 +
 + mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
 + ret = wait_event_timeout(mscl-irq_queue,
 + !mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
 + MSCL_SHUTDOWN_TIMEOUT);
 +
 + return ret == 0 ? -ETIMEDOUT : ret;
 +}
 +
 +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
 +{
 + struct mscl_ctx *ctx = q-drv_priv;
 + int ret;
 +
 + ret = pm_runtime_get_sync(ctx-mscl_dev-pdev-dev);
 +
 + return ret  0 ? 0 : ret;
 +}
 +
 +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
 +{
 + struct mscl_ctx *ctx = q-drv_priv;
 + int ret;
 +
 + ret = mscl_m2m_ctx_stop_req(ctx);
 + if (ret == -ETIMEDOUT)
 + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +
 + pm_runtime_put(ctx-mscl_dev-pdev-dev);
 +
 + return 0;
 +}
 +
 +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
 +{
 + struct vb2_buffer *src_vb, *dst_vb;
 +
 + if (!ctx || !ctx-m2m_ctx)
 + return;
 +
 + src_vb = v4l2_m2m_src_buf_remove(ctx-m2m_ctx);
 + dst_vb = v4l2_m2m_dst_buf_remove(ctx-m2m_ctx);
 +
 + if (src_vb  dst_vb) {
 + v4l2_m2m_buf_done(src_vb, vb_state);
 + v4l2_m2m_buf_done(dst_vb, vb_state);
 +
 + v4l2_m2m_job_finish(ctx-mscl_dev-m2m.m2m_dev,
 + ctx-m2m_ctx);
 + }
 +}
 +
 +

Stray empty line.

 +static void mscl_m2m_job_abort(void *priv)
 +{
 + struct mscl_ctx *ctx = priv;
 + int ret;
 +
 + ret = mscl_m2m_ctx_stop_req(ctx);
 + if (ret == -ETIMEDOUT)
 + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +}
 +
 +static int mscl_get_bufs(struct mscl_ctx *ctx)
 +{
 + struct mscl_frame *s_frame, *d_frame;
 + struct vb2_buffer *src_vb, *dst_vb;
 + int ret;
 +
 + s_frame = ctx-s_frame;
 + d_frame = ctx-d_frame;
 +
 + src_vb = v4l2_m2m_next_src_buf(ctx-m2m_ctx);
 + ret = mscl_prepare_addr(ctx, src_vb, s_frame, s_frame-addr);
 + if (ret)

How about using if (ret  0) pattern consistently ?

 + return ret;
 +
 + dst_vb = v4l2_m2m_next_dst_buf(ctx-m2m_ctx);
 + ret = mscl_prepare_addr(ctx, dst_vb, d_frame, d_frame-addr);
 + if (ret)
 + return ret;
 +
 + dst_vb-v4l2_buf.timestamp = src_vb-v4l2_buf.timestamp;
 +
 + return 0;
 +}
 +
 +static void mscl_m2m_device_run(void *priv)
 +{
 + struct mscl_ctx *ctx = priv;
 + struct mscl_dev *mscl;
 + unsigned long flags;
 + int ret;
 + bool is_set = false;

Unneeded initialization. And I can see a room for improvement WRT
the variable's name.

 +
 + if (WARN(!ctx, null hardware context\n))
 + return;
 +
 + mscl = ctx-mscl_dev;
 + spin_lock_irqsave(mscl-slock, flags);
 +
 + set_bit(ST_M2M_PEND, mscl-state);
 +
 + /* Reconfigure hardware if the context has changed. */
 + if (mscl-m2m.ctx != ctx) {
 + dev_dbg(mscl-pdev-dev,
 + mscl-m2m.ctx = 0x%p, current_ctx = 0x%p,
 + mscl-m2m.ctx, ctx);
 + ctx-state |= MSCL_PARAMS;
 + mscl-m2m.ctx = ctx;
 + }
 +
 + is_set = (ctx-state  MSCL_CTX_STOP_REQ) ? 1 : 0;

Just make it

is_set = ctx-state  MSCL_CTX_STOP_REQ;

 + ctx-state = ~MSCL_CTX_STOP_REQ;
 + if (is_set) {
 + wake_up(mscl-irq_queue);
 + goto put_device;
 + }
 +
 + ret = 

[PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-08-19 Thread Shaik Ameer Basha
This patch adds the memory to memory (m2m) interface functionality
for the M-Scaler driver.

Signed-off-by: Shaik Ameer Basha shaik.am...@samsung.com
---
 drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 +
 1 file changed, 763 insertions(+)
 create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c

diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
b/drivers/media/platform/exynos-mscl/mscl-m2m.c
new file mode 100644
index 000..fecbb57
--- /dev/null
+++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
@@ -0,0 +1,763 @@
+/*
+ * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung EXYNOS5 SoC series M-Scaler driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include linux/module.h
+#include linux/pm_runtime.h
+#include linux/slab.h
+
+#include media/v4l2-ioctl.h
+
+#include mscl-core.h
+
+static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
+{
+   struct mscl_ctx *curr_ctx;
+   struct mscl_dev *mscl = ctx-mscl_dev;
+   int ret;
+
+   curr_ctx = v4l2_m2m_get_curr_priv(mscl-m2m.m2m_dev);
+   if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
+   return 0;
+
+   mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
+   ret = wait_event_timeout(mscl-irq_queue,
+   !mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
+   MSCL_SHUTDOWN_TIMEOUT);
+
+   return ret == 0 ? -ETIMEDOUT : ret;
+}
+
+static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+   struct mscl_ctx *ctx = q-drv_priv;
+   int ret;
+
+   ret = pm_runtime_get_sync(ctx-mscl_dev-pdev-dev);
+
+   return ret  0 ? 0 : ret;
+}
+
+static int mscl_m2m_stop_streaming(struct vb2_queue *q)
+{
+   struct mscl_ctx *ctx = q-drv_priv;
+   int ret;
+
+   ret = mscl_m2m_ctx_stop_req(ctx);
+   if (ret == -ETIMEDOUT)
+   mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+
+   pm_runtime_put(ctx-mscl_dev-pdev-dev);
+
+   return 0;
+}
+
+void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
+{
+   struct vb2_buffer *src_vb, *dst_vb;
+
+   if (!ctx || !ctx-m2m_ctx)
+   return;
+
+   src_vb = v4l2_m2m_src_buf_remove(ctx-m2m_ctx);
+   dst_vb = v4l2_m2m_dst_buf_remove(ctx-m2m_ctx);
+
+   if (src_vb  dst_vb) {
+   v4l2_m2m_buf_done(src_vb, vb_state);
+   v4l2_m2m_buf_done(dst_vb, vb_state);
+
+   v4l2_m2m_job_finish(ctx-mscl_dev-m2m.m2m_dev,
+   ctx-m2m_ctx);
+   }
+}
+
+
+static void mscl_m2m_job_abort(void *priv)
+{
+   struct mscl_ctx *ctx = priv;
+   int ret;
+
+   ret = mscl_m2m_ctx_stop_req(ctx);
+   if (ret == -ETIMEDOUT)
+   mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+}
+
+static int mscl_get_bufs(struct mscl_ctx *ctx)
+{
+   struct mscl_frame *s_frame, *d_frame;
+   struct vb2_buffer *src_vb, *dst_vb;
+   int ret;
+
+   s_frame = ctx-s_frame;
+   d_frame = ctx-d_frame;
+
+   src_vb = v4l2_m2m_next_src_buf(ctx-m2m_ctx);
+   ret = mscl_prepare_addr(ctx, src_vb, s_frame, s_frame-addr);
+   if (ret)
+   return ret;
+
+   dst_vb = v4l2_m2m_next_dst_buf(ctx-m2m_ctx);
+   ret = mscl_prepare_addr(ctx, dst_vb, d_frame, d_frame-addr);
+   if (ret)
+   return ret;
+
+   dst_vb-v4l2_buf.timestamp = src_vb-v4l2_buf.timestamp;
+
+   return 0;
+}
+
+static void mscl_m2m_device_run(void *priv)
+{
+   struct mscl_ctx *ctx = priv;
+   struct mscl_dev *mscl;
+   unsigned long flags;
+   int ret;
+   bool is_set = false;
+
+   if (WARN(!ctx, null hardware context\n))
+   return;
+
+   mscl = ctx-mscl_dev;
+   spin_lock_irqsave(mscl-slock, flags);
+
+   set_bit(ST_M2M_PEND, mscl-state);
+
+   /* Reconfigure hardware if the context has changed. */
+   if (mscl-m2m.ctx != ctx) {
+   dev_dbg(mscl-pdev-dev,
+   mscl-m2m.ctx = 0x%p, current_ctx = 0x%p,
+   mscl-m2m.ctx, ctx);
+   ctx-state |= MSCL_PARAMS;
+   mscl-m2m.ctx = ctx;
+   }
+
+   is_set = (ctx-state  MSCL_CTX_STOP_REQ) ? 1 : 0;
+   ctx-state = ~MSCL_CTX_STOP_REQ;
+   if (is_set) {
+   wake_up(mscl-irq_queue);
+   goto put_device;
+   }
+
+   ret = mscl_get_bufs(ctx);
+   if (ret) {
+   dev_dbg(mscl-pdev-dev, Wrong address);
+   goto put_device;
+   }
+
+   mscl_hw_address_queue_reset(ctx);
+   mscl_set_prefbuf(mscl, ctx-s_frame);
+   mscl_hw_set_input_addr(mscl, ctx-s_frame.addr);
+   

Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-08-19 Thread Hans Verkuil
On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
 This patch adds the memory to memory (m2m) interface functionality
 for the M-Scaler driver.

Just one small comment below...

 
 Signed-off-by: Shaik Ameer Basha shaik.am...@samsung.com
 ---
  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
 +
  1 file changed, 763 insertions(+)
  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c
 
 diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
 b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 new file mode 100644
 index 000..fecbb57
 --- /dev/null
 +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 @@ -0,0 +1,763 @@
 +/*
 + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.
 + *   http://www.samsung.com
 + *
 + * Samsung EXYNOS5 SoC series M-Scaler driver
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published
 + * by the Free Software Foundation, either version 2 of the License,
 + * or (at your option) any later version.
 + */
 +
 +#include linux/module.h
 +#include linux/pm_runtime.h
 +#include linux/slab.h
 +
 +#include media/v4l2-ioctl.h
 +
 +#include mscl-core.h
 +
 +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
 +{
 + struct mscl_ctx *curr_ctx;
 + struct mscl_dev *mscl = ctx-mscl_dev;
 + int ret;
 +
 + curr_ctx = v4l2_m2m_get_curr_priv(mscl-m2m.m2m_dev);
 + if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
 + return 0;
 +
 + mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
 + ret = wait_event_timeout(mscl-irq_queue,
 + !mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
 + MSCL_SHUTDOWN_TIMEOUT);
 +
 + return ret == 0 ? -ETIMEDOUT : ret;
 +}
 +
 +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
 +{
 + struct mscl_ctx *ctx = q-drv_priv;
 + int ret;
 +
 + ret = pm_runtime_get_sync(ctx-mscl_dev-pdev-dev);
 +
 + return ret  0 ? 0 : ret;
 +}
 +
 +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
 +{
 + struct mscl_ctx *ctx = q-drv_priv;
 + int ret;
 +
 + ret = mscl_m2m_ctx_stop_req(ctx);
 + if (ret == -ETIMEDOUT)
 + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +
 + pm_runtime_put(ctx-mscl_dev-pdev-dev);
 +
 + return 0;
 +}
 +
 +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
 +{
 + struct vb2_buffer *src_vb, *dst_vb;
 +
 + if (!ctx || !ctx-m2m_ctx)
 + return;
 +
 + src_vb = v4l2_m2m_src_buf_remove(ctx-m2m_ctx);
 + dst_vb = v4l2_m2m_dst_buf_remove(ctx-m2m_ctx);
 +
 + if (src_vb  dst_vb) {
 + v4l2_m2m_buf_done(src_vb, vb_state);
 + v4l2_m2m_buf_done(dst_vb, vb_state);
 +
 + v4l2_m2m_job_finish(ctx-mscl_dev-m2m.m2m_dev,
 + ctx-m2m_ctx);
 + }
 +}
 +
 +
 +static void mscl_m2m_job_abort(void *priv)
 +{
 + struct mscl_ctx *ctx = priv;
 + int ret;
 +
 + ret = mscl_m2m_ctx_stop_req(ctx);
 + if (ret == -ETIMEDOUT)
 + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +}
 +
 +static int mscl_get_bufs(struct mscl_ctx *ctx)
 +{
 + struct mscl_frame *s_frame, *d_frame;
 + struct vb2_buffer *src_vb, *dst_vb;
 + int ret;
 +
 + s_frame = ctx-s_frame;
 + d_frame = ctx-d_frame;
 +
 + src_vb = v4l2_m2m_next_src_buf(ctx-m2m_ctx);
 + ret = mscl_prepare_addr(ctx, src_vb, s_frame, s_frame-addr);
 + if (ret)
 + return ret;
 +
 + dst_vb = v4l2_m2m_next_dst_buf(ctx-m2m_ctx);
 + ret = mscl_prepare_addr(ctx, dst_vb, d_frame, d_frame-addr);
 + if (ret)
 + return ret;
 +
 + dst_vb-v4l2_buf.timestamp = src_vb-v4l2_buf.timestamp;
 +
 + return 0;
 +}
 +
 +static void mscl_m2m_device_run(void *priv)
 +{
 + struct mscl_ctx *ctx = priv;
 + struct mscl_dev *mscl;
 + unsigned long flags;
 + int ret;
 + bool is_set = false;
 +
 + if (WARN(!ctx, null hardware context\n))
 + return;
 +
 + mscl = ctx-mscl_dev;
 + spin_lock_irqsave(mscl-slock, flags);
 +
 + set_bit(ST_M2M_PEND, mscl-state);
 +
 + /* Reconfigure hardware if the context has changed. */
 + if (mscl-m2m.ctx != ctx) {
 + dev_dbg(mscl-pdev-dev,
 + mscl-m2m.ctx = 0x%p, current_ctx = 0x%p,
 + mscl-m2m.ctx, ctx);
 + ctx-state |= MSCL_PARAMS;
 + mscl-m2m.ctx = ctx;
 + }
 +
 + is_set = (ctx-state  MSCL_CTX_STOP_REQ) ? 1 : 0;
 + ctx-state = ~MSCL_CTX_STOP_REQ;
 + if (is_set) {
 + wake_up(mscl-irq_queue);
 + goto put_device;
 + }
 +
 + ret = mscl_get_bufs(ctx);
 + if (ret) {
 + dev_dbg(mscl-pdev-dev, Wrong address);
 + goto put_device;
 + }
 +
 + mscl_hw_address_queue_reset(ctx);
 + mscl_set_prefbuf(mscl, 

Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-08-19 Thread Hans Verkuil
On 08/19/2013 02:58 PM, Hans Verkuil wrote:
 On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
 This patch adds the memory to memory (m2m) interface functionality
 for the M-Scaler driver.
 
 Just one small comment below...
 

 Signed-off-by: Shaik Ameer Basha shaik.am...@samsung.com
 ---
  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
 +
  1 file changed, 763 insertions(+)
  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c

 diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
 b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 new file mode 100644
 index 000..fecbb57
 --- /dev/null
 +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
 @@ -0,0 +1,763 @@
 +/*
 + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.
 + *  http://www.samsung.com
 + *
 + * Samsung EXYNOS5 SoC series M-Scaler driver
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published
 + * by the Free Software Foundation, either version 2 of the License,
 + * or (at your option) any later version.
 + */
 +
 +#include linux/module.h
 +#include linux/pm_runtime.h
 +#include linux/slab.h
 +
 +#include media/v4l2-ioctl.h
 +
 +#include mscl-core.h
 +
 +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
 +{
 +struct mscl_ctx *curr_ctx;
 +struct mscl_dev *mscl = ctx-mscl_dev;
 +int ret;
 +
 +curr_ctx = v4l2_m2m_get_curr_priv(mscl-m2m.m2m_dev);
 +if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
 +return 0;
 +
 +mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
 +ret = wait_event_timeout(mscl-irq_queue,
 +!mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
 +MSCL_SHUTDOWN_TIMEOUT);
 +
 +return ret == 0 ? -ETIMEDOUT : ret;
 +}
 +
 +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
 +{
 +struct mscl_ctx *ctx = q-drv_priv;
 +int ret;
 +
 +ret = pm_runtime_get_sync(ctx-mscl_dev-pdev-dev);
 +
 +return ret  0 ? 0 : ret;
 +}
 +
 +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
 +{
 +struct mscl_ctx *ctx = q-drv_priv;
 +int ret;
 +
 +ret = mscl_m2m_ctx_stop_req(ctx);
 +if (ret == -ETIMEDOUT)
 +mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +
 +pm_runtime_put(ctx-mscl_dev-pdev-dev);
 +
 +return 0;
 +}
 +
 +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
 +{
 +struct vb2_buffer *src_vb, *dst_vb;
 +
 +if (!ctx || !ctx-m2m_ctx)
 +return;
 +
 +src_vb = v4l2_m2m_src_buf_remove(ctx-m2m_ctx);
 +dst_vb = v4l2_m2m_dst_buf_remove(ctx-m2m_ctx);
 +
 +if (src_vb  dst_vb) {
 +v4l2_m2m_buf_done(src_vb, vb_state);
 +v4l2_m2m_buf_done(dst_vb, vb_state);
 +
 +v4l2_m2m_job_finish(ctx-mscl_dev-m2m.m2m_dev,
 +ctx-m2m_ctx);
 +}
 +}
 +
 +
 +static void mscl_m2m_job_abort(void *priv)
 +{
 +struct mscl_ctx *ctx = priv;
 +int ret;
 +
 +ret = mscl_m2m_ctx_stop_req(ctx);
 +if (ret == -ETIMEDOUT)
 +mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 +}
 +
 +static int mscl_get_bufs(struct mscl_ctx *ctx)
 +{
 +struct mscl_frame *s_frame, *d_frame;
 +struct vb2_buffer *src_vb, *dst_vb;
 +int ret;
 +
 +s_frame = ctx-s_frame;
 +d_frame = ctx-d_frame;
 +
 +src_vb = v4l2_m2m_next_src_buf(ctx-m2m_ctx);
 +ret = mscl_prepare_addr(ctx, src_vb, s_frame, s_frame-addr);
 +if (ret)
 +return ret;
 +
 +dst_vb = v4l2_m2m_next_dst_buf(ctx-m2m_ctx);
 +ret = mscl_prepare_addr(ctx, dst_vb, d_frame, d_frame-addr);
 +if (ret)
 +return ret;
 +
 +dst_vb-v4l2_buf.timestamp = src_vb-v4l2_buf.timestamp;
 +
 +return 0;
 +}
 +
 +static void mscl_m2m_device_run(void *priv)
 +{
 +struct mscl_ctx *ctx = priv;
 +struct mscl_dev *mscl;
 +unsigned long flags;
 +int ret;
 +bool is_set = false;
 +
 +if (WARN(!ctx, null hardware context\n))
 +return;
 +
 +mscl = ctx-mscl_dev;
 +spin_lock_irqsave(mscl-slock, flags);
 +
 +set_bit(ST_M2M_PEND, mscl-state);
 +
 +/* Reconfigure hardware if the context has changed. */
 +if (mscl-m2m.ctx != ctx) {
 +dev_dbg(mscl-pdev-dev,
 +mscl-m2m.ctx = 0x%p, current_ctx = 0x%p,
 +mscl-m2m.ctx, ctx);
 +ctx-state |= MSCL_PARAMS;
 +mscl-m2m.ctx = ctx;
 +}
 +
 +is_set = (ctx-state  MSCL_CTX_STOP_REQ) ? 1 : 0;
 +ctx-state = ~MSCL_CTX_STOP_REQ;
 +if (is_set) {
 +wake_up(mscl-irq_queue);
 +goto put_device;
 +}
 +
 +ret = mscl_get_bufs(ctx);
 +if (ret) {
 +dev_dbg(mscl-pdev-dev, Wrong address);
 +goto put_device;
 +}
 +
 +mscl_hw_address_queue_reset(ctx);
 +mscl_set_prefbuf(mscl, ctx-s_frame);
 +