Re: [PATCH RFC v3 1/3] V4L: Add driver for S3C244X/S3C64XX SoC series camera interface

2012-11-25 Thread Alexey Klimov
Hi Sylwester,

On Sat, Nov 17, 2012 at 2:39 AM, Sylwester Nawrocki
sylvester.nawro...@gmail.com wrote:
 Hi Alexey,


 On 11/16/2012 03:10 PM, Alexey Klimov wrote:

 +static int s3c_camif_hw_init(struct camif_dev *camif, struct camif_vp
 *vp)
 +{
 +   unsigned int ip_rev = camif-variant-ip_revision;
 +   unsigned long flags;
 +
 +   if (camif-sensor.sd == NULL || vp-out_fmt == NULL)
 +   return -EINVAL;
 +
 +   spin_lock_irqsave(camif-slock, flags);
 +
 +   if (ip_rev == S3C244X_CAMIF_IP_REV)
 +   camif_hw_clear_fifo_overflow(vp);
 +   camif_hw_set_camera_bus(camif);
 +   camif_hw_set_source_format(camif);
 +   camif_hw_set_camera_crop(camif);
 +   camif_hw_set_test_pattern(camif, camif-test_pattern-val);
 +   if (ip_rev == S3C6410_CAMIF_IP_REV)
 +   camif_hw_set_input_path(vp);
 +   camif_cfg_video_path(vp);
 +   vp-state= ~ST_VP_CONFIG;

 +
 +   spin_unlock_irqrestore(camif-slock, flags);
 +   return 0;
 +}
 +
 +/*
 + * Initialize the video path, only up from the scaler stage. The camera
 + * input interface set up is skipped. This is useful to enable one of
 the
 + * video paths when the other is already running.
 + */
 +static int s3c_camif_hw_vp_init(struct camif_dev *camif, struct
 camif_vp
 *vp)
 +{
 +   unsigned int ip_rev = camif-variant-ip_revision;
 +   unsigned long flags;
 +
 +   if (vp-out_fmt == NULL)
 +   return -EINVAL;
 +
 +   spin_lock_irqsave(camif-slock, flags);
 +   camif_prepare_dma_offset(vp);
 +   if (ip_rev == S3C244X_CAMIF_IP_REV)
 +   camif_hw_clear_fifo_overflow(vp);
 +   camif_cfg_video_path(vp);
 +   if (ip_rev == S3C6410_CAMIF_IP_REV)
 +   camif_hw_set_effect(vp, false);
 +   vp-state= ~ST_VP_CONFIG;

 +
 +   spin_unlock_irqrestore(camif-slock, flags);
 +   return 0;
 +}

 ...

 +/*
 + * Reinitialize the driver so it is ready to start streaming again.
 + * Return any buffers to vb2, perform CAMIF software reset and
 + * turn off streaming at the data pipeline (sensor) if required.
 + */
 +static int camif_reinitialize(struct camif_vp *vp)
 +{
 +   struct camif_dev *camif = vp-camif;
 +   struct camif_buffer *buf;
 +   unsigned long flags;
 +   bool streaming;
 +
 +   spin_lock_irqsave(camif-slock, flags);
 +   streaming = vp-state  ST_VP_SENSOR_STREAMING;
 +
 +   vp-state= ~(ST_VP_PENDING | ST_VP_RUNNING | ST_VP_OFF |

 +  ST_VP_ABORTING | ST_VP_STREAMING |
 +  ST_VP_SENSOR_STREAMING | ST_VP_LASTIRQ);
 +
 +   /* Release unused buffers */
 +   while (!list_empty(vp-pending_buf_q)) {
 +   buf = camif_pending_queue_pop(vp);
 +   vb2_buffer_done(buf-vb, VB2_BUF_STATE_ERROR);
 +   }
 +
 +   while (!list_empty(vp-active_buf_q)) {
 +   buf = camif_active_queue_pop(vp);
 +   vb2_buffer_done(buf-vb, VB2_BUF_STATE_ERROR);
 +   }
 +
 +   spin_unlock_irqrestore(camif-slock, flags);
 +
 +   if (!streaming)
 +   return 0;
 +
 +   return sensor_set_streaming(camif, 0);
 +}

 ...

 +static int start_streaming(struct vb2_queue *vq, unsigned int count)
 +{
 +   struct camif_vp *vp = vb2_get_drv_priv(vq);
 +   struct camif_dev *camif = vp-camif;
 +   unsigned long flags;
 +   int ret;
 +
 +   /*
 +* We assume the codec capture path is always activated
 +* first, before the preview path starts streaming.
 +* This is required to avoid internal FIFO overflow and
 +* a need for CAMIF software reset.
 +*/
 +   spin_lock_irqsave(camif-slock, flags);


 Here.


 +
 +   if (camif-stream_count == 0) {
 +   camif_hw_reset(camif);
 +   spin_unlock_irqrestore(camif-slock, flags);
 +   ret = s3c_camif_hw_init(camif, vp);
 +   } else {
 +   spin_unlock_irqrestore(camif-slock, flags);
 +   ret = s3c_camif_hw_vp_init(camif, vp);
 +   }
 +
 +   if (ret  0) {
 +   camif_reinitialize(vp);
 +   return ret;
 +   }
 +
 +   spin_lock_irqsave(camif-slock, flags);


 Could you please check this function? Is it ok that you have double
 spin_lock_irqsave()? I don't know may be it's okay. Also when you call
 camif_reinitialize() you didn't call spin_unlock_irqrestore() before and
 inside camif_reinitialize() you will also call spin_lock_irqsave()..


 Certainly with nested spinlock locking this code would have been useless.
 I suppose this is what you mean by double spin_lock_irqsave(). Since
 it is known to work there must be spin_unlock_irqrestore() somewhere,
 before the second spin_lock_irqsave() above. Just look around with more
 focus ;)

You are right. I'm very sorry, i need to be more focus :)

-- 
Best regards, Klimov Alexey
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a 

Re: [PATCH RFC v3 1/3] V4L: Add driver for S3C244X/S3C64XX SoC series camera interface

2012-11-17 Thread Sylwester Nawrocki

Hi Hans,

On 11/16/2012 02:45 PM, Hans Verkuil wrote:

Hi Sylwester,

Just one comment, see below...

On Thu November 15 2012 23:05:13 Sylwester Nawrocki wrote:

This patch adds V4L2 driver for Samsung S3C244X/S3C64XX SoC series
camera interface. The driver exposes a subdev device node for CAMIF
pixel resolution and crop control and two video capture nodes - for
the codec and preview data paths. It has been tested on Mini2440
(s3c2440) and Mini6410 (s3c6410) board with gstreamer and mplayer.

Signed-off-by: Sylwester Nawrockisylvester.nawro...@gmail.com
Signed-off-by: Tomasz Figatomasz.f...@gmail.com
---

...

+static int s3c_camif_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+   struct camif_vp *vp = video_drvdata(file);
+   struct camif_dev *camif = vp-camif;
+   struct media_entity *sensor =camif-sensor.sd-entity;
+   int ret;
+
+   pr_debug([vp%d]\n, vp-id);
+
+   if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+   return -EINVAL;
+
+   if (vp-owner  vp-owner != priv)
+   return -EBUSY;
+
+   if (s3c_vp_active(vp))
+   return 0;
+
+   ret = media_entity_pipeline_start(sensor, camif-m_pipeline);
+   if (ret  0)
+   return ret;
+
+   ret = camif_pipeline_validate(camif);
+   if (ret  0) {
+   media_entity_pipeline_stop(sensor);
+   return ret;
+   }
+
+   return vb2_streamon(vp-vb_queue, type);
+}
+
+static int s3c_camif_streamoff(struct file *file, void *priv,
+  enum v4l2_buf_type type)
+{
+   struct camif_vp *vp = video_drvdata(file);
+   struct camif_dev *camif = vp-camif;
+   int ret;
+
+   pr_debug([vp%d]\n, vp-id);
+
+   if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+   return -EINVAL;
+
+   if (vp-owner  vp-owner != priv)
+   return -EBUSY;
+
+   ret = vb2_streamoff(vp-vb_queue, type);
+   if (ret == 0)
+   media_entity_pipeline_stop(camif-sensor.sd-entity);
+   return ret;
+}
+
+static int s3c_camif_reqbufs(struct file *file, void *priv,
+struct v4l2_requestbuffers *rb)
+{
+   struct camif_vp *vp = video_drvdata(file);
+   int ret;
+
+   pr_debug([vp%d] rb count: %d, owner: %p, priv: %p\n,
+vp-id, rb-count, vp-owner, priv);
+
+   if (vp-owner  vp-owner != priv)
+   return -EBUSY;
+
+   if (rb-count)
+   rb-count = max_t(u32, CAMIF_REQ_BUFS_MIN, rb-count);
+   else
+   vp-owner = NULL;
+
+   ret = vb2_reqbufs(vp-vb_queue, rb);
+   if (!ret) {
+   vp-reqbufs_count = rb-count;
+   if (vp-owner == NULL  rb-count  0)
+   vp-owner = priv;
+   }
+
+   return ret;
+}
+
+static int s3c_camif_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+   struct camif_vp *vp = video_drvdata(file);
+   return vb2_querybuf(vp-vb_queue, buf);
+}
+
+static int s3c_camif_qbuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+   struct camif_vp *vp = video_drvdata(file);
+
+   pr_debug([vp%d]\n, vp-id);
+
+   if (vp-owner  vp-owner != priv)
+   return -EBUSY;
+
+   return vb2_qbuf(vp-vb_queue, buf);
+}
+
+static int s3c_camif_dqbuf(struct file *file, void *priv,
+  struct v4l2_buffer *buf)
+{
+   struct camif_vp *vp = video_drvdata(file);
+
+   pr_debug([vp%d] sequence: %d\n, vp-id, vp-frame_sequence);
+
+   if (vp-owner  vp-owner != priv)
+   return -EBUSY;
+
+   return vb2_dqbuf(vp-vb_queue, buf, file-f_flags  O_NONBLOCK);
+}
+
+static int s3c_camif_create_bufs(struct file *file, void *priv,
+struct v4l2_create_buffers *create)
+{
+   struct camif_vp *vp = video_drvdata(file);
+   int ret;
+
+   if (vp-owner  vp-owner != priv)
+   return -EBUSY;
+
+   create-count = max_t(u32, 1, create-count);
+   ret = vb2_create_bufs(vp-vb_queue, create);
+
+   if (!ret  vp-owner == NULL)
+   vp-owner = priv;
+
+   return ret;
+}
+
+static int s3c_camif_prepare_buf(struct file *file, void *priv,
+struct v4l2_buffer *b)
+{
+   struct camif_vp *vp = video_drvdata(file);
+   return vb2_prepare_buf(vp-vb_queue, b);
+}
+


Are you aware of the vb2 ioctl helper functions I've added? See 
videobuf2-core.h,
at the end.


Yes, I just chose not to introduce these helpers now, to make any 
back-porting

of this driver to older kernels easier.


They can probably replace some of these ioctls. It's something you can do later
in a separate patch, so this isn't blocking as far as I am concerned. It's just
a hint.


Thanks, I'll see which ones can be replaced. But I would prefer to make it
a separate patch for subsequent kernel 

Re: [PATCH RFC v3 1/3] V4L: Add driver for S3C244X/S3C64XX SoC series camera interface

2012-11-16 Thread Hans Verkuil
Hi Sylwester,

Just one comment, see below...

On Thu November 15 2012 23:05:13 Sylwester Nawrocki wrote:
 This patch adds V4L2 driver for Samsung S3C244X/S3C64XX SoC series
 camera interface. The driver exposes a subdev device node for CAMIF
 pixel resolution and crop control and two video capture nodes - for
 the codec and preview data paths. It has been tested on Mini2440
 (s3c2440) and Mini6410 (s3c6410) board with gstreamer and mplayer.
 
 Signed-off-by: Sylwester Nawrocki sylvester.nawro...@gmail.com
 Signed-off-by: Tomasz Figa tomasz.f...@gmail.com
 ---
  drivers/media/platform/Kconfig   |   12 +
  drivers/media/platform/Makefile  |1 +
  drivers/media/platform/s3c-camif/Makefile|5 +
  drivers/media/platform/s3c-camif/camif-capture.c | 1636 
 ++
  drivers/media/platform/s3c-camif/camif-core.c|  661 +
  drivers/media/platform/s3c-camif/camif-core.h|  382 +
  drivers/media/platform/s3c-camif/camif-regs.c|  579 
  drivers/media/platform/s3c-camif/camif-regs.h|  267 
  include/media/s3c_camif.h|   45 +
  9 files changed, 3588 insertions(+), 0 deletions(-)
  create mode 100644 drivers/media/platform/s3c-camif/Makefile
  create mode 100644 drivers/media/platform/s3c-camif/camif-capture.c
  create mode 100644 drivers/media/platform/s3c-camif/camif-core.c
  create mode 100644 drivers/media/platform/s3c-camif/camif-core.h
  create mode 100644 drivers/media/platform/s3c-camif/camif-regs.c
  create mode 100644 drivers/media/platform/s3c-camif/camif-regs.h
  create mode 100644 include/media/s3c_camif.h
 
 diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
 index 181c768..3dcfea6 100644
 --- a/drivers/media/platform/Kconfig
 +++ b/drivers/media/platform/Kconfig
 @@ -109,6 +109,18 @@ config VIDEO_OMAP3_DEBUG
   ---help---
 Enable debug messages on OMAP 3 camera controller driver.
  
 +config VIDEO_S3C_CAMIF
 + tristate Samsung S3C24XX/S3C64XX SoC Camera Interface driver
 + depends on VIDEO_V4L2  I2C  VIDEO_V4L2_SUBDEV_API
 + depends on (PLAT_S3C64XX || PLAT_S3C24XX)  PM_RUNTIME
 + select VIDEOBUF2_DMA_CONTIG
 + ---help---
 +   This is a v4l2 driver for s3c24xx and s3c64xx SoC series camera
 +   host interface (CAMIF).
 +
 +   To compile this driver as a module, choose M here: the module
 +   will be called s3c-camif.
 +
  source drivers/media/platform/soc_camera/Kconfig
  source drivers/media/platform/s5p-fimc/Kconfig
  source drivers/media/platform/s5p-tv/Kconfig
 diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
 index baaa550..4817d28 100644
 --- a/drivers/media/platform/Makefile
 +++ b/drivers/media/platform/Makefile
 @@ -27,6 +27,7 @@ obj-$(CONFIG_VIDEO_CODA)+= coda.o
  
  obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)  += m2m-deinterlace.o
  
 +obj-$(CONFIG_VIDEO_S3C_CAMIF)+= s3c-camif/
  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/
  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/
  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)  += s5p-mfc/
 diff --git a/drivers/media/platform/s3c-camif/Makefile 
 b/drivers/media/platform/s3c-camif/Makefile
 new file mode 100644
 index 000..50bf8c5
 --- /dev/null
 +++ b/drivers/media/platform/s3c-camif/Makefile
 @@ -0,0 +1,5 @@
 +# Makefile for s3c244x/s3c64xx CAMIF driver
 +
 +s3c-camif-objs := camif-core.o camif-capture.o camif-regs.o
 +
 +obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif.o
 diff --git a/drivers/media/platform/s3c-camif/camif-capture.c 
 b/drivers/media/platform/s3c-camif/camif-capture.c
 new file mode 100644
 index 000..8daf684
 --- /dev/null
 +++ b/drivers/media/platform/s3c-camif/camif-capture.c
 @@ -0,0 +1,1636 @@
 +/*
 + * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
 + *
 + * Copyright (C) 2012 Sylwester Nawrocki sylvester.nawro...@gmail.com
 + * Copyright (C) 2012 Tomasz Figa tomasz.f...@gmail.com
 + *
 + * Based on drivers/media/platform/s5p-fimc,
 + * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 +*/
 +#define pr_fmt(fmt) %s:%d  fmt, __func__, __LINE__
 +
 +#include linux/bug.h
 +#include linux/clk.h
 +#include linux/device.h
 +#include linux/errno.h
 +#include linux/i2c.h
 +#include linux/interrupt.h
 +#include linux/io.h
 +#include linux/kernel.h
 +#include linux/list.h
 +#include linux/module.h
 +#include linux/platform_device.h
 +#include linux/pm_runtime.h
 +#include linux/ratelimit.h
 +#include linux/slab.h
 +#include linux/types.h
 +#include linux/videodev2.h
 +
 +#include media/media-device.h
 +#include media/v4l2-ctrls.h
 +#include media/v4l2-event.h
 +#include media/v4l2-ioctl.h
 +#include media/videobuf2-core.h
 +#include media/videobuf2-dma-contig.h
 +
 

Re: [PATCH RFC v3 1/3] V4L: Add driver for S3C244X/S3C64XX SoC series camera interface

2012-11-16 Thread Alexey Klimov
Hi Sylwester,

 On Fri, Nov 16, 2012 at 2:05 AM, Sylwester Nawrocki
 sylvester.nawro...@gmail.com wrote:

 This patch adds V4L2 driver for Samsung S3C244X/S3C64XX SoC series
 camera interface. The driver exposes a subdev device node for CAMIF
 pixel resolution and crop control and two video capture nodes - for
 the codec and preview data paths. It has been tested on Mini2440
 (s3c2440) and Mini6410 (s3c6410) board with gstreamer and mplayer.

 Signed-off-by: Sylwester Nawrocki sylvester.nawro...@gmail.com
 Signed-off-by: Tomasz Figa tomasz.f...@gmail.com
 ---
  drivers/media/platform/Kconfig   |   12 +
  drivers/media/platform/Makefile  |1 +
  drivers/media/platform/s3c-camif/Makefile|5 +
  drivers/media/platform/s3c-camif/camif-capture.c | 1636
 ++
  drivers/media/platform/s3c-camif/camif-core.c|  661 +
  drivers/media/platform/s3c-camif/camif-core.h|  382 +
  drivers/media/platform/s3c-camif/camif-regs.c|  579 
  drivers/media/platform/s3c-camif/camif-regs.h|  267 
  include/media/s3c_camif.h|   45 +
  9 files changed, 3588 insertions(+), 0 deletions(-)
  create mode 100644 drivers/media/platform/s3c-camif/Makefile
  create mode 100644 drivers/media/platform/s3c-camif/camif-capture.c
  create mode 100644 drivers/media/platform/s3c-camif/camif-core.c
  create mode 100644 drivers/media/platform/s3c-camif/camif-core.h
  create mode 100644 drivers/media/platform/s3c-camif/camif-regs.c
  create mode 100644 drivers/media/platform/s3c-camif/camif-regs.h
  create mode 100644 include/media/s3c_camif.h

 diff --git a/drivers/media/platform/Kconfig
 b/drivers/media/platform/Kconfig
 index 181c768..3dcfea6 100644
 --- a/drivers/media/platform/Kconfig
 +++ b/drivers/media/platform/Kconfig
 @@ -109,6 +109,18 @@ config VIDEO_OMAP3_DEBUG
 ---help---
   Enable debug messages on OMAP 3 camera controller driver.

 +config VIDEO_S3C_CAMIF
 +   tristate Samsung S3C24XX/S3C64XX SoC Camera Interface driver
 +   depends on VIDEO_V4L2  I2C  VIDEO_V4L2_SUBDEV_API
 +   depends on (PLAT_S3C64XX || PLAT_S3C24XX)  PM_RUNTIME
 +   select VIDEOBUF2_DMA_CONTIG
 +   ---help---
 + This is a v4l2 driver for s3c24xx and s3c64xx SoC series camera
 + host interface (CAMIF).
 +
 + To compile this driver as a module, choose M here: the module
 + will be called s3c-camif.
 +
  source drivers/media/platform/soc_camera/Kconfig
  source drivers/media/platform/s5p-fimc/Kconfig
  source drivers/media/platform/s5p-tv/Kconfig
 diff --git a/drivers/media/platform/Makefile
 b/drivers/media/platform/Makefile
 index baaa550..4817d28 100644
 --- a/drivers/media/platform/Makefile
 +++ b/drivers/media/platform/Makefile
 @@ -27,6 +27,7 @@ obj-$(CONFIG_VIDEO_CODA)  += coda.o

  obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)+= m2m-deinterlace.o

 +obj-$(CONFIG_VIDEO_S3C_CAMIF)  += s3c-camif/
  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC)   += s5p-fimc/
  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)   += s5p-jpeg/
  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)+= s5p-mfc/
 diff --git a/drivers/media/platform/s3c-camif/Makefile
 b/drivers/media/platform/s3c-camif/Makefile
 new file mode 100644
 index 000..50bf8c5
 --- /dev/null
 +++ b/drivers/media/platform/s3c-camif/Makefile
 @@ -0,0 +1,5 @@
 +# Makefile for s3c244x/s3c64xx CAMIF driver
 +
 +s3c-camif-objs := camif-core.o camif-capture.o camif-regs.o
 +
 +obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif.o
 diff --git a/drivers/media/platform/s3c-camif/camif-capture.c
 b/drivers/media/platform/s3c-camif/camif-capture.c
 new file mode 100644
 index 000..8daf684
 --- /dev/null
 +++ b/drivers/media/platform/s3c-camif/camif-capture.c
 @@ -0,0 +1,1636 @@
 +/*
 + * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
 + *
 + * Copyright (C) 2012 Sylwester Nawrocki sylvester.nawro...@gmail.com
 + * Copyright (C) 2012 Tomasz Figa tomasz.f...@gmail.com
 + *
 + * Based on drivers/media/platform/s5p-fimc,
 + * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 +*/
 +#define pr_fmt(fmt) %s:%d  fmt, __func__, __LINE__
 +
 +#include linux/bug.h
 +#include linux/clk.h
 +#include linux/device.h
 +#include linux/errno.h
 +#include linux/i2c.h
 +#include linux/interrupt.h
 +#include linux/io.h
 +#include linux/kernel.h
 +#include linux/list.h
 +#include linux/module.h
 +#include linux/platform_device.h
 +#include linux/pm_runtime.h
 +#include linux/ratelimit.h
 +#include linux/slab.h
 +#include linux/types.h
 +#include linux/videodev2.h
 +
 +#include media/media-device.h
 +#include media/v4l2-ctrls.h
 +#include media/v4l2-event.h
 +#include media/v4l2-ioctl.h
 +#include media/videobuf2-core.h
 +#include 

Re: [PATCH RFC v3 1/3] V4L: Add driver for S3C244X/S3C64XX SoC series camera interface

2012-11-16 Thread Sylwester Nawrocki

Hi Alexey,

On 11/16/2012 03:10 PM, Alexey Klimov wrote:

+static int s3c_camif_hw_init(struct camif_dev *camif, struct camif_vp
*vp)
+{
+   unsigned int ip_rev = camif-variant-ip_revision;
+   unsigned long flags;
+
+   if (camif-sensor.sd == NULL || vp-out_fmt == NULL)
+   return -EINVAL;
+
+   spin_lock_irqsave(camif-slock, flags);
+
+   if (ip_rev == S3C244X_CAMIF_IP_REV)
+   camif_hw_clear_fifo_overflow(vp);
+   camif_hw_set_camera_bus(camif);
+   camif_hw_set_source_format(camif);
+   camif_hw_set_camera_crop(camif);
+   camif_hw_set_test_pattern(camif, camif-test_pattern-val);
+   if (ip_rev == S3C6410_CAMIF_IP_REV)
+   camif_hw_set_input_path(vp);
+   camif_cfg_video_path(vp);
+   vp-state= ~ST_VP_CONFIG;
+
+   spin_unlock_irqrestore(camif-slock, flags);
+   return 0;
+}
+
+/*
+ * Initialize the video path, only up from the scaler stage. The camera
+ * input interface set up is skipped. This is useful to enable one of
the
+ * video paths when the other is already running.
+ */
+static int s3c_camif_hw_vp_init(struct camif_dev *camif, struct camif_vp
*vp)
+{
+   unsigned int ip_rev = camif-variant-ip_revision;
+   unsigned long flags;
+
+   if (vp-out_fmt == NULL)
+   return -EINVAL;
+
+   spin_lock_irqsave(camif-slock, flags);
+   camif_prepare_dma_offset(vp);
+   if (ip_rev == S3C244X_CAMIF_IP_REV)
+   camif_hw_clear_fifo_overflow(vp);
+   camif_cfg_video_path(vp);
+   if (ip_rev == S3C6410_CAMIF_IP_REV)
+   camif_hw_set_effect(vp, false);
+   vp-state= ~ST_VP_CONFIG;
+
+   spin_unlock_irqrestore(camif-slock, flags);
+   return 0;
+}

...

+/*
+ * Reinitialize the driver so it is ready to start streaming again.
+ * Return any buffers to vb2, perform CAMIF software reset and
+ * turn off streaming at the data pipeline (sensor) if required.
+ */
+static int camif_reinitialize(struct camif_vp *vp)
+{
+   struct camif_dev *camif = vp-camif;
+   struct camif_buffer *buf;
+   unsigned long flags;
+   bool streaming;
+
+   spin_lock_irqsave(camif-slock, flags);
+   streaming = vp-state  ST_VP_SENSOR_STREAMING;
+
+   vp-state= ~(ST_VP_PENDING | ST_VP_RUNNING | ST_VP_OFF |
+  ST_VP_ABORTING | ST_VP_STREAMING |
+  ST_VP_SENSOR_STREAMING | ST_VP_LASTIRQ);
+
+   /* Release unused buffers */
+   while (!list_empty(vp-pending_buf_q)) {
+   buf = camif_pending_queue_pop(vp);
+   vb2_buffer_done(buf-vb, VB2_BUF_STATE_ERROR);
+   }
+
+   while (!list_empty(vp-active_buf_q)) {
+   buf = camif_active_queue_pop(vp);
+   vb2_buffer_done(buf-vb, VB2_BUF_STATE_ERROR);
+   }
+
+   spin_unlock_irqrestore(camif-slock, flags);
+
+   if (!streaming)
+   return 0;
+
+   return sensor_set_streaming(camif, 0);
+}

...

+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+   struct camif_vp *vp = vb2_get_drv_priv(vq);
+   struct camif_dev *camif = vp-camif;
+   unsigned long flags;
+   int ret;
+
+   /*
+* We assume the codec capture path is always activated
+* first, before the preview path starts streaming.
+* This is required to avoid internal FIFO overflow and
+* a need for CAMIF software reset.
+*/
+   spin_lock_irqsave(camif-slock, flags);


Here.



+
+   if (camif-stream_count == 0) {
+   camif_hw_reset(camif);
+   spin_unlock_irqrestore(camif-slock, flags);
+   ret = s3c_camif_hw_init(camif, vp);
+   } else {
+   spin_unlock_irqrestore(camif-slock, flags);
+   ret = s3c_camif_hw_vp_init(camif, vp);
+   }
+
+   if (ret  0) {
+   camif_reinitialize(vp);
+   return ret;
+   }
+
+   spin_lock_irqsave(camif-slock, flags);


Could you please check this function? Is it ok that you have double
spin_lock_irqsave()? I don't know may be it's okay. Also when you call
camif_reinitialize() you didn't call spin_unlock_irqrestore() before and
inside camif_reinitialize() you will also call spin_lock_irqsave()..


Certainly with nested spinlock locking this code would have been useless.
I suppose this is what you mean by double spin_lock_irqsave(). Since
it is known to work there must be spin_unlock_irqrestore() somewhere,
before the second spin_lock_irqsave() above. Just look around with more
focus ;)

Nevertheless, it looks locking can be removed from functions
s3c_camif_hw_init() and s3c_camif_vp_init(), those are called only from
one place, where in addition the spinlock is already held. I'm going
to squash following patch into that one:

8--
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c 
b/drivers/media/platform/s3c-camif/camif-capture.c

index c2ecdcc..6401fdb 100644
---