Merge tag 'v3.8-rc1' into staging/for_v3.9
authorMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 27 Dec 2012 14:44:11 +0000 (12:44 -0200)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 27 Dec 2012 14:44:11 +0000 (12:44 -0200)
Linux 3.8-rc1

* tag 'v3.8-rc1': (10696 commits)
  Linux 3.8-rc1
  Revert "nfsd: warn on odd reply state in nfsd_vfs_read"
  ARM: dts: fix duplicated build target and alphabetical sort out for exynos
  dm stripe: add WRITE SAME support
  dm: remove map_info
  dm snapshot: do not use map_context
  dm thin: dont use map_context
  dm raid1: dont use map_context
  dm flakey: dont use map_context
  dm raid1: rename read_record to bio_record
  dm: move target request nr to dm_target_io
  dm snapshot: use per_bio_data
  dm verity: use per_bio_data
  dm raid1: use per_bio_data
  dm: introduce per_bio_data
  dm kcopyd: add WRITE SAME support to dm_kcopyd_zero
  dm linear: add WRITE SAME support
  dm: add WRITE SAME support
  dm: prepare to support WRITE SAME
  dm ioctl: use kmalloc if possible
  ...

Conflicts:
MAINTAINERS

217 files changed:
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/pixfmt-uv8.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/subdev-formats.xml
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media_api.tmpl
Documentation/video4linux/et61x251.txt [deleted file]
Documentation/video4linux/ibmcam.txt [deleted file]
Documentation/video4linux/m5602.txt [deleted file]
Documentation/video4linux/ov511.txt [deleted file]
Documentation/video4linux/se401.txt [deleted file]
Documentation/video4linux/soc-camera.txt
Documentation/video4linux/stv680.txt [deleted file]
Documentation/video4linux/v4l2-framework.txt
Documentation/video4linux/w9968cf.txt [deleted file]
Documentation/video4linux/zc0301.txt [deleted file]
MAINTAINERS
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/dm644x.c
drivers/media/common/saa7146/saa7146_fops.c
drivers/media/dvb-frontends/ix2505v.c
drivers/media/dvb-frontends/or51211.c
drivers/media/dvb-frontends/tda10071.c
drivers/media/dvb-frontends/tda10071.h
drivers/media/dvb-frontends/tda8261_cfg.h
drivers/media/i2c/ov7670.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/cx23885/Kconfig
drivers/media/pci/cx23885/cx23885-cards.c
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/pci/cx23885/cx23885-input.c
drivers/media/pci/cx23885/cx23885-video.c
drivers/media/pci/cx23885/cx23885.h
drivers/media/pci/cx25821/cx25821-video.c
drivers/media/pci/cx88/cx88-core.c
drivers/media/pci/ivtv/ivtv-driver.c
drivers/media/pci/meye/meye.c
drivers/media/pci/saa7134/saa7134-core.c
drivers/media/pci/saa7134/saa7134-dvb.c
drivers/media/pci/sta2x11/sta2x11_vip.c
drivers/media/pci/zoran/zoran_device.c
drivers/media/pci/zoran/zoran_driver.c
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/blackfin/Kconfig
drivers/media/platform/blackfin/Makefile
drivers/media/platform/blackfin/bfin_capture.c
drivers/media/platform/blackfin/ppi.c
drivers/media/platform/coda.c
drivers/media/platform/davinci/Kconfig
drivers/media/platform/davinci/Makefile
drivers/media/platform/davinci/vpbe.c
drivers/media/platform/davinci/vpbe_display.c
drivers/media/platform/davinci/vpbe_osd.c
drivers/media/platform/davinci/vpbe_venc.c
drivers/media/platform/davinci/vpfe_capture.c
drivers/media/platform/davinci/vpif_capture.c
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/davinci/vpss.c
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/exynos-gsc/gsc-core.h
drivers/media/platform/exynos-gsc/gsc-m2m.c
drivers/media/platform/exynos-gsc/gsc-regs.c
drivers/media/platform/fsl-viu.c
drivers/media/platform/m2m-deinterlace.c
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/omap24xxcam.c
drivers/media/platform/omap3isp/ispqueue.c
drivers/media/platform/s5p-fimc/fimc-capture.c
drivers/media/platform/s5p-fimc/fimc-core.c
drivers/media/platform/s5p-fimc/fimc-core.h
drivers/media/platform/s5p-fimc/fimc-lite-reg.c
drivers/media/platform/s5p-fimc/fimc-lite.c
drivers/media/platform/s5p-fimc/fimc-lite.h
drivers/media/platform/s5p-fimc/fimc-m2m.c
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/s5p-fimc/fimc-mdevice.h
drivers/media/platform/s5p-fimc/fimc-reg.c
drivers/media/platform/s5p-fimc/fimc-reg.h
drivers/media/platform/s5p-fimc/mipi-csis.c
drivers/media/platform/s5p-tv/sii9234_drv.c
drivers/media/platform/sh_veu.c [new file with mode: 0644]
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/atmel-isi.c
drivers/media/platform/soc_camera/mx1_camera.c
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/mx3_camera.c
drivers/media/platform/soc_camera/omap1_camera.c
drivers/media/platform/soc_camera/pxa_camera.c
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
drivers/media/platform/soc_camera/sh_mobile_csi2.c
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/platform/soc_camera/soc_mediabus.c
drivers/media/platform/timblogiw.c
drivers/media/platform/vino.c
drivers/media/platform/vivi.c
drivers/media/rc/ati_remote.c
drivers/media/rc/ene_ir.c
drivers/media/rc/fintek-cir.c
drivers/media/rc/gpio-ir-recv.c
drivers/media/rc/ite-cir.c
drivers/media/rc/keymaps/Makefile
drivers/media/rc/keymaps/rc-total-media-in-hand-02.c [new file with mode: 0644]
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/rc-main.c
drivers/media/rc/winbond-cir.c
drivers/media/tuners/tda18212.c
drivers/media/tuners/tda18218.c
drivers/media/tuners/tda18271-fe.c
drivers/media/usb/Kconfig
drivers/media/usb/au0828/Kconfig
drivers/media/usb/au0828/Makefile
drivers/media/usb/au0828/au0828-cards.c
drivers/media/usb/au0828/au0828-core.c
drivers/media/usb/au0828/au0828-i2c.c
drivers/media/usb/au0828/au0828-video.c
drivers/media/usb/au0828/au0828.h
drivers/media/usb/cpia2/cpia2_usb.c
drivers/media/usb/cpia2/cpia2_v4l.c
drivers/media/usb/cx231xx/cx231xx-417.c
drivers/media/usb/cx231xx/cx231xx-vbi.c
drivers/media/usb/cx231xx/cx231xx-video.c
drivers/media/usb/dvb-usb-v2/it913x.c
drivers/media/usb/dvb-usb/dw2102.c
drivers/media/usb/em28xx/Kconfig
drivers/media/usb/em28xx/em28xx-cards.c
drivers/media/usb/em28xx/em28xx-core.c
drivers/media/usb/em28xx/em28xx-dvb.c
drivers/media/usb/em28xx/em28xx-i2c.c
drivers/media/usb/em28xx/em28xx-input.c
drivers/media/usb/em28xx/em28xx-reg.h
drivers/media/usb/em28xx/em28xx-vbi.c
drivers/media/usb/em28xx/em28xx-video.c
drivers/media/usb/em28xx/em28xx.h
drivers/media/usb/gspca/jl2005bcd.c
drivers/media/usb/gspca/kinect.c
drivers/media/usb/gspca/pac207.c
drivers/media/usb/gspca/sonixb.c
drivers/media/usb/gspca/sonixj.c
drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
drivers/media/usb/gspca/t613.c
drivers/media/usb/pwc/pwc-if.c
drivers/media/usb/s2255/s2255drv.c
drivers/media/usb/sn9c102/sn9c102_core.c
drivers/media/usb/stk1160/stk1160-video.c
drivers/media/usb/stkwebcam/stk-webcam.c
drivers/media/usb/tlg2300/pd-video.c
drivers/media/usb/tm6000/tm6000-dvb.c
drivers/media/usb/tm6000/tm6000-video.c
drivers/media/usb/tm6000/tm6000.h
drivers/media/usb/usbvision/usbvision-core.c
drivers/media/usb/usbvision/usbvision-video.c
drivers/media/usb/zr364xx/zr364xx.c
drivers/media/v4l2-core/v4l2-common.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/media/v4l2-core/videobuf-core.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/staging/media/Kconfig
drivers/staging/media/Makefile
drivers/staging/media/as102/as10x_cmd_cfg.c
drivers/staging/media/cxd2099/cxd2099.c
drivers/staging/media/cxd2099/cxd2099.h
drivers/staging/media/davinci_vpfe/Kconfig [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/Makefile [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/TODO [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_ipipe.c [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_ipipe.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_ipipeif.c [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_ipipeif.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_isif.c [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_isif.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_isif_regs.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_resizer.c [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/dm365_resizer.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/vpfe.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/vpfe_video.c [new file with mode: 0644]
drivers/staging/media/davinci_vpfe/vpfe_video.h [new file with mode: 0644]
drivers/staging/media/dt3155v4l/dt3155v4l.c
drivers/staging/media/go7007/go7007-driver.c
drivers/staging/media/go7007/go7007-i2c.c
drivers/staging/media/go7007/go7007-v4l2.c
drivers/staging/media/go7007/s2250-board.c
drivers/staging/media/go7007/s2250-loader.c
drivers/staging/media/go7007/wis-sony-tuner.c
drivers/staging/media/go7007/wis-tw2804.c
drivers/staging/media/go7007/wis-tw9903.c
drivers/staging/media/go7007/wis-uda1342.c
drivers/staging/media/lirc/lirc_bt829.c
drivers/staging/media/lirc/lirc_igorplugusb.c
drivers/staging/media/lirc/lirc_imon.c
drivers/staging/media/lirc/lirc_parallel.c
drivers/staging/media/lirc/lirc_sasem.c
drivers/staging/media/lirc/lirc_serial.c
drivers/staging/media/lirc/lirc_sir.c
drivers/staging/media/solo6x10/p2m.c
drivers/staging/media/solo6x10/v4l2-enc.c
include/media/blackfin/bfin_capture.h
include/media/blackfin/ppi.h
include/media/davinci/vpbe_osd.h
include/media/davinci/vpbe_venc.h
include/media/davinci/vpss.h
include/media/rc-map.h
include/media/v4l2-common.h
include/media/v4l2-mem2mem.h
include/uapi/linux/v4l2-mediabus.h
include/uapi/linux/videodev2.h

index 3dd9e78815d1bca89576c2817bb050471419cf04..ebd2bfd1ee8eb3a380ab52cde6883473727cfb8f 100644 (file)
@@ -2477,6 +2477,18 @@ that used it. It was originally scheduled for removal in 2.6.35.
       </orderedlist>
     </section>
 
+    <section>
+      <title>V4L2 in Linux 3.9</title>
+      <orderedlist>
+        <listitem>
+         <para>Added timestamp types to
+         <structfield>flags</structfield> field in
+         <structname>v4l2_buffer</structname>. See <xref
+         linkend="buffer-flags" />.</para>
+        </listitem>
+      </orderedlist>
+    </section>
+
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
 
index 388a3403265380f14128feb10b50543f69bd994c..2c4646d504c2b6af4b80358dad6d6de9c2e06151 100644 (file)
@@ -741,17 +741,19 @@ applications when an output stream.</entry>
            <entry>struct timeval</entry>
            <entry><structfield>timestamp</structfield></entry>
            <entry></entry>
-           <entry><para>For input streams this is the
-system time (as returned by the <function>gettimeofday()</function>
-function) when the first data byte was captured. For output streams
-the data will not be displayed before this time, secondary to the
-nominal frame rate determined by the current video standard in
-enqueued order. Applications can for example zero this field to
-display frames as soon as possible. The driver stores the time at
-which the first data byte was actually sent out in the
-<structfield>timestamp</structfield> field. This permits
-applications to monitor the drift between the video and system
-clock.</para></entry>
+           <entry><para>For input streams this is time when the first data
+           byte was captured, as returned by the
+           <function>clock_gettime()</function> function for the relevant
+           clock id; see <constant>V4L2_BUF_FLAG_TIMESTAMP_*</constant> in
+           <xref linkend="buffer-flags" />. For output streams the data
+           will not be displayed before this time, secondary to the nominal
+           frame rate determined by the current video standard in enqueued
+           order. Applications can for example zero this field to display
+           frames as soon as possible. The driver stores the time at which
+           the first data byte was actually sent out in the
+           <structfield>timestamp</structfield> field. This permits
+           applications to monitor the drift between the video and system
+           clock.</para></entry>
          </row>
          <row>
            <entry>&v4l2-timecode;</entry>
@@ -903,7 +905,7 @@ should set this to 0.</entry>
          </row>
          <row>
            <entry></entry>
-           <entry>__unsigned long</entry>
+           <entry>unsigned long</entry>
            <entry><structfield>userptr</structfield></entry>
            <entry>When the memory type in the containing &v4l2-buffer; is
              <constant>V4L2_MEMORY_USERPTR</constant>, this is a userspace
@@ -1114,6 +1116,35 @@ Typically applications shall use this flag for output buffers if the data
 in this buffer has not been created by the CPU but by some DMA-capable unit,
 in which case caches have not been used.</entry>
          </row>
+         <row>
+           <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_MASK</constant></entry>
+           <entry>0xe000</entry>
+           <entry>Mask for timestamp types below. To test the
+           timestamp type, mask out bits not belonging to timestamp
+           type by performing a logical and operation with buffer
+           flags and timestamp mask.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN</constant></entry>
+           <entry>0x0000</entry>
+           <entry>Unknown timestamp type. This type is used by
+           drivers before Linux 3.9 and may be either monotonic (see
+           below) or realtime (wall clock). Monotonic clock has been
+           favoured in embedded systems whereas most of the drivers
+           use the realtime clock. Either kinds of timestamps are
+           available in user space via
+           <function>clock_gettime(2)</function> using clock IDs
+           <constant>CLOCK_MONOTONIC</constant> and
+           <constant>CLOCK_REALTIME</constant>, respectively.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC</constant></entry>
+           <entry>0x2000</entry>
+           <entry>The buffer timestamp has been taken from the
+           <constant>CLOCK_MONOTONIC</constant> clock. To access the
+           same clock outside V4L2, use
+           <function>clock_gettime(2)</function> .</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index a990b34d911a123f775f20001f9e9629947276b2..f3a3d459fcdf58bede0e69437fd3d44ec0f133e7 100644 (file)
@@ -6,7 +6,7 @@
       <refnamediv>
        <refname id="V4L2-PIX-FMT-NV12M"><constant>V4L2_PIX_FMT_NV12M</constant></refname>
        <refname id="V4L2-PIX-FMT-NV21M"><constant>V4L2_PIX_FMT_NV21M</constant></refname>
-       <refname id="V4L2-PIX-FMT-NV12MT_16X16"><constant>V4L2_PIX_FMT_NV12MT_16X16</constant></refname>
+       <refname id="V4L2-PIX-FMT-NV12MT-16X16"><constant>V4L2_PIX_FMT_NV12MT_16X16</constant></refname>
        <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> and <constant>V4L2_PIX_FMT_NV21</constant> with planes
          non contiguous in memory. </refpurpose>
       </refnamediv>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml
new file mode 100644 (file)
index 0000000..c934192
--- /dev/null
@@ -0,0 +1,34 @@
+       <refentry>
+         <refmeta>
+           <refentrytitle>
+             V4L2_PIX_FMT_SBGGR10ALAW8 ('aBA8'),
+             V4L2_PIX_FMT_SGBRG10ALAW8 ('aGA8'),
+             V4L2_PIX_FMT_SGRBG10ALAW8 ('agA8'),
+             V4L2_PIX_FMT_SRGGB10ALAW8 ('aRA8'),
+           </refentrytitle>
+           &manvol;
+         </refmeta>
+         <refnamediv>
+           <refname id="V4L2-PIX-FMT-SBGGR10ALAW8">
+             <constant>V4L2_PIX_FMT_SBGGR10ALAW8</constant>
+           </refname>
+           <refname id="V4L2-PIX-FMT-SGBRG10ALAW8">
+             <constant>V4L2_PIX_FMT_SGBRG10ALAW8</constant>
+           </refname>
+           <refname id="V4L2-PIX-FMT-SGRBG10ALAW8">
+             <constant>V4L2_PIX_FMT_SGRBG10ALAW8</constant>
+           </refname>
+           <refname id="V4L2-PIX-FMT-SRGGB10ALAW8">
+             <constant>V4L2_PIX_FMT_SRGGB10ALAW8</constant>
+           </refname>
+           <refpurpose>10-bit Bayer formats compressed to 8 bits</refpurpose>
+         </refnamediv>
+         <refsect1>
+           <title>Description</title>
+           <para>The following four pixel formats are raw sRGB / Bayer
+           formats with 10 bits per color compressed to 8 bits each,
+           using the A-LAW algorithm. Each color component consumes 8
+           bits of memory. In other respects this format is similar to
+           <xref linkend="V4L2-PIX-FMT-SRGGB8">.</xref></para>
+         </refsect1>
+       </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-uv8.xml b/Documentation/DocBook/media/v4l/pixfmt-uv8.xml
new file mode 100644 (file)
index 0000000..c507c1f
--- /dev/null
@@ -0,0 +1,62 @@
+       <refentry id="V4L2-PIX-FMT-UV8">
+         <refmeta>
+           <refentrytitle>V4L2_PIX_FMT_UV8  ('UV8')</refentrytitle>
+           &manvol;
+         </refmeta>
+         <refnamediv>
+           <refname><constant>V4L2_PIX_FMT_UV8</constant></refname>
+           <refpurpose>UV plane interleaved</refpurpose>
+         </refnamediv>
+         <refsect1>
+           <title>Description</title>
+           <para>In this format there is no Y plane, Only CbCr plane. ie
+           (UV interleaved)</para>
+           <example>
+           <title>
+             <constant>V4L2_PIX_FMT_UV8</constant>
+              pixel image
+           </title>
+
+           <formalpara>
+             <title>Byte Order.</title>
+             <para>Each cell is one byte.
+               <informaltable frame="none">
+               <tgroup cols="5" align="center">
+                 <colspec align="left" colwidth="2*" />
+                 <tbody valign="top">
+                   <row>
+                     <entry>start&nbsp;+&nbsp;0:</entry>
+                     <entry>Cb<subscript>00</subscript></entry>
+                     <entry>Cr<subscript>00</subscript></entry>
+                     <entry>Cb<subscript>01</subscript></entry>
+                     <entry>Cr<subscript>01</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;4:</entry>
+                     <entry>Cb<subscript>10</subscript></entry>
+                     <entry>Cr<subscript>10</subscript></entry>
+                     <entry>Cb<subscript>11</subscript></entry>
+                     <entry>Cr<subscript>11</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;8:</entry>
+                     <entry>Cb<subscript>20</subscript></entry>
+                     <entry>Cr<subscript>20</subscript></entry>
+                     <entry>Cb<subscript>21</subscript></entry>
+                     <entry>Cr<subscript>21</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start&nbsp;+&nbsp;12:</entry>
+                     <entry>Cb<subscript>30</subscript></entry>
+                     <entry>Cr<subscript>30</subscript></entry>
+                     <entry>Cb<subscript>31</subscript></entry>
+                     <entry>Cr<subscript>31</subscript></entry>
+                   </row>
+                 </tbody>
+               </tgroup>
+               </informaltable>
+             </para>
+             </formalpara>
+           </example>
+         </refsect1>
+       </refentry>
index bf94f417592cac290670f4e65ace3a54fc1eb173..99b8d2ad6e4ff1613db6a789c0228afde61318b5 100644 (file)
@@ -673,6 +673,7 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
     &sub-srggb8;
     &sub-sbggr16;
     &sub-srggb10;
+    &sub-srggb10alaw8;
     &sub-srggb10dpcm8;
     &sub-srggb12;
   </section>
@@ -701,6 +702,7 @@ information.</para>
     &sub-y12;
     &sub-y10b;
     &sub-y16;
+    &sub-uv8;
     &sub-yuyv;
     &sub-uyvy;
     &sub-yvyu;
index a0a936455faef1c68d59f5997b8697b7ad1e2d65..cc51372ed5e0c07fd277f8f67a303e5a3324599e 100644 (file)
        <listitem><para>The number of bits per pixel component. All components are
        transferred on the same number of bits. Common values are 8, 10 and 12.</para>
        </listitem>
-       <listitem><para>If the pixel components are DPCM-compressed, a mention of the
-       DPCM compression and the number of bits per compressed pixel component.</para>
-       </listitem>
+       <listitem><para>The compression (optional). If the pixel components are
+       ALAW- or DPCM-compressed, a mention of the compression scheme and the
+       number of bits per compressed pixel component.</para></listitem>
        <listitem><para>The number of bus samples per pixel. Pixels that are wider than
        the bus width must be transferred in multiple samples. Common values are
        1 and 2.</para></listitem>
              <entry>r<subscript>1</subscript></entry>
              <entry>r<subscript>0</subscript></entry>
            </row>
+           <row id="V4L2-MBUS-FMT-SBGGR10-ALAW8-1X8">
+             <entry>V4L2_MBUS_FMT_SBGGR10_ALAW8_1X8</entry>
+             <entry>0x3015</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>b<subscript>7</subscript></entry>
+             <entry>b<subscript>6</subscript></entry>
+             <entry>b<subscript>5</subscript></entry>
+             <entry>b<subscript>4</subscript></entry>
+             <entry>b<subscript>3</subscript></entry>
+             <entry>b<subscript>2</subscript></entry>
+             <entry>b<subscript>1</subscript></entry>
+             <entry>b<subscript>0</subscript></entry>
+           </row>
+           <row id="V4L2-MBUS-FMT-SGBRG10-ALAW8-1X8">
+             <entry>V4L2_MBUS_FMT_SGBRG10_ALAW8_1X8</entry>
+             <entry>0x3016</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>g<subscript>7</subscript></entry>
+             <entry>g<subscript>6</subscript></entry>
+             <entry>g<subscript>5</subscript></entry>
+             <entry>g<subscript>4</subscript></entry>
+             <entry>g<subscript>3</subscript></entry>
+             <entry>g<subscript>2</subscript></entry>
+             <entry>g<subscript>1</subscript></entry>
+             <entry>g<subscript>0</subscript></entry>
+           </row>
+           <row id="V4L2-MBUS-FMT-SGRBG10-ALAW8-1X8">
+             <entry>V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8</entry>
+             <entry>0x3017</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>g<subscript>7</subscript></entry>
+             <entry>g<subscript>6</subscript></entry>
+             <entry>g<subscript>5</subscript></entry>
+             <entry>g<subscript>4</subscript></entry>
+             <entry>g<subscript>3</subscript></entry>
+             <entry>g<subscript>2</subscript></entry>
+             <entry>g<subscript>1</subscript></entry>
+             <entry>g<subscript>0</subscript></entry>
+           </row>
+           <row id="V4L2-MBUS-FMT-SRGGB10-ALAW8-1X8">
+             <entry>V4L2_MBUS_FMT_SRGGB10_ALAW8_1X8</entry>
+             <entry>0x3018</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>r<subscript>7</subscript></entry>
+             <entry>r<subscript>6</subscript></entry>
+             <entry>r<subscript>5</subscript></entry>
+             <entry>r<subscript>4</subscript></entry>
+             <entry>r<subscript>3</subscript></entry>
+             <entry>r<subscript>2</subscript></entry>
+             <entry>r<subscript>1</subscript></entry>
+             <entry>r<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-SBGGR10-DPCM8-1X8">
              <entry>V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8</entry>
              <entry>0x300b</entry>
       <title>Packed YUV Formats</title>
 
       <para>Those data formats transfer pixel data as (possibly downsampled) Y, U
-      and V components. The format code is made of the following information.
+      and V components. Some formats include dummy bits in some of their samples
+      and are collectively referred to as "YDYC" (Y-Dummy-Y-Chroma) formats.
+      One cannot rely on the values of these dummy bits as those are undefined.
+      </para>
+      <para>The format code is made of the following information.
       <itemizedlist>
        <listitem><para>The Y, U and V components order code, as transferred on the
-       bus. Possible values are YUYV, UYVY, YVYU and VYUY.</para></listitem>
+       bus. Possible values are YUYV, UYVY, YVYU and VYUY for formats with no
+       dummy bit, and YDYUYDYV, YDYVYDYU, YUYDYVYD and YVYDYUYD for YDYC formats.
+       </para></listitem>
        <listitem><para>The number of bits per pixel component. All components are
        transferred on the same number of bits. Common values are 8, 10 and 12.</para>
        </listitem>
       U, Y, V, Y order will be named <constant>V4L2_MBUS_FMT_UYVY8_2X8</constant>.
       </para>
 
-      <para>The following table lisst existing packet YUV formats.</para>
+       <para><xref linkend="v4l2-mbus-pixelcode-yuv8"/> list existing packet YUV
+       formats and describes the organization of each pixel data in each sample.
+       When a format pattern is split across multiple samples each of the samples
+       in the pattern is described.</para>
+
+       <para>The role of each bit transferred over the bus is identified by one
+       of the following codes.</para>
+
+       <itemizedlist>
+          <listitem><para>y<subscript>x</subscript> for luma component bit number x</para></listitem>
+          <listitem><para>u<subscript>x</subscript> for blue chroma component bit number x</para></listitem>
+          <listitem><para>v<subscript>x</subscript> for red chroma component bit number x</para></listitem>
+          <listitem><para>- for non-available bits (for positions higher than the bus width)</para></listitem>
+          <listitem><para>d for dummy bits</para></listitem>
+       </itemizedlist>
 
       <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-yuv8">
        <title>YUV Formats</title>
          <colspec colname="id" align="left" />
          <colspec colname="code" align="center"/>
          <colspec colname="bit" />
-         <colspec colnum="4" colname="b19" align="center" />
-         <colspec colnum="5" colname="b18" align="center" />
-         <colspec colnum="6" colname="b17" align="center" />
-         <colspec colnum="7" colname="b16" align="center" />
-         <colspec colnum="8" colname="b15" align="center" />
-         <colspec colnum="9" colname="b14" align="center" />
-         <colspec colnum="10" colname="b13" align="center" />
-         <colspec colnum="11" colname="b12" align="center" />
-         <colspec colnum="12" colname="b11" align="center" />
-         <colspec colnum="13" colname="b10" align="center" />
-         <colspec colnum="14" colname="b09" align="center" />
-         <colspec colnum="15" colname="b08" align="center" />
-         <colspec colnum="16" colname="b07" align="center" />
-         <colspec colnum="17" colname="b06" align="center" />
-         <colspec colnum="18" colname="b05" align="center" />
-         <colspec colnum="19" colname="b04" align="center" />
-         <colspec colnum="20" colname="b03" align="center" />
-         <colspec colnum="21" colname="b02" align="center" />
-         <colspec colnum="22" colname="b01" align="center" />
-         <colspec colnum="23" colname="b00" align="center" />
-         <spanspec namest="b19" nameend="b00" spanname="b0" />
+         <colspec colnum="4" colname="b29" align="center" />
+         <colspec colnum="5" colname="b28" align="center" />
+         <colspec colnum="6" colname="b27" align="center" />
+         <colspec colnum="7" colname="b26" align="center" />
+         <colspec colnum="8" colname="b25" align="center" />
+         <colspec colnum="9" colname="b24" align="center" />
+         <colspec colnum="10" colname="b23" align="center" />
+         <colspec colnum="11" colname="b22" align="center" />
+         <colspec colnum="12" colname="b21" align="center" />
+         <colspec colnum="13" colname="b20" align="center" />
+         <colspec colnum="14" colname="b19" align="center" />
+         <colspec colnum="15" colname="b18" align="center" />
+         <colspec colnum="16" colname="b17" align="center" />
+         <colspec colnum="17" colname="b16" align="center" />
+         <colspec colnum="18" colname="b15" align="center" />
+         <colspec colnum="19" colname="b14" align="center" />
+         <colspec colnum="20" colname="b13" align="center" />
+         <colspec colnum="21" colname="b12" align="center" />
+         <colspec colnum="22" colname="b11" align="center" />
+         <colspec colnum="23" colname="b10" align="center" />
+         <colspec colnum="24" colname="b09" align="center" />
+         <colspec colnum="25" colname="b08" align="center" />
+         <colspec colnum="26" colname="b07" align="center" />
+         <colspec colnum="27" colname="b06" align="center" />
+         <colspec colnum="28" colname="b05" align="center" />
+         <colspec colnum="29" colname="b04" align="center" />
+         <colspec colnum="30" colname="b03" align="center" />
+         <colspec colnum="31" colname="b02" align="center" />
+         <colspec colnum="32" colname="b01" align="center" />
+         <colspec colnum="33" colname="b00" align="center" />
+         <spanspec namest="b29" nameend="b00" spanname="b0" />
          <thead>
            <row>
              <entry>Identifier</entry>
              <entry></entry>
              <entry></entry>
              <entry>Bit</entry>
+             <entry>29</entry>
+             <entry>28</entry>
+             <entry>27</entry>
+             <entry>26</entry>
+             <entry>25</entry>
+             <entry>24</entry>
+             <entry>23</entry>
+             <entry>22</entry>
+             <entry>21</entry>
+             <entry>10</entry>
              <entry>19</entry>
              <entry>18</entry>
              <entry>17</entry>
              <entry>V4L2_MBUS_FMT_Y8_1X8</entry>
              <entry>0x2001</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
            </row>
-           <row id="V4L2-MBUS-FMT-UYVY8-1_5X8">
-             <entry>V4L2_MBUS_FMT_UYVY8_1_5X8</entry>
-             <entry>0x2002</entry>
+           <row id="V4L2-MBUS-FMT-UV8-1X8">
+             <entry>V4L2_MBUS_FMT_UV8_1X8</entry>
+             <entry>0x2015</entry>
              <entry></entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
+           </row>
+           <row id="V4L2-MBUS-FMT-UYVY8-1_5X8">
+             <entry>V4L2_MBUS_FMT_UYVY8_1_5X8</entry>
+             <entry>0x2002</entry>
+             <entry></entry>
+             &dash-ent-10;
+             &dash-ent-10;
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-10;
+             &dash-ent-10;
+             <entry>-</entry>
+             <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_VYUY8_1_5X8</entry>
              <entry>0x2003</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>u<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_YUYV8_1_5X8</entry>
              <entry>0x2004</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>u<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_YVYU8_1_5X8</entry>
              <entry>0x2005</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_UYVY8_2X8</entry>
              <entry>0x2006</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>u<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_VYUY8_2X8</entry>
              <entry>0x2007</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>u<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_YUYV8_2X8</entry>
              <entry>0x2008</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>u<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_YVYU8_2X8</entry>
              <entry>0x2009</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_Y10_1X10</entry>
              <entry>0x200a</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_YUYV10_2X10</entry>
              <entry>0x200b</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>u<subscript>9</subscript></entry>
              <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>v<subscript>9</subscript></entry>
              <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_YVYU10_2X10</entry>
              <entry>0x200c</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>v<subscript>9</subscript></entry>
              <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-10;
+             &dash-ent-10;
              <entry>u<subscript>9</subscript></entry>
              <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_Y12_1X12</entry>
              <entry>0x2013</entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>V4L2_MBUS_FMT_UYVY8_1X16</entry>
              <entry>0x200f</entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>V4L2_MBUS_FMT_VYUY8_1X16</entry>
              <entry>0x2010</entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>V4L2_MBUS_FMT_YUYV8_1X16</entry>
              <entry>0x2011</entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>V4L2_MBUS_FMT_YVYU8_1X16</entry>
              <entry>0x2012</entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>-</entry>
              <entry>-</entry>
              <entry>-</entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
            </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-10;
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
+           </row>
+           <row id="V4L2-MBUS-FMT-YDYUYDYV8-1X16">
+             <entry>V4L2_MBUS_FMT_YDYUYDYV8_1X16</entry>
+             <entry>0x2014</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+           </row>
            <row>
              <entry></entry>
              <entry></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
            </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-YUYV10-1X20">
              <entry>V4L2_MBUS_FMT_YUYV10_1X20</entry>
              <entry>0x200d</entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>V4L2_MBUS_FMT_YVYU10_1X20</entry>
              <entry>0x200e</entry>
              <entry></entry>
+             &dash-ent-10;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
+             &dash-ent-10;
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>u<subscript>9</subscript></entry>
+             <entry>u<subscript>8</subscript></entry>
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
+           </row>
+           <row id="V4L2-MBUS-FMT-YUV10-1X30">
+             <entry>V4L2_MBUS_FMT_YUV10_1X30</entry>
+             <entry>0x2014</entry>
+             <entry></entry>
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
+             <entry>v<subscript>9</subscript></entry>
+             <entry>v<subscript>8</subscript></entry>
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
            </row>
          </tbody>
        </tgroup>
index 4d110b1ad3e93c6559b094ac5bd832f2e4bf3be0..8fe29427c8e4a75bec736348055f1930c238b69e 100644 (file)
@@ -139,6 +139,16 @@ structs, ioctls) must be noted in more detail in the history chapter
 (compat.xml), along with the possible impact on existing drivers and
 applications. -->
 
+      <revision>
+       <revnumber>3.9</revnumber>
+       <date>2012-12-03</date>
+       <authorinitials>sa</authorinitials>
+       <revremark>Added timestamp types to
+       <structname>v4l2_buffer</structname>, see <xref
+       linkend="buffer-flags" />.
+       </revremark>
+      </revision>
+
       <revision>
        <revnumber>3.6</revnumber>
        <date>2012-07-02</date>
@@ -472,7 +482,7 @@ and discussions on the V4L mailing list.</revremark>
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.6</subtitle>
+ <subtitle>Revision 3.9</subtitle>
 
   <chapter id="common">
     &sub-common;
index f2413acfe24105b00b529feca5a0490d6a9b126d..1f6593deb9955ad494edef4b182bd16bf01b8ce4 100644 (file)
@@ -22,6 +22,7 @@
 
 <!-- LinuxTV v4l-dvb repository. -->
 <!ENTITY v4l-dvb               "<ulink url='http://linuxtv.org/repo/'>http://linuxtv.org/repo/</ulink>">
+<!ENTITY dash-ent-10            "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
 ]>
 
 <book id="media_api">
diff --git a/Documentation/video4linux/et61x251.txt b/Documentation/video4linux/et61x251.txt
deleted file mode 100644 (file)
index e0cdae4..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-
-                      ET61X[12]51 PC Camera Controllers
-                               Driver for Linux
-                      =================================
-
-                              - Documentation -
-
-
-Index
-=====
-1.  Copyright
-2.  Disclaimer
-3.  License
-4.  Overview and features
-5.  Module dependencies
-6.  Module loading
-7.  Module parameters
-8.  Optional device control through "sysfs"
-9.  Supported devices
-10. Notes for V4L2 application developers
-11. Contact information
-
-
-1. Copyright
-============
-Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
-
-
-2. Disclaimer
-=============
-Etoms is a trademark of Etoms Electronics Corp.
-This software is not developed or sponsored by Etoms Electronics.
-
-
-3. License
-==========
-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.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-4. Overview and features
-========================
-This driver supports the video interface of the devices mounting the ET61X151
-or ET61X251 PC Camera Controllers.
-
-It's worth to note that Etoms Electronics has never collaborated with the
-author during the development of this project; despite several requests,
-Etoms Electronics also refused to release enough detailed specifications of
-the video compression engine.
-
-The driver relies on the Video4Linux2 and USB core modules. It has been
-designed to run properly on SMP systems as well.
-
-The latest version of the ET61X[12]51 driver can be found at the following URL:
-http://www.linux-projects.org/
-
-Some of the features of the driver are:
-
-- full compliance with the Video4Linux2 API (see also "Notes for V4L2
-  application developers" paragraph);
-- available mmap or read/poll methods for video streaming through isochronous
-  data transfers;
-- automatic detection of image sensor;
-- support for any window resolutions and optional panning within the maximum
-  pixel area of image sensor;
-- image downscaling with arbitrary scaling factors from 1 and 2 in both
-  directions (see "Notes for V4L2 application developers" paragraph);
-- two different video formats for uncompressed or compressed data in low or
-  high compression quality (see also "Notes for V4L2 application developers"
-  paragraph);
-- full support for the capabilities of every possible image sensors that can
-  be connected to the ET61X[12]51 bridges, including, for instance, red, green,
-  blue and global gain adjustments and exposure control (see "Supported
-  devices" paragraph for details);
-- use of default color settings for sunlight conditions;
-- dynamic I/O interface for both ET61X[12]51 and image sensor control (see
-  "Optional device control through 'sysfs'" paragraph);
-- dynamic driver control thanks to various module parameters (see "Module
-  parameters" paragraph);
-- up to 64 cameras can be handled at the same time; they can be connected and
-  disconnected from the host many times without turning off the computer, if
-  the system supports hotplugging;
-- no known bugs.
-
-
-5. Module dependencies
-======================
-For it to work properly, the driver needs kernel support for Video4Linux and
-USB.
-
-The following options of the kernel configuration file must be enabled and
-corresponding modules must be compiled:
-
-       # Multimedia devices
-       #
-       CONFIG_VIDEO_DEV=m
-
-To enable advanced debugging functionality on the device through /sysfs:
-
-       # Multimedia devices
-       #
-       CONFIG_VIDEO_ADV_DEBUG=y
-
-       # USB support
-       #
-       CONFIG_USB=m
-
-In addition, depending on the hardware being used, the modules below are
-necessary:
-
-       # USB Host Controller Drivers
-       #
-       CONFIG_USB_EHCI_HCD=m
-       CONFIG_USB_UHCI_HCD=m
-       CONFIG_USB_OHCI_HCD=m
-
-And finally:
-
-       # USB Multimedia devices
-       #
-       CONFIG_USB_ET61X251=m
-
-
-6. Module loading
-=================
-To use the driver, it is necessary to load the "et61x251" module into memory
-after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
-"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
-"uhci-hcd" or "ohci-hcd".
-
-Loading can be done as shown below:
-
-       [root@localhost home]# modprobe et61x251
-
-At this point the devices should be recognized. You can invoke "dmesg" to
-analyze kernel messages and verify that the loading process has gone well:
-
-       [user@localhost home]$ dmesg
-
-
-7. Module parameters
-====================
-Module parameters are listed below:
--------------------------------------------------------------------------------
-Name:           video_nr
-Type:           short array (min = 0, max = 64)
-Syntax:         <-1|n[,...]>
-Description:    Specify V4L2 minor mode number:
-               -1 = use next available
-                n = use minor number n
-               You can specify up to 64 cameras this way.
-               For example:
-               video_nr=-1,2,-1 would assign minor number 2 to the second
-               registered camera and use auto for the first one and for every
-               other camera.
-Default:        -1
--------------------------------------------------------------------------------
-Name:           force_munmap
-Type:           bool array (min = 0, max = 64)
-Syntax:         <0|1[,...]>
-Description:    Force the application to unmap previously mapped buffer memory
-               before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-               all the applications support this feature. This parameter is
-               specific for each detected camera.
-               0 = do not force memory unmapping
-               1 = force memory unmapping (save memory)
-Default:        0
--------------------------------------------------------------------------------
-Name:           frame_timeout
-Type:           uint array (min = 0, max = 64)
-Syntax:         <n[,...]>
-Description:    Timeout for a video frame in seconds. This parameter is
-               specific for each detected camera. This parameter can be
-               changed at runtime thanks to the /sys filesystem interface.
-Default:        2
--------------------------------------------------------------------------------
-Name:           debug
-Type:           ushort
-Syntax:         <n>
-Description:    Debugging information level, from 0 to 3:
-               0 = none (use carefully)
-               1 = critical errors
-               2 = significant information
-               3 = more verbose messages
-               Level 3 is useful for testing only, when only one device
-               is used at the same time. It also shows some more information
-               about the hardware being detected. This module parameter can be
-               changed at runtime thanks to the /sys filesystem interface.
-Default:        2
--------------------------------------------------------------------------------
-
-
-8. Optional device control through "sysfs"
-==========================================
-If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
-it is possible to read and write both the ET61X[12]51 and the image sensor
-registers by using the "sysfs" filesystem interface.
-
-There are four files in the /sys/class/video4linux/videoX directory for each
-registered camera: "reg", "val", "i2c_reg" and "i2c_val". The first two files
-control the ET61X[12]51 bridge, while the other two control the sensor chip.
-"reg" and "i2c_reg" hold the values of the current register index where the
-following reading/writing operations are addressed at through "val" and
-"i2c_val". Their use is not intended for end-users, unless you know what you
-are doing. Remember that you must be logged in as root before writing to them.
-
-As an example, suppose we were to want to read the value contained in the
-register number 1 of the sensor register table - which is usually the product
-identifier - of the camera registered as "/dev/video0":
-
-       [root@localhost #] cd /sys/class/video4linux/video0
-       [root@localhost #] echo 1 > i2c_reg
-       [root@localhost #] cat i2c_val
-
-Note that if the sensor registers cannot be read, "cat" will fail.
-To avoid race conditions, all the I/O accesses to the files are serialized.
-
-
-9. Supported devices
-====================
-None of the names of the companies as well as their products will be mentioned
-here. They have never collaborated with the author, so no advertising.
-
-From the point of view of a driver, what unambiguously identify a device are
-its vendor and product USB identifiers. Below is a list of known identifiers of
-devices mounting the ET61X[12]51 PC camera controllers:
-
-Vendor ID  Product ID
----------  ----------
-0x102c     0x6151
-0x102c     0x6251
-0x102c     0x6253
-0x102c     0x6254
-0x102c     0x6255
-0x102c     0x6256
-0x102c     0x6257
-0x102c     0x6258
-0x102c     0x6259
-0x102c     0x625a
-0x102c     0x625b
-0x102c     0x625c
-0x102c     0x625d
-0x102c     0x625e
-0x102c     0x625f
-0x102c     0x6260
-0x102c     0x6261
-0x102c     0x6262
-0x102c     0x6263
-0x102c     0x6264
-0x102c     0x6265
-0x102c     0x6266
-0x102c     0x6267
-0x102c     0x6268
-0x102c     0x6269
-
-The following image sensors are supported:
-
-Model       Manufacturer
------       ------------
-TAS5130D1B  Taiwan Advanced Sensor Corporation
-
-All the available control settings of each image sensor are supported through
-the V4L2 interface.
-
-
-10. Notes for V4L2 application developers
-=========================================
-This driver follows the V4L2 API specifications. In particular, it enforces two
-rules:
-
-- exactly one I/O method, either "mmap" or "read", is associated with each
-file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method;
-
-- although it is not mandatory, previously mapped buffer memory should always
-be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's.
-The same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map the buffers again before any I/O
-attempts on them.
-
-Consistently with the hardware limits, this driver also supports image
-downscaling with arbitrary scaling factors from 1 and 2 in both directions.
-However, the V4L2 API specifications don't correctly define how the scaling
-factor can be chosen arbitrarily by the "negotiation" of the "source" and
-"target" rectangles. To work around this flaw, we have added the convention
-that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
-scaling factor is restored to 1.
-
-This driver supports two different video formats: the first one is the "8-bit
-Sequential Bayer" format and can be used to obtain uncompressed video data
-from the device through the current I/O method, while the second one provides
-"raw" compressed video data (without frame headers not related to the
-compressed data). The current compression quality may vary from 0 to 1 and can
-be selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP
-V4L2 ioctl's.
-
-
-11. Contact information
-=======================
-The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
-
-GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
-'FCE635A4'; the public 1024-bit key should be available at any keyserver;
-the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
diff --git a/Documentation/video4linux/ibmcam.txt b/Documentation/video4linux/ibmcam.txt
deleted file mode 100644 (file)
index a510552..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-README for Linux device driver for the IBM "C-It" USB video camera
-
-INTRODUCTION:
-
-This driver does not use all features known to exist in
-the IBM camera. However most of needed features work well.
-
-This driver was developed using logs of observed USB traffic
-which was produced by standard Windows driver (c-it98.sys).
-I did not have data sheets from Xirlink.
-
-Video formats:
-      128x96  [model 1]
-      176x144
-      320x240 [model 2]
-      352x240 [model 2]
-      352x288
-Frame rate: 3 - 30 frames per second (FPS)
-External interface: USB
-Internal interface: Video For Linux (V4L)
-Supported controls:
-- by V4L: Contrast,  Brightness, Color, Hue
-- by driver options: frame rate, lighting conditions, video format,
-                    default picture settings, sharpness.
-
-SUPPORTED CAMERAS:
-
-Xirlink "C-It" camera, also known as "IBM PC Camera".
-The device uses proprietary ASIC (and compression method);
-it is manufactured by Xirlink. See http://xirlinkwebcam.sourceforge.net, 
-http://www.ibmpccamera.com, or http://www.c-itnow.com/ for details and pictures.
-
-This very chipset ("X Chip", as marked at the factory)
-is used in several other cameras, and they are supported
-as well:
-
-- IBM NetCamera
-- Veo Stingray
-
-The Linux driver was developed with camera with following
-model number (or FCC ID): KSX-XVP510. This camera has three
-interfaces, each with one endpoint (control, iso, iso). This
-type of cameras is referred to as "model 1". These cameras are
-no longer manufactured.
-
-Xirlink now manufactures new cameras which are somewhat different.
-In particular, following models [FCC ID] belong to that category:
-
-XVP300 [KSX-X9903]
-XVP600 [KSX-X9902]
-XVP610 [KSX-X9902]
-
-(see http://www.xirlink.com/ibmpccamera/ for updates, they refer
-to these new cameras by Windows driver dated 12-27-99, v3005 BETA)
-These cameras have two interfaces, one endpoint in each (iso, bulk).
-Such type of cameras is referred to as "model 2". They are supported
-(with exception of 352x288 native mode).
-
-Some IBM NetCameras (Model 4) are made to generate only compressed
-video streams. This is great for performance, but unfortunately
-nobody knows how to decompress the stream :-( Therefore, these
-cameras are *unsupported* and if you try to use one of those, all
-you get is random colored horizontal streaks, not the image!
-If you have one of those cameras, you probably should return it
-to the store and get something that is supported.
-
-Tell me more about all that "model" business
---------------------------------------------
-
-I just invented model numbers to uniquely identify flavors of the
-hardware/firmware that were sold. It was very confusing to use
-brand names or some other internal numbering schemes. So I found
-by experimentation that all Xirlink chipsets fall into four big
-classes, and I called them "models". Each model is programmed in
-its own way, and each model sends back the video in its own way.
-
-Quirks of Model 2 cameras:
--------------------------
-
-Model 2 does not have hardware contrast control. Corresponding V4L
-control is implemented in software, which is not very nice to your
-CPU, but at least it works.
-
-This driver provides 352x288 mode by switching the camera into
-quasi-352x288 RGB mode (800 Kbits per frame) essentially limiting
-this mode to 10 frames per second or less, in ideal conditions on
-the bus (USB is shared, after all). The frame rate
-has to be programmed very conservatively. Additional concern is that
-frame rate depends on brightness setting; therefore the picture can
-be good at one brightness and broken at another! I did not want to fix
-the frame rate at slowest setting, but I had to move it pretty much down
-the scale (so that framerate option barely matters). I also noticed that
-camera after first powering up produces frames slightly faster than during
-consecutive uses. All this means that if you use 352x288 (which is
-default), be warned - you may encounter broken picture on first connect;
-try to adjust brightness - brighter image is slower, so USB will be able
-to send all data. However if you regularly use Model 2 cameras you may
-prefer 176x144 which makes perfectly good I420, with no scaling and
-lesser demands on USB (300 Kbits per second, or 26 frames per second).
-
-Another strange effect of 352x288 mode is the fine vertical grid visible
-on some colored surfaces. I am sure it is caused by me not understanding
-what the camera is trying to say. Blame trade secrets for that.
-
-The camera that I had also has a hardware quirk: if disconnected,
-it needs few minutes to "relax" before it can be plugged in again
-(poorly designed USB processor reset circuit?)
-
-[Veo Stingray with Product ID 0x800C is also Model 2, but I haven't
-observed this particular flaw in it.]
-
-Model 2 camera can be programmed for very high sensitivity (even starlight
-may be enough), this makes it convenient for tinkering with. The driver
-code has enough comments to help a programmer to tweak the camera
-as s/he feels necessary.
-
-WHAT YOU NEED:
-
-- A supported IBM PC (C-it) camera (model 1 or 2)
-
-- A Linux box with USB support (2.3/2.4; 2.2 w/backport may work)
-
-- A Video4Linux compatible frame grabber program such as xawtv.
-
-HOW TO COMPILE THE DRIVER:
-
-You need to compile the driver only if you are a developer
-or if you want to make changes to the code. Most distributions
-precompile all modules, so you can go directly to the next
-section "HOW TO USE THE DRIVER".
-
-The ibmcam driver uses usbvideo helper library (module),
-so if you are studying the ibmcam code you will be led there.
-
-The driver itself consists of only one file in usb/ directory:
-ibmcam.c. This file is included into the Linux kernel build
-process if you configure the kernel for CONFIG_USB_IBMCAM.
-Run "make xconfig" and in USB section you will find the IBM
-camera driver. Select it, save the configuration and recompile.
-
-HOW TO USE THE DRIVER:
-
-I recommend to compile driver as a module. This gives you an
-easier access to its configuration. The camera has many more
-settings than V4L can operate, so some settings are done using
-module options.
-
-To begin with, on most modern Linux distributions the driver
-will be automatically loaded whenever you plug the supported
-camera in. Therefore, you don't need to do anything. However
-if you want to experiment with some module parameters then
-you can load and unload the driver manually, with camera
-plugged in or unplugged.
-
-Typically module is installed with command 'modprobe', like this:
-
-# modprobe ibmcam framerate=1
-
-Alternatively you can use 'insmod' in similar fashion:
-
-# insmod /lib/modules/2.x.y/usb/ibmcam.o framerate=1
-
-Module can be inserted with camera connected or disconnected.
-
-The driver can have options, though some defaults are provided.
-
-Driver options: (* indicates that option is model-dependent)
-
-Name            Type            Range [default] Example
---------------  --------------  --------------  ------------------
-debug           Integer         0-9 [0]         debug=1
-flags           Integer         0-0xFF [0]      flags=0x0d
-framerate       Integer         0-6 [2]         framerate=1
-hue_correction  Integer         0-255 [128]     hue_correction=115
-init_brightness Integer         0-255 [128]     init_brightness=100
-init_contrast   Integer         0-255 [192]     init_contrast=200
-init_color      Integer         0-255 [128]     init_color=130
-init_hue        Integer         0-255 [128]     init_hue=115
-lighting        Integer         0-2* [1]        lighting=2
-sharpness       Integer         0-6* [4]        sharpness=3
-size            Integer         0-2* [2]        size=1
-
-Options for Model 2 only:
-
-Name            Type            Range [default] Example
---------------  --------------  --------------  ------------------
-init_model2_rg  Integer         0..255 [0x70]   init_model2_rg=128
-init_model2_rg2 Integer         0..255 [0x2f]   init_model2_rg2=50
-init_model2_sat Integer         0..255 [0x34]   init_model2_sat=65
-init_model2_yb  Integer         0..255 [0xa0]   init_model2_yb=200
-
-debug           You don't need this option unless you are a developer.
-               If you are a developer then you will see in the code
-               what values do what. 0=off.
-
-flags           This is a bit mask, and you can combine any number of
-               bits to produce what you want. Usually you don't want
-               any of extra features this option provides:
-
-               FLAGS_RETRY_VIDIOCSYNC  1  This bit allows to retry failed
-                                          VIDIOCSYNC ioctls without failing.
-                                          Will work with xawtv, will not
-                                          with xrealproducer. Default is
-                                          not set.
-               FLAGS_MONOCHROME        2  Activates monochrome (b/w) mode.
-               FLAGS_DISPLAY_HINTS     4  Shows colored pixels which have
-                                          magic meaning to developers.
-               FLAGS_OVERLAY_STATS     8  Shows tiny numbers on screen,
-                                          useful only for debugging.
-               FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
-               FLAGS_SEPARATE_FRAMES   32 Shows each frame separately, as
-                                          it was received from the camera.
-                                          Default (not set) is to mix the
-                                          preceding frame in to compensate
-                                          for occasional loss of Isoc data
-                                          on high frame rates.
-               FLAGS_CLEAN_FRAMES      64 Forces "cleanup" of each frame
-                                          prior to use; relevant only if
-                                          FLAGS_SEPARATE_FRAMES is set.
-                                          Default is not to clean frames,
-                                          this is a little faster but may
-                                          produce flicker if frame rate is
-                                          too high and Isoc data gets lost.
-               FLAGS_NO_DECODING      128 This flag turns the video stream
-                                          decoder off, and dumps the raw
-                                          Isoc data from the camera into
-                                          the reading process. Useful to
-                                          developers, but not to users.
-
-framerate       This setting controls frame rate of the camera. This is
-               an approximate setting (in terms of "worst" ... "best")
-               because camera changes frame rate depending on amount
-               of light available. Setting 0 is slowest, 6 is fastest.
-               Beware - fast settings are very demanding and may not
-               work well with all video sizes. Be conservative.
-
-hue_correction  This highly optional setting allows to adjust the
-               hue of the image in a way slightly different from
-               what usual "hue" control does. Both controls affect
-               YUV colorspace: regular "hue" control adjusts only
-               U component, and this "hue_correction" option similarly
-               adjusts only V component. However usually it is enough
-               to tweak only U or V to compensate for colored light or
-               color temperature; this option simply allows more
-               complicated correction when and if it is necessary.
-
-init_brightness These settings specify _initial_ values which will be
-init_contrast   used to set up the camera. If your V4L application has
-init_color      its own controls to adjust the picture then these
-init_hue        controls will be used too. These options allow you to
-               preconfigure the camera when it gets connected, before
-               any V4L application connects to it. Good for webcams.
-
-init_model2_rg  These initial settings alter color balance of the
-init_model2_rg2 camera on hardware level. All four settings may be used
-init_model2_sat to tune the camera to specific lighting conditions. These
-init_model2_yb  settings only apply to Model 2 cameras.
-
-lighting        This option selects one of three hardware-defined
-               photosensitivity settings of the camera. 0=bright light,
-               1=Medium (default), 2=Low light. This setting affects
-               frame rate: the dimmer the lighting the lower the frame
-               rate (because longer exposition time is needed). The
-               Model 2 cameras allow values more than 2 for this option,
-               thus enabling extremely high sensitivity at cost of frame
-               rate, color saturation and imaging sensor noise.
-
-sharpness       This option controls smoothing (noise reduction)
-               made by camera. Setting 0 is most smooth, setting 6
-               is most sharp. Be aware that CMOS sensor used in the
-               camera is pretty noisy, so if you choose 6 you will
-               be greeted with "snowy" image. Default is 4. Model 2
-               cameras do not support this feature.
-
-size            This setting chooses one of several image sizes that are
-               supported by this driver. Cameras may support more, but
-               it's difficult to reverse-engineer all formats.
-               Following video sizes are supported:
-
-               size=0     128x96  (Model 1 only)
-               size=1     160x120
-               size=2     176x144
-               size=3     320x240 (Model 2 only)
-               size=4     352x240 (Model 2 only)
-               size=5     352x288
-               size=6     640x480 (Model 3 only)
-
-               The 352x288 is the native size of the Model 1 sensor
-               array, so it's the best resolution the camera can
-               yield. The best resolution of Model 2 is 176x144, and
-               larger images are produced by stretching the bitmap.
-               Model 3 has sensor with 640x480 grid, and it works too,
-               but the frame rate will be exceptionally low (1-2 FPS);
-               it may be still OK for some applications, like security.
-               Choose the image size you need. The smaller image can
-               support faster frame rate. Default is 352x288.
-
-For more information and the Troubleshooting FAQ visit this URL:
-
-               http://www.linux-usb.org/ibmcam/
-
-WHAT NEEDS TO BE DONE:
-
-- The button on the camera is not used. I don't know how to get to it.
-  I know now how to read button on Model 2, but what to do with it?
-
-- Camera reports its status back to the driver; however I don't know
-  what returned data means. If camera fails at some initialization
-  stage then something should be done, and I don't do that because
-  I don't even know that some command failed. This is mostly Model 1
-  concern because Model 2 uses different commands which do not return
-  status (and seem to complete successfully every time).
-
-- Some flavors of Model 4 NetCameras produce only compressed video
-  streams, and I don't know how to decode them.
-
-CREDITS:
-
-The code is based in no small part on the CPiA driver by Johannes Erdfelt,
-Randy Dunlap, and others. Big thanks to them for their pioneering work on that
-and the USB stack.
-
-I also thank John Lightsey for his donation of the Veo Stingray camera.
diff --git a/Documentation/video4linux/m5602.txt b/Documentation/video4linux/m5602.txt
deleted file mode 100644 (file)
index 4450ab1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-This document describes the ALi m5602 bridge connected
-to the following supported sensors:
-OmniVision OV9650,
-Samsung s5k83a,
-Samsung s5k4aa,
-Micron mt9m111,
-Pixel plus PO1030
-
-This driver mimics the windows drivers, which have a braindead implementation sending bayer-encoded frames at VGA resolution.
-In a perfect world we should be able to reprogram the m5602 and the connected sensor in hardware instead, supporting a range of resolutions and pixelformats
-
-Anyway, have fun and please report any bugs to m560x-driver-devel@lists.sourceforge.net
diff --git a/Documentation/video4linux/ov511.txt b/Documentation/video4linux/ov511.txt
deleted file mode 100644 (file)
index b3326b1..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
--------------------------------------------------------------------------------
-Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC
--------------------------------------------------------------------------------
-
-Author: Mark McClelland
-Homepage: http://alpha.dyndns.org/ov511
-
-INTRODUCTION:
-
-This is a driver for the OV511, a USB-only chip used in many "webcam" devices.
-Any camera using the OV511/OV511+ and the OV6620/OV7610/20/20AE should work.
-Video capture devices that use the Philips SAA7111A decoder also work. It
-supports streaming and capture of color or monochrome video via the Video4Linux
-API. Most V4L apps are compatible with it. Most resolutions with a width and
-height that are a multiple of 8 are supported.
-
-If you need more information, please visit the OV511 homepage at the above URL.
-
-WHAT YOU NEED:
-
-- If you want to help with the development, get the chip's specification docs at
-  http://www.ovt.com/omniusbp.html
-
-- A Video4Linux compatible frame grabber program (I recommend vidcat and xawtv)
-    vidcat is part of the w3cam package:  http://mpx.freeshell.net/
-    xawtv is available at:  http://linux.bytesex.org/xawtv/
-
-HOW TO USE IT:
-
-Note: These are simplified instructions. For complete instructions see:
-       http://alpha.dyndns.org/ov511/install.html
-
-You must have first compiled USB support, support for your specific USB host
-controller (UHCI or OHCI), and Video4Linux support for your kernel (I recommend
-making them modules.) Make sure "Enforce bandwidth allocation" is NOT enabled.
-
-Next, (as root):
-
-       modprobe usbcore
-       modprobe usb-uhci  <OR>  modprobe usb-ohci
-       modprobe videodev
-       modprobe ov511
-
-If it is not already there (it usually is), create the video device:
-
-       mknod /dev/video0 c 81 0
-
-Optionally, symlink /dev/video to /dev/video0
-
-You will have to set permissions on this device to allow you to read/write
-from it:
-
-       chmod 666 /dev/video
-       chmod 666 /dev/video0 (if necessary)
-
-Now you are ready to run a video app! Both vidcat and xawtv work well for me
-at 640x480.
-
-[Using vidcat:]
-
-       vidcat -s 640x480 -p c > test.jpg
-       xview test.jpg
-
-[Using xawtv:]
-
-From the main xawtv directory:
-
-       make clean
-       ./configure
-       make
-       make install
-
-Now you should be able to run xawtv. Right click for the options dialog.
-
-MODULE PARAMETERS:
-
-  You can set these with:  insmod ov511 NAME=VALUE
-  There is currently no way to set these on a per-camera basis.
-
-  NAME: autobright
-  TYPE: integer (Boolean)
-  DEFAULT: 1
-  DESC: Brightness is normally under automatic control and can't be set
-       manually by the video app. Set to 0 for manual control.
-
-  NAME: autogain
-  TYPE: integer (Boolean)
-  DEFAULT: 1
-  DESC: Auto Gain Control enable. This feature is not yet implemented.
-
-  NAME: autoexp
-  TYPE: integer (Boolean)
-  DEFAULT: 1
-  DESC: Auto Exposure Control enable. This feature is not yet implemented.
-
-  NAME: debug
-  TYPE: integer (0-6)
-  DEFAULT: 3
-  DESC: Sets the threshold for printing debug messages. The higher the value,
-       the more is printed. The levels are cumulative, and are as follows:
-         0=no debug messages
-         1=init/detection/unload and other significant messages
-         2=some warning messages
-         3=config/control function calls
-         4=most function calls and data parsing messages
-         5=highly repetitive mesgs
-
-  NAME: snapshot
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: Set to 1 to enable snapshot mode. read()/VIDIOCSYNC will block until
-       the snapshot button is pressed. Note: enabling this mode disables
-       /proc/video/ov511/<minor#>/button
-
-  NAME: cams
-  TYPE: integer (1-4 for OV511, 1-31 for OV511+)
-  DEFAULT: 1
-  DESC: Number of cameras allowed to stream simultaneously on a single bus.
-       Values higher than 1 reduce the data rate of each camera, allowing two
-       or more to be used at once. If you have a complicated setup involving
-       both OV511 and OV511+ cameras, trial-and-error may be necessary for
-       finding the optimum setting.
-
-  NAME: compress
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: Set this to 1 to turn on the camera's compression engine. This can
-       potentially increase the frame rate at the expense of quality, if you
-       have a fast CPU. You must load the proper compression module for your
-       camera before starting your application (ov511_decomp or ov518_decomp).
-
-  NAME: testpat
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: This configures the camera's sensor to transmit a colored test-pattern
-       instead of an image. This does not work correctly yet.
-
-  NAME: dumppix
-  TYPE: integer (0-2)
-  DEFAULT: 0
-  DESC: Dumps raw pixel data and skips post-processing and format conversion.
-       It is for debugging purposes only. Options are:
-               0: Disable (default)
-               1: Dump raw data from camera, excluding headers and trailers
-               2: Dumps data exactly as received from camera
-
-  NAME: led
-  TYPE: integer (0-2)
-  DEFAULT: 1 (Always on)
-  DESC: Controls whether the LED (the little light) on the front of the camera
-       is always off (0), always on (1), or only on when driver is open (2).
-       This is not supported with the OV511, and might only work with certain
-       cameras (ones that actually have the LED wired to the control pin, and
-       not just hard-wired to be on all the time).
-
-  NAME: dump_bridge
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: Dumps the bridge (OV511[+] or OV518[+]) register values to the system
-       log. Only useful for serious debugging/development purposes.
-
-  NAME: dump_sensor
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: Dumps the sensor register values to the system log. Only useful for
-       serious debugging/development purposes.
-
-  NAME: printph
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: Setting this to 1 will dump the first 12 bytes of each isoc frame. This
-       is only useful if you are trying to debug problems with the isoc data
-       stream (i.e.: camera initializes, but vidcat hangs until Ctrl-C). Be
-       warned that this dumps a large number of messages to your kernel log.
-
-  NAME: phy, phuv, pvy, pvuv, qhy, qhuv, qvy, qvuv
-  TYPE: integer (0-63 for phy and phuv, 0-255 for rest)
-  DEFAULT: OV511 default values
-  DESC: These are registers 70h - 77h of the OV511, which control the
-       prediction ranges and quantization thresholds of the compressor, for
-       the Y and UV channels in the horizontal and vertical directions. See
-       the OV511 or OV511+ data sheet for more detailed descriptions. These
-       normally do not need to be changed.
-
-  NAME: lightfreq
-  TYPE: integer (0, 50, or 60)
-  DEFAULT: 0 (use sensor default)
-  DESC: Sets the sensor to match your lighting frequency. This can reduce the
-       appearance of "banding", i.e. horizontal lines or waves of light and
-       dark that are often caused by artificial lighting. Valid values are:
-               0 - Use default (depends on sensor, most likely 60 Hz)
-               50 - For European and Asian 50 Hz power
-               60 - For American 60 Hz power
-
-  NAME: bandingfilter
-  TYPE: integer (Boolean)
-  DEFAULT: 0 (off)
-  DESC: Enables the sensor´s banding filter exposure algorithm. This reduces
-       or stabilizes the "banding" caused by some artificial light sources
-       (especially fluorescent). You might have to set lightfreq correctly for
-       this to work right. As an added bonus, this sometimes makes it
-       possible to capture your monitor´s output.
-
-  NAME: fastset
-  TYPE: integer (Boolean)
-  DEFAULT: 0 (off)
-  DESC: Allows picture settings (brightness, contrast, color, and hue) to take
-       effect immediately, even in the middle of a frame. This reduces the
-       time to change settings, but can ruin frames during the change. Only
-       affects OmniVision sensors.
-
-  NAME: force_palette
-  TYPE: integer (Boolean)
-  DEFAULT: 0 (off)
-  DESC: Forces the palette (color format) to a specific value. If an
-       application requests a different palette, it will be rejected, thereby
-       forcing it to try others until it succeeds. This is useful for forcing
-       greyscale mode with a color camera, for example. Supported modes are:
-               0                           (Allows all the following formats)
-               1   VIDEO_PALETTE_GREY      (Linear greyscale)
-               10  VIDEO_PALETTE_YUV420    (YUV 4:2:0 Planar)
-               15  VIDEO_PALETTE_YUV420P   (YUV 4:2:0 Planar, same as 10)
-
-  NAME: backlight
-  TYPE: integer (Boolean)
-  DEFAULT: 0 (off)
-  DESC: Setting this flag changes the exposure algorithm for OmniVision sensors
-       such that objects in the camera's view (i.e. your head) can be clearly
-       seen when they are illuminated from behind. It reduces or eliminates
-       the sensor's auto-exposure function, so it should only be used when
-       needed. Additionally, it is only supported with the OV6620 and OV7620.
-
-  NAME: unit_video
-  TYPE: Up to 16 comma-separated integers
-  DEFAULT: 0,0,0... (automatically assign the next available minor(s))
-  DESC: You can specify up to 16 minor numbers to be assigned to ov511 devices.
-       For example, "unit_video=1,3" will make the driver use /dev/video1 and
-       /dev/video3 for the first two devices it detects. Additional devices
-       will be assigned automatically starting at the first available device
-       node (/dev/video0 in this case). Note that you cannot specify 0 as a
-       minor number. This feature requires kernel version 2.4.5 or higher.
-
-  NAME: remove_zeros
-  TYPE: integer (Boolean)
-  DEFAULT: 0 (do not skip any incoming data)
-  DESC: Setting this to 1 will remove zero-padding from incoming data. This
-       will compensate for the blocks of corruption that can appear when the
-       camera cannot keep up with the speed of the USB bus (eg. at low frame
-       resolutions). This feature is always enabled when compression is on.
-
-  NAME: mirror
-  TYPE: integer (Boolean)
-  DEFAULT: 0 (off)
-  DESC: Setting this to 1 will reverse ("mirror") the image horizontally. This
-       might be necessary if your camera has a custom lens assembly. This has
-       no effect with video capture devices.
-
-  NAME: ov518_color
-  TYPE: integer (Boolean)
-  DEFAULT: 0 (off)
-  DESC: Enable OV518 color support. This is off by default since it doesn't
-       work most of the time. If you want to try it, you must also load
-       ov518_decomp with the "nouv=0" parameter. If you get improper colors or
-       diagonal lines through the image, restart your video app and try again.
-       Repeat as necessary.
-
-WORKING FEATURES:
- o Color streaming/capture at most widths and heights that are multiples of 8.
- o Monochrome (use force_palette=1 to enable)
- o Setting/getting of saturation, contrast, brightness, and hue (only some of
-   them work the OV7620 and OV7620AE)
- o /proc status reporting
- o SAA7111A video capture support at 320x240 and 640x480
- o Compression support
- o SMP compatibility
-
-HOW TO CONTACT ME:
-
-You can email me at mark@alpha.dyndns.org . Please prefix the subject line
-with "OV511: " so that I am certain to notice your message.
-
-CREDITS:
-
-The code is based in no small part on the CPiA driver by Johannes Erdfelt,
-Randy Dunlap, and others. Big thanks to them for their pioneering work on that
-and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and
-image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio
-Matsuoka for their work as well.
diff --git a/Documentation/video4linux/se401.txt b/Documentation/video4linux/se401.txt
deleted file mode 100644 (file)
index bd6526e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-Linux driver for SE401 based USB cameras
-
-Copyright, 2001, Jeroen Vreeken
-
-
-INTRODUCTION:
-
-The SE401 chip is the used in low-cost usb webcams.
-It is produced by Endpoints Inc. (www.endpoints.com).
-It interfaces directly to a cmos image sensor and USB. The only other major
-part in a se401 based camera is a dram chip.
-
-The following cameras are known to work with this driver:
-
-Aox se401 (non-branded) cameras
-Philips PVCV665 USB VGA webcam 'Vesta Fun'
-Kensington VideoCAM PC Camera Model 67014
-Kensington VideoCAM PC Camera Model 67015
-Kensington VideoCAM PC Camera Model 67016
-Kensington VideoCAM PC Camera Model 67017
-
-
-WHAT YOU NEED:
-
--      USB support
--      VIDEO4LINUX support
-
-More information about USB support for linux can be found at:
-http://www.linux-usb.org
-
-
-MODULE OPTIONS:
-
-When the driver is compiled as a module you can also use the 'flickerless'
-option. With it exposure is limited to values that do not interfere with the
-net frequency. Valid options for this option are 0, 50 and 60. (0=disable,
-50=50hz, 60=60hz)
-
-
-KNOWN PROBLEMS:
-
-The driver works fine with the usb-ohci and uhci host controller drivers,
-the default settings also work with usb-uhci. But sending more than one bulk
-transfer at a time with usb-uhci doesn't work yet.
-Users of usb-ohci and uhci can safely enlarge SE401_NUMSBUF in se401.h in
-order to increase the throughput (and thus framerate).
-
-
-HELP:
-
-The latest info on this driver can be found at:
-http://members.chello.nl/~j.vreeken/se401/
-And questions to me can be send to:
-pe1rxq@amsat.org
index 3f87c7da4ca2e303629b6b878e5e4e329db4aab1..f62fcdbc8b9ffdeb3a92b3131c487df8fc7f08e8 100644 (file)
@@ -9,32 +9,36 @@ The following terms are used in this document:
    of connecting to a variety of systems and interfaces, typically uses i2c for
    control and configuration, and a parallel or a serial bus for data.
  - camera host - an interface, to which a camera is connected. Typically a
-   specialised interface, present on many SoCs, e.g., PXA27x and PXA3xx, SuperH,
+   specialised interface, present on many SoCs, e.g. PXA27x and PXA3xx, SuperH,
    AVR32, i.MX27, i.MX31.
  - camera host bus - a connection between a camera host and a camera. Can be
-   parallel or serial, consists of data and control lines, e.g., clock, vertical
+   parallel or serial, consists of data and control lines, e.g. clock, vertical
    and horizontal synchronization signals.
 
 Purpose of the soc-camera subsystem
 -----------------------------------
 
-The soc-camera subsystem provides a unified API between camera host drivers and
-camera sensor drivers. It implements a V4L2 interface to the user, currently
-only the mmap method is supported.
+The soc-camera subsystem initially provided a unified API between camera host
+drivers and camera sensor drivers. Later the soc-camera sensor API has been
+replaced with the V4L2 standard subdev API. This also made camera driver re-use
+with non-soc-camera hosts possible. The camera host API to the soc-camera core
+has been preserved.
 
-This subsystem has been written to connect drivers for System-on-Chip (SoC)
-video capture interfaces with drivers for CMOS camera sensor chips to enable
-the reuse of sensor drivers with various hosts. The subsystem has been designed
-to support multiple camera host interfaces and multiple cameras per interface,
-although most applications have only one camera sensor.
+Soc-camera implements a V4L2 interface to the user, currently only the "mmap"
+method is supported by host drivers. However, the soc-camera core also provides
+support for the "read" method.
+
+The subsystem has been designed to support multiple camera host interfaces and
+multiple cameras per interface, although most applications have only one camera
+sensor.
 
 Existing drivers
 ----------------
 
-As of 2.6.27-rc4 there are two host drivers in the mainline: pxa_camera.c for
-PXA27x SoCs and sh_mobile_ceu_camera.c for SuperH SoCs, and four sensor drivers:
-mt9m001.c, mt9m111.c, mt9v022.c and a generic soc_camera_platform.c driver. This
-list is not supposed to be updated, look for more examples in your tree.
+As of 3.7 there are seven host drivers in the mainline: atmel-isi.c,
+mx1_camera.c (broken, scheduled for removal), mx2_camera.c, mx3_camera.c,
+omap1_camera.c, pxa_camera.c, sh_mobile_ceu_camera.c, and multiple sensor
+drivers under drivers/media/i2c/soc_camera/.
 
 Camera host API
 ---------------
@@ -45,38 +49,37 @@ soc_camera_host_register(struct soc_camera_host *);
 
 function. The host object can be initialized as follows:
 
-static struct soc_camera_host pxa_soc_camera_host = {
-       .drv_name       = PXA_CAM_DRV_NAME,
-       .ops            = &pxa_soc_camera_host_ops,
-};
+       struct soc_camera_host  *ici;
+       ici->drv_name           = DRV_NAME;
+       ici->ops                = &camera_host_ops;
+       ici->priv               = pcdev;
+       ici->v4l2_dev.dev       = &pdev->dev;
+       ici->nr                 = pdev->id;
 
 All camera host methods are passed in a struct soc_camera_host_ops:
 
-static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
+static struct soc_camera_host_ops camera_host_ops = {
        .owner          = THIS_MODULE,
-       .add            = pxa_camera_add_device,
-       .remove         = pxa_camera_remove_device,
-       .suspend        = pxa_camera_suspend,
-       .resume         = pxa_camera_resume,
-       .set_fmt_cap    = pxa_camera_set_fmt_cap,
-       .try_fmt_cap    = pxa_camera_try_fmt_cap,
-       .init_videobuf  = pxa_camera_init_videobuf,
-       .reqbufs        = pxa_camera_reqbufs,
-       .poll           = pxa_camera_poll,
-       .querycap       = pxa_camera_querycap,
-       .try_bus_param  = pxa_camera_try_bus_param,
-       .set_bus_param  = pxa_camera_set_bus_param,
+       .add            = camera_add_device,
+       .remove         = camera_remove_device,
+       .set_fmt        = camera_set_fmt_cap,
+       .try_fmt        = camera_try_fmt_cap,
+       .init_videobuf2 = camera_init_videobuf2,
+       .poll           = camera_poll,
+       .querycap       = camera_querycap,
+       .set_bus_param  = camera_set_bus_param,
+       /* The rest of host operations are optional */
 };
 
 .add and .remove methods are called when a sensor is attached to or detached
-from the host, apart from performing host-internal tasks they shall also call
-sensor driver's .init and .release methods respectively. .suspend and .resume
-methods implement host's power-management functionality and its their
-responsibility to call respective sensor's methods. .try_bus_param and
-.set_bus_param are used to negotiate physical connection parameters between the
-host and the sensor. .init_videobuf is called by soc-camera core when a
-video-device is opened, further video-buffer management is implemented completely
-by the specific camera host driver. The rest of the methods are called from
+from the host. .set_bus_param is used to configure physical connection
+parameters between the host and the sensor. .init_videobuf2 is called by
+soc-camera core when a video-device is opened, the host driver would typically
+call vb2_queue_init() in this method. Further video-buffer management is
+implemented completely by the specific camera host driver. If the host driver
+supports non-standard pixel format conversion, it should implement a
+.get_formats and, possibly, a .put_formats operations. See below for more
+details about format conversion. The rest of the methods are called from
 respective V4L2 operations.
 
 Camera API
@@ -84,37 +87,21 @@ Camera API
 
 Sensor drivers can use struct soc_camera_link, typically provided by the
 platform, and used to specify to which camera host bus the sensor is connected,
-and arbitrarily provide platform .power and .reset methods for the camera.
-soc_camera_device_register() and soc_camera_device_unregister() functions are
-used to add a sensor driver to or remove one from the system. The registration
-function takes a pointer to struct soc_camera_device as the only parameter.
-This struct can be initialized as follows:
-
-       /* link to driver operations */
-       icd->ops        = &mt9m001_ops;
-       /* link to the underlying physical (e.g., i2c) device */
-       icd->control    = &client->dev;
-       /* window geometry */
-       icd->x_min      = 20;
-       icd->y_min      = 12;
-       icd->x_current  = 20;
-       icd->y_current  = 12;
-       icd->width_min  = 48;
-       icd->width_max  = 1280;
-       icd->height_min = 32;
-       icd->height_max = 1024;
-       icd->y_skip_top = 1;
-       /* camera bus ID, typically obtained from platform data */
-       icd->iface      = icl->bus_id;
-
-struct soc_camera_ops provides .probe and .remove methods, which are called by
-the soc-camera core, when a camera is matched against or removed from a camera
-host bus, .init, .release, .suspend, and .resume are called from the camera host
-driver as discussed above. Other members of this struct provide respective V4L2
-functionality.
-
-struct soc_camera_device also links to an array of struct soc_camera_data_format,
-listing pixel formats, supported by the camera.
+and optionally provide platform .power and .reset methods for the camera. This
+struct is provided to the camera driver via the I2C client device platform data
+and can be obtained, using the soc_camera_i2c_to_link() macro. Care should be
+taken, when using soc_camera_vdev_to_subdev() and when accessing struct
+soc_camera_device, using v4l2_get_subdev_hostdata(): both only work, when
+running on an soc-camera host. The actual camera driver operation is implemented
+using the V4L2 subdev API. Additionally soc-camera camera drivers can use
+auxiliary soc-camera helper functions like soc_camera_power_on() and
+soc_camera_power_off(), which switch regulators, provided by the platform and call
+board-specific power switching methods. soc_camera_apply_board_flags() takes
+camera bus configuration capability flags and applies any board transformations,
+e.g. signal polarity inversion. soc_mbus_get_fmtdesc() can be used to obtain a
+pixel format descriptor, corresponding to a certain media-bus pixel format code.
+soc_camera_limit_side() can be used to restrict beginning and length of a frame
+side, based on camera capabilities.
 
 VIDIOC_S_CROP and VIDIOC_S_FMT behaviour
 ----------------------------------------
@@ -153,8 +140,25 @@ implemented.
 User window geometry is kept in .user_width and .user_height fields in struct
 soc_camera_device and used by the soc-camera core and host drivers. The core
 updates these fields upon successful completion of a .s_fmt() call, but if these
-fields change elsewhere, e.g., during .s_crop() processing, the host driver is
+fields change elsewhere, e.g. during .s_crop() processing, the host driver is
 responsible for updating them.
 
+Format conversion
+-----------------
+
+V4L2 distinguishes between pixel formats, as they are stored in memory, and as
+they are transferred over a media bus. Soc-camera provides support to
+conveniently manage these formats. A table of standard transformations is
+maintained by soc-camera core, which describes, what FOURCC pixel format will
+be obtained, if a media-bus pixel format is stored in memory according to
+certain rules. E.g. if V4L2_MBUS_FMT_YUYV8_2X8 data is sampled with 8 bits per
+sample and stored in memory in the little-endian order with no gaps between
+bytes, data in memory will represent the V4L2_PIX_FMT_YUYV FOURCC format. These
+standard transformations will be used by soc-camera or by camera host drivers to
+configure camera drivers to produce the FOURCC format, requested by the user,
+using the VIDIOC_S_FMT ioctl(). Apart from those standard format conversions,
+host drivers can also provide their own conversion rules by implementing a
+.get_formats and, if required, a .put_formats methods.
+
 --
 Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
diff --git a/Documentation/video4linux/stv680.txt b/Documentation/video4linux/stv680.txt
deleted file mode 100644 (file)
index e3de336..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-Linux driver for STV0680 based USB cameras
-
-Copyright, 2001, Kevin Sisson
-
-
-INTRODUCTION:
-
-STMicroelectronics produces the STV0680B chip, which comes in two
-types, -001 and -003. The -003 version allows the recording and downloading
-of sound clips from the camera, and allows a flash attachment. Otherwise,
-it uses the same commands as the -001 version. Both versions support a
-variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20
-CIF pictures. The STV0680 supports either a serial or a usb interface, and
-video is possible through the usb interface.
-
-The following cameras are known to work with this driver, although any
-camera with Vendor/Product codes of 0553/0202 should work:
-
-Aiptek Pencam (various models)
-Nisis QuickPix 2
-Radio Shack 'Kid's digital camera' (#60-1207)
-At least one Trust Spycam model
-Several other European brand models
-
-WHAT YOU NEED:
-
--      USB support
--      VIDEO4LINUX support
-
-More information about USB support for linux can be found at:
-http://www.linux-usb.org
-
-
-MODULE OPTIONS:
-
-When the driver is compiled as a module, you can set a "swapRGB=1"
-option, if necessary, for those applications that require it
-(such as xawtv). However, the driver should detect and set this
-automatically, so this option should not normally be used.
-
-
-KNOWN PROBLEMS:
-
-The driver seems to work better with the usb-ohci than the usb-uhci host
-controller driver.
-
-HELP:
-
-The latest info on this driver can be found at:
-http://personal.clt.bellsouth.net/~kjsisson or at
-http://stv0680-usb.sourceforge.net
-
-Any questions to me can be send to:  kjsisson@bellsouth.net
index 32bfe926e8d77717e67a9e485ca89b398f5c26a8..0a1ef671c9d42eb456c0f60738519ad1c98f6479 100644 (file)
@@ -68,8 +68,7 @@ Structure of the framework
 The framework closely resembles the driver structure: it has a v4l2_device
 struct for the device instance data, a v4l2_subdev struct to refer to
 sub-device instances, the video_device struct stores V4L2 device node data
-and in the future a v4l2_fh struct will keep track of filehandle instances
-(this is not yet implemented).
+and the v4l2_fh struct keeps track of filehandle instances.
 
 The V4L2 framework also optionally integrates with the media framework. If a
 driver sets the struct v4l2_device mdev field, sub-devices and video nodes
diff --git a/Documentation/video4linux/w9968cf.txt b/Documentation/video4linux/w9968cf.txt
deleted file mode 100644 (file)
index 9649450..0000000
+++ /dev/null
@@ -1,458 +0,0 @@
-
-                  W996[87]CF JPEG USB Dual Mode Camera Chip
-                    Driver for Linux 2.6 (basic version)
-                  =========================================
-
-                              - Documentation -
-
-
-Index
-=====
-1.  Copyright
-2.  Disclaimer
-3.  License
-4.  Overview
-5.  Supported devices
-6.  Module dependencies
-7.  Module loading
-8.  Module parameters
-9.  Contact information
-10. Credits
-
-
-1. Copyright
-============
-Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it>
-
-
-2. Disclaimer
-=============
-Winbond is a trademark of Winbond Electronics Corporation.
-This software is not sponsored or developed by Winbond.
-
-
-3. License
-==========
-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.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-4. Overview
-===========
-This driver supports the video streaming capabilities of the devices mounting
-Winbond W9967CF and Winbond W9968CF JPEG USB Dual Mode Camera Chips. OV681
-based cameras should be supported as well.
-
-The driver is divided into two modules: the basic one, "w9968cf", is needed for
-the supported devices to work; the second one, "w9968cf-vpp", is an optional
-module, which provides some useful video post-processing functions like video
-decoding, up-scaling and colour conversions.
-
-Note that the official kernels do neither include nor support the second
-module for performance purposes. Therefore, it is always recommended to
-download and install the latest and complete release of the driver,
-replacing the existing one, if present.
-
-The latest and full-featured version of the W996[87]CF driver can be found at:
-http://www.linux-projects.org. Please refer to the documentation included in
-that package, if you are going to use it.
-
-Up to 32 cameras can be handled at the same time. They can be connected and
-disconnected from the host many times without turning off the computer, if
-your system supports the hotplug facility.
-
-To change the default settings for each camera, many parameters can be passed
-through command line when the module is loaded into memory.
-
-The driver relies on the Video4Linux, USB and I2C core modules. It has been
-designed to run properly on SMP systems as well. An additional module,
-"ovcamchip", is mandatory; it provides support for some OmniVision image
-sensors connected to the W996[87]CF chips; if found in the system, the module
-will be automatically loaded by default (provided that the kernel has been
-compiled with the automatic module loading option).
-
-
-5. Supported devices
-====================
-At the moment, known W996[87]CF and OV681 based devices are:
-- Aroma Digi Pen VGA Dual Mode ADG-5000 (unknown image sensor)
-- AVerMedia AVerTV USB (SAA7111A, Philips FI1216Mk2 tuner, PT2313L audio chip)
-- Creative Labs Video Blaster WebCam Go (OmniVision OV7610 sensor)
-- Creative Labs Video Blaster WebCam Go Plus (OmniVision OV7620 sensor)
-- Lebon LDC-035A (unknown image sensor)
-- Ezonics EZ-802 EZMega Cam (OmniVision OV8610C sensor)
-- OmniVision OV8610-EDE (OmniVision OV8610 sensor)
-- OPCOM Digi Pen VGA Dual Mode Pen Camera (unknown image sensor)
-- Pretec Digi Pen-II (OmniVision OV7620 sensor)
-- Pretec DigiPen-480 (OmniVision OV8610 sensor)
-
-If you know any other W996[87]CF or OV681 based cameras, please contact me.
-
-The list above does not imply that all those devices work with this driver: up
-until now only webcams that have an image sensor supported by the "ovcamchip"
-module work. Kernel messages will always tell you whether this is case.
-
-Possible external microcontrollers of those webcams are not supported: this
-means that still images cannot be downloaded from the device memory.
-
-Furthermore, it's worth to note that I was only able to run tests on my
-"Creative Labs Video Blaster WebCam Go". Donations of other models, for
-additional testing and full support, would be much appreciated.
-
-
-6. Module dependencies
-======================
-For it to work properly, the driver needs kernel support for Video4Linux, USB
-and I2C, and the "ovcamchip" module for the image sensor. Make sure you are not
-actually using any external "ovcamchip" module, given that the W996[87]CF
-driver depends on the version of the module present in the official kernels.
-
-The following options of the kernel configuration file must be enabled and
-corresponding modules must be compiled:
-
-       # Multimedia devices
-       #
-       CONFIG_VIDEO_DEV=m
-
-       # I2C support
-       #
-       CONFIG_I2C=m
-
-The I2C core module can be compiled statically in the kernel as well.
-
-       # OmniVision Camera Chip support
-       #
-       CONFIG_VIDEO_OVCAMCHIP=m
-
-       # USB support
-       #
-       CONFIG_USB=m
-
-In addition, depending on the hardware being used, only one of the modules
-below is necessary:
-
-       # USB Host Controller Drivers
-       #
-       CONFIG_USB_EHCI_HCD=m
-       CONFIG_USB_UHCI_HCD=m
-       CONFIG_USB_OHCI_HCD=m
-
-And finally:
-
-       # USB Multimedia devices
-       #
-       CONFIG_USB_W9968CF=m
-
-
-7. Module loading
-=================
-To use the driver, it is necessary to load the "w9968cf" module into memory
-after every other module required.
-
-Loading can be done this way, from root:
-
-       [root@localhost home]# modprobe usbcore
-       [root@localhost home]# modprobe i2c-core
-       [root@localhost home]# modprobe videodev
-       [root@localhost home]# modprobe w9968cf
-
-At this point the pertinent devices should be recognized: "dmesg" can be used
-to analyze kernel messages:
-
-       [user@localhost home]$ dmesg
-
-There are a lot of parameters the module can use to change the default
-settings for each device. To list every possible parameter with a brief
-explanation about them and which syntax to use, it is recommended to run the
-"modinfo" command:
-
-       [root@locahost home]# modinfo w9968cf
-
-
-8. Module parameters
-====================
-Module parameters are listed below:
--------------------------------------------------------------------------------
-Name:            ovmod_load
-Type:            bool
-Syntax:          <0|1>
-Description:     Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled.
-                If enabled, 'insmod' searches for the required 'ovcamchip'
-                module in the system, according to its configuration, and
-                loads that module automatically. This action is performed as
-                once soon as the 'w9968cf' module is loaded into memory.
-Default:         1
--------------------------------------------------------------------------------
-Name:           simcams
-Type:           int
-Syntax:         <n>
-Description:    Number of cameras allowed to stream simultaneously.
-               n may vary from 0 to 32.
-Default:        32
--------------------------------------------------------------------------------
-Name:           video_nr
-Type:           int array (min = 0, max = 32)
-Syntax:         <-1|n[,...]>
-Description:    Specify V4L minor mode number.
-               -1 = use next available
-                n = use minor number n
-               You can specify up to 32 cameras this way.
-               For example:
-               video_nr=-1,2,-1 would assign minor number 2 to the second
-               recognized camera and use auto for the first one and for every
-               other camera.
-Default:        -1
--------------------------------------------------------------------------------
-Name:           packet_size
-Type:           int array (min = 0, max = 32)
-Syntax:         <n[,...]>
-Description:    Specify the maximum data payload size in bytes for alternate
-               settings, for each device. n is scaled between 63 and 1023.
-Default:        1023
--------------------------------------------------------------------------------
-Name:           max_buffers
-Type:           int array (min = 0, max = 32)
-Syntax:         <n[,...]>
-Description:    For advanced users.
-               Specify the maximum number of video frame buffers to allocate
-               for each device, from 2 to 32.
-Default:        2
--------------------------------------------------------------------------------
-Name:           double_buffer
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Hardware double buffering: 0 disabled, 1 enabled.
-               It should be enabled if you want smooth video output: if you
-               obtain out of sync. video, disable it, or try to
-               decrease the 'clockdiv' module parameter value.
-Default:        1 for every device.
--------------------------------------------------------------------------------
-Name:           clamping
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Video data clamping: 0 disabled, 1 enabled.
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           filter_type
-Type:           int array (min = 0, max = 32)
-Syntax:         <0|1|2[,...]>
-Description:    Video filter type.
-               0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
-               The filter is used to reduce noise and aliasing artifacts
-               produced by the CCD or CMOS image sensor.
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           largeview
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Large view: 0 disabled, 1 enabled.
-Default:        1 for every device.
--------------------------------------------------------------------------------
-Name:           upscaling
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Software scaling (for non-compressed video only):
-               0 disabled, 1 enabled.
-               Disable it if you have a slow CPU or you don't have enough
-               memory.
-Default:        0 for every device.
-Note:           If 'w9968cf-vpp' is not present, this parameter is set to 0.
--------------------------------------------------------------------------------
-Name:           decompression
-Type:           int array (min = 0, max = 32)
-Syntax:         <0|1|2[,...]>
-Description:    Software video decompression:
-               0 = disables decompression
-                   (doesn't allow formats needing decompression).
-               1 = forces decompression
-                   (allows formats needing decompression only).
-               2 = allows any permitted formats.
-               Formats supporting (de)compressed video are YUV422P and
-               YUV420P/YUV420 in any resolutions where width and height are
-               multiples of 16.
-Default:        2 for every device.
-Note:           If 'w9968cf-vpp' is not present, forcing decompression is not
-               allowed; in this case this parameter is set to 2.
--------------------------------------------------------------------------------
-Name:           force_palette
-Type:           int array (min = 0, max = 32)
-Syntax:         <0|9|10|13|15|8|7|1|6|3|4|5[,...]>
-Description:    Force picture palette.
-               In order:
-                0 = Off - allows any of the following formats:
-                9 = UYVY    16 bpp - Original video, compression disabled
-               10 = YUV420  12 bpp - Original video, compression enabled
-               13 = YUV422P 16 bpp - Original video, compression enabled
-               15 = YUV420P 12 bpp - Original video, compression enabled
-                8 = YUVY    16 bpp - Software conversion from UYVY
-                7 = YUV422  16 bpp - Software conversion from UYVY
-                1 = GREY     8 bpp - Software conversion from UYVY
-                6 = RGB555  16 bpp - Software conversion from UYVY
-                3 = RGB565  16 bpp - Software conversion from UYVY
-                4 = RGB24   24 bpp - Software conversion from UYVY
-                5 = RGB32   32 bpp - Software conversion from UYVY
-               When not 0, this parameter will override 'decompression'.
-Default:        0 for every device. Initial palette is 9 (UYVY).
-Note:           If 'w9968cf-vpp' is not present, this parameter is set to 9.
--------------------------------------------------------------------------------
-Name:           force_rgb
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Read RGB video data instead of BGR:
-               1 = use RGB component ordering.
-               0 = use BGR component ordering.
-               This parameter has effect when using RGBX palettes only.
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           autobright
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Image sensor automatically changes brightness:
-               0 = no, 1 = yes
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           autoexp
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Image sensor automatically changes exposure:
-               0 = no, 1 = yes
-Default:        1 for every device.
--------------------------------------------------------------------------------
-Name:           lightfreq
-Type:           int array (min = 0, max = 32)
-Syntax:         <50|60[,...]>
-Description:    Light frequency in Hz:
-               50 for European and Asian lighting, 60 for American lighting.
-Default:        50 for every device.
--------------------------------------------------------------------------------
-Name:           bandingfilter
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Banding filter to reduce effects of fluorescent
-               lighting:
-               0 disabled, 1 enabled.
-               This filter tries to reduce the pattern of horizontal
-               light/dark bands caused by some (usually fluorescent) lighting.
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           clockdiv
-Type:           int array (min = 0, max = 32)
-Syntax:         <-1|n[,...]>
-Description:    Force pixel clock divisor to a specific value (for experts):
-               n may vary from 0 to 127.
-               -1 for automatic value.
-               See also the 'double_buffer' module parameter.
-Default:        -1 for every device.
--------------------------------------------------------------------------------
-Name:           backlight
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Objects are lit from behind:
-               0 = no, 1 = yes
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           mirror
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    Reverse image horizontally:
-               0 = no, 1 = yes
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           monochrome
-Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]>
-Description:    The image sensor is monochrome:
-               0 = no, 1 = yes
-Default:        0 for every device.
--------------------------------------------------------------------------------
-Name:           brightness
-Type:           long array (min = 0, max = 32)
-Syntax:         <n[,...]>
-Description:    Set picture brightness (0-65535).
-               This parameter has no effect if 'autobright' is enabled.
-Default:        31000 for every device.
--------------------------------------------------------------------------------
-Name:           hue
-Type:           long array (min = 0, max = 32)
-Syntax:         <n[,...]>
-Description:    Set picture hue (0-65535).
-Default:        32768 for every device.
--------------------------------------------------------------------------------
-Name:           colour
-Type:           long array (min = 0, max = 32)
-Syntax:         <n[,...]>
-Description:    Set picture saturation (0-65535).
-Default:        32768 for every device.
--------------------------------------------------------------------------------
-Name:           contrast
-Type:           long array (min = 0, max = 32)
-Syntax:         <n[,...]>
-Description:    Set picture contrast (0-65535).
-Default:        50000 for every device.
--------------------------------------------------------------------------------
-Name:           whiteness
-Type:           long array (min = 0, max = 32)
-Syntax:         <n[,...]>
-Description:    Set picture whiteness (0-65535).
-Default:        32768 for every device.
--------------------------------------------------------------------------------
-Name:           debug
-Type:           int
-Syntax:         <n>
-Description:    Debugging information level, from 0 to 6:
-               0 = none (use carefully)
-               1 = critical errors
-               2 = significant information
-               3 = configuration or general messages
-               4 = warnings
-               5 = called functions
-               6 = function internals
-               Level 5 and 6 are useful for testing only, when only one
-               device is used.
-Default:        2
--------------------------------------------------------------------------------
-Name:           specific_debug
-Type:           bool
-Syntax:         <0|1>
-Description:    Enable or disable specific debugging messages:
-               0 = print messages concerning every level <= 'debug' level.
-               1 = print messages concerning the level indicated by 'debug'.
-Default:        0
--------------------------------------------------------------------------------
-
-
-9. Contact information
-======================
-I may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
-
-I can accept GPG/PGP encrypted e-mail. My GPG key ID is 'FCE635A4'.
-My public 1024-bit key should be available at your keyserver; the fingerprint
-is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
-
-
-10. Credits
-==========
-The development would not have proceed much further without having looked at
-the source code of other drivers and without the help of several persons; in
-particular:
-
-- the I2C interface to kernel and high-level image sensor control routines have
-  been taken from the OV511 driver by Mark McClelland;
-
-- memory management code has been copied from the bttv driver by Ralph Metzler,
-  Marcus Metzler and Gerd Knorr;
-
-- the low-level I2C read function has been written by Frederic Jouault;
-
-- the low-level I2C fast write function has been written by Piotr Czerczak.
diff --git a/Documentation/video4linux/zc0301.txt b/Documentation/video4linux/zc0301.txt
deleted file mode 100644 (file)
index b41c83c..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-
-             ZC0301 and ZC0301P Image Processor and Control Chip
-                               Driver for Linux
-             ===================================================
-
-                              - Documentation -
-
-
-Index
-=====
-1.  Copyright
-2.  Disclaimer
-3.  License
-4.  Overview and features
-5.  Module dependencies
-6.  Module loading
-7.  Module parameters
-8.  Supported devices
-9.  Notes for V4L2 application developers
-10. Contact information
-11. Credits
-
-
-1. Copyright
-============
-Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
-
-
-2. Disclaimer
-=============
-This software is not developed or sponsored by Z-Star Microelectronics Corp.
-Trademarks are property of their respective owner.
-
-
-3. License
-==========
-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.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-4. Overview and features
-========================
-This driver supports the video interface of the devices mounting the ZC0301 or
-ZC0301P Image Processors and Control Chips.
-
-The driver relies on the Video4Linux2 and USB core modules. It has been
-designed to run properly on SMP systems as well.
-
-The latest version of the ZC0301[P] driver can be found at the following URL:
-http://www.linux-projects.org/
-
-Some of the features of the driver are:
-
-- full compliance with the Video4Linux2 API (see also "Notes for V4L2
-  application developers" paragraph);
-- available mmap or read/poll methods for video streaming through isochronous
-  data transfers;
-- automatic detection of image sensor;
-- video format is standard JPEG;
-- dynamic driver control thanks to various module parameters (see "Module
-  parameters" paragraph);
-- up to 64 cameras can be handled at the same time; they can be connected and
-  disconnected from the host many times without turning off the computer, if
-  the system supports hotplugging;
-
-
-5. Module dependencies
-======================
-For it to work properly, the driver needs kernel support for Video4Linux and
-USB.
-
-The following options of the kernel configuration file must be enabled and
-corresponding modules must be compiled:
-
-       # Multimedia devices
-       #
-       CONFIG_VIDEO_DEV=m
-
-       # USB support
-       #
-       CONFIG_USB=m
-
-In addition, depending on the hardware being used, the modules below are
-necessary:
-
-       # USB Host Controller Drivers
-       #
-       CONFIG_USB_EHCI_HCD=m
-       CONFIG_USB_UHCI_HCD=m
-       CONFIG_USB_OHCI_HCD=m
-
-The ZC0301 controller also provides a built-in microphone interface. It is
-supported by the USB Audio driver thanks to the ALSA API:
-
-       # Sound
-       #
-       CONFIG_SOUND=y
-
-       # Advanced Linux Sound Architecture
-       #
-       CONFIG_SND=m
-
-       # USB devices
-       #
-       CONFIG_SND_USB_AUDIO=m
-
-And finally:
-
-       # V4L USB devices
-       #
-       CONFIG_USB_ZC0301=m
-
-
-6. Module loading
-=================
-To use the driver, it is necessary to load the "zc0301" module into memory
-after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
-"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
-"uhci-hcd" or "ohci-hcd".
-
-Loading can be done as shown below:
-
-       [root@localhost home]# modprobe zc0301
-
-At this point the devices should be recognized. You can invoke "dmesg" to
-analyze kernel messages and verify that the loading process has gone well:
-
-       [user@localhost home]$ dmesg
-
-
-7. Module parameters
-====================
-Module parameters are listed below:
--------------------------------------------------------------------------------
-Name:           video_nr
-Type:           short array (min = 0, max = 64)
-Syntax:         <-1|n[,...]>
-Description:    Specify V4L2 minor mode number:
-               -1 = use next available
-                n = use minor number n
-               You can specify up to 64 cameras this way.
-               For example:
-               video_nr=-1,2,-1 would assign minor number 2 to the second
-               registered camera and use auto for the first one and for every
-               other camera.
-Default:        -1
--------------------------------------------------------------------------------
-Name:           force_munmap
-Type:           bool array (min = 0, max = 64)
-Syntax:         <0|1[,...]>
-Description:    Force the application to unmap previously mapped buffer memory
-               before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-               all the applications support this feature. This parameter is
-               specific for each detected camera.
-               0 = do not force memory unmapping
-               1 = force memory unmapping (save memory)
-Default:        0
--------------------------------------------------------------------------------
-Name:           frame_timeout
-Type:           uint array (min = 0, max = 64)
-Syntax:         <n[,...]>
-Description:    Timeout for a video frame in seconds. This parameter is
-               specific for each detected camera. This parameter can be
-               changed at runtime thanks to the /sys filesystem interface.
-Default:        2
--------------------------------------------------------------------------------
-Name:           debug
-Type:           ushort
-Syntax:         <n>
-Description:    Debugging information level, from 0 to 3:
-               0 = none (use carefully)
-               1 = critical errors
-               2 = significant information
-               3 = more verbose messages
-               Level 3 is useful for testing only, when only one device
-               is used at the same time. It also shows some information
-               about the hardware being detected. This module parameter can be
-               changed at runtime thanks to the /sys filesystem interface.
-Default:        2
--------------------------------------------------------------------------------
-
-
-8. Supported devices
-====================
-None of the names of the companies as well as their products will be mentioned
-here. They have never collaborated with the author, so no advertising.
-
-From the point of view of a driver, what unambiguously identify a device are
-its vendor and product USB identifiers. Below is a list of known identifiers of
-devices mounting the ZC0301 Image Processor and Control Chips:
-
-Vendor ID  Product ID
----------  ----------
-0x041e     0x4017
-0x041e     0x401c
-0x041e     0x401e
-0x041e     0x401f
-0x041e     0x4022
-0x041e     0x4034
-0x041e     0x4035
-0x041e     0x4036
-0x041e     0x403a
-0x0458     0x7007
-0x0458     0x700c
-0x0458     0x700f
-0x046d     0x08ae
-0x055f     0xd003
-0x055f     0xd004
-0x0ac8     0x0301
-0x0ac8     0x301b
-0x0ac8     0x303b
-0x10fd     0x0128
-0x10fd     0x8050
-0x10fd     0x804e
-
-The list above does not imply that all those devices work with this driver: up
-until now only the ones that mount the following image sensors are supported;
-kernel messages will always tell you whether this is the case:
-
-Model       Manufacturer
------       ------------
-PAS202BCB   PixArt Imaging, Inc.
-PB-0330     Photobit Corporation
-
-
-9. Notes for V4L2 application developers
-========================================
-This driver follows the V4L2 API specifications. In particular, it enforces two
-rules:
-
-- exactly one I/O method, either "mmap" or "read", is associated with each
-file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method;
-
-- although it is not mandatory, previously mapped buffer memory should always
-be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's.
-The same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map the buffers again before any I/O
-attempts on them.
-
-
-10. Contact information
-=======================
-The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
-
-GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
-'FCE635A4'; the public 1024-bit key should be available at any keyserver;
-the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
-
-
-11. Credits
-===========
-- Information about the chip internals needed to enable the I2C protocol have
-  been taken from the documentation of the ZC030x Video4Linux1 driver written
-  by Andrew Birkett <andy@nobugs.org>;
-- The initialization values of the ZC0301 controller connected to the PAS202BCB
-  and PB-0330 image sensors have been taken from the SPCA5XX driver maintained
-  by Michel Xhaard <mxhaard@magic.fr>;
-- Stanislav Lechev donated one camera.
index 4e2a1f67a1fcf00b553e8190947368d240d74b44..376117d5518da2703984a58c624ccbd3fdd328f0 100644 (file)
@@ -464,6 +464,14 @@ S: Maintained
 F:     drivers/scsi/aic7xxx/
 F:     drivers/scsi/aic7xxx_old/
 
+AIMSLAB FM RADIO RECEIVER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/radio-aimslab*
+
 AIO
 M:     Benjamin LaHaise <bcrl@kvack.org>
 L:     linux-aio@kvack.org
@@ -558,6 +566,18 @@ L: linux-rdma@vger.kernel.org
 S:     Maintained
 F:     drivers/infiniband/hw/amso1100/
 
+ANALOG DEVICES INC AD9389B DRIVER
+M:     Hans Verkuil <hans.verkuil@cisco.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/i2c/ad9389b*
+
+ANALOG DEVICES INC ADV7604 DRIVER
+M:     Hans Verkuil <hans.verkuil@cisco.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/i2c/adv7604*
+
 ANALOG DEVICES INC ASOC CODEC DRIVERS
 M:     Lars-Peter Clausen <lars@metafoo.de>
 L:     device-drivers-devel@blackfin.uclinux.org
@@ -1119,6 +1139,14 @@ F:       arch/arm/mach-s5pv210/mach-goni.c
 F:     arch/arm/mach-exynos/mach-universal_c210.c
 F:     arch/arm/mach-exynos/mach-nuri.c
 
+ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
+M:     Kyungmin Park <kyungmin.park@samsung.com>
+M:     Kamil Debski <k.debski@samsung.com>
+L:     linux-arm-kernel@lists.infradead.org
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/platform/s5p-g2d/
+
 ARM/SAMSUNG S5P SERIES FIMC SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
@@ -1412,7 +1440,7 @@ ATMEL ISI DRIVER
 M:     Josh Wu <josh.wu@atmel.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
-F:     drivers/media/platform/atmel-isi.c
+F:     drivers/media/platform/soc_camera/atmel-isi.c
 F:     include/media/atmel-isi.h
 
 ATMEL LCDFB DRIVER
@@ -1509,6 +1537,14 @@ T:       git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/dvb-usb-v2/az6007.c
 
+AZTECH FM RADIO RECEIVER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/radio-aztech*
+
 B43 WIRELESS DRIVER
 M:     Stefano Brivio <stefano.brivio@polimi.it>
 L:     linux-wireless@vger.kernel.org
@@ -1790,6 +1826,14 @@ S:       Supported
 F:     Documentation/filesystems/caching/cachefiles.txt
 F:     fs/cachefiles/
 
+CADET FM/AM RADIO RECEIVER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/radio-cadet*
+
 CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
 M:     Jonathan Corbet <corbet@lwn.net>
 L:     linux-media@vger.kernel.org
@@ -2187,6 +2231,15 @@ F:       Documentation/video4linux/cx18.txt
 F:     drivers/media/pci/cx18/
 F:     include/uapi/linux/ivtv*
 
+CX2341X MPEG ENCODER HELPER MODULE
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/i2c/cx2341x*
+F:     include/media/cx2341x*
+
 CX88 VIDEO4LINUX DRIVER
 M:     Mauro Carvalho Chehab <mchehab@redhat.com>
 L:     linux-media@vger.kernel.org
@@ -2558,6 +2611,13 @@ S:       Maintained
 F:     drivers/gpu/drm/tegra/
 F:     Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
 
+DSBR100 USB FM RADIO DRIVER
+M:     Alexey Klimov <klimov.linux@gmail.com>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/radio/dsbr100.c
+
 DSCC4 DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
@@ -2622,7 +2682,7 @@ W:        http://github.com/mkrufky
 Q:     http://patchwork.linuxtv.org/project/linux-media/list/
 T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
-F:     drivers/media/usb/dvb-usb-v2/cxusb*
+F:     drivers/media/usb/dvb-usb/cxusb*
 
 DVB_USB_CYPRESS_FIRMWARE MEDIA DRIVER
 M:     Antti Palosaari <crope@iki.fi>
@@ -3319,6 +3379,14 @@ W:       http://www.icp-vortex.com/
 S:     Supported
 F:     drivers/scsi/gdt*
 
+GEMTEK FM RADIO RECEIVER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/radio-gemtek*
+
 GENERIC GPIO I2C DRIVER
 M:     Haavard Skinnemoen <hskinnemoen@gmail.com>
 S:     Supported
@@ -4202,6 +4270,14 @@ F:       Documentation/isapnp.txt
 F:     drivers/pnp/isapnp/
 F:     include/linux/isapnp.h
 
+ISA RADIO MODULE
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/radio-isa*
+
 iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER
 M:     Peter Jones <pjones@redhat.com>
 M:     Konrad Rzeszutek Wilk <konrad@kernel.org>
@@ -4358,6 +4434,14 @@ W:       http://lse.sourceforge.net/kdump/
 S:     Maintained
 F:     Documentation/kdump/
 
+KEENE FM RADIO TRANSMITTER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/radio-keene*
+
 KERNEL AUTOMOUNTER v4 (AUTOFS4)
 M:     Ian Kent <raven@themaw.net>
 L:     autofs@vger.kernel.org
@@ -4831,6 +4915,13 @@ Q:       http://patchwork.linuxtv.org/project/linux-media/list/
 S:     Maintained
 F:     drivers/media/dvb-frontends/m88rs2000*
 
+MA901 MASTERKIT USB FM RADIO DRIVER
+M:      Alexey Klimov <klimov.linux@gmail.com>
+L:      linux-media@vger.kernel.org
+T:      git git://linuxtv.org/media_tree.git
+S:      Maintained
+F:      drivers/media/radio/radio-ma901.c
+
 MAC80211
 M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
@@ -4928,6 +5019,14 @@ S:       Maintained
 F:     Documentation/hwmon/max6650
 F:     drivers/hwmon/max6650.c
 
+MAXIRADIO FM RADIO RECEIVER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/radio-maxiradio*
+
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
 M:     Mauro Carvalho Chehab <mchehab@redhat.com>
 P:     LinuxTV.org Project
@@ -4950,6 +5049,14 @@ F:       include/uapi/linux/meye.h
 F:     include/uapi/linux/ivtv*
 F:     include/uapi/linux/uvcvideo.h
 
+MEDIAVISION PRO MOVIE STUDIO DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Odd Fixes
+F:     drivers/media/parport/pms*
+
 MEGARAID SCSI DRIVERS
 M:     Neela Syam Kolli <megaraidlinux@lsi.com>
 L:     linux-scsi@vger.kernel.org
@@ -5019,6 +5126,14 @@ S:       Supported
 F:     Documentation/mips/
 F:     arch/mips/
 
+MIROSOUND PCM20 FM RADIO RECEIVER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Odd Fixes
+F:     drivers/media/radio/radio-miropcm20*
+
 MODULE SUPPORT
 M:     Rusty Russell <rusty@rustcorp.com.au>
 S:     Maintained
@@ -6198,6 +6313,14 @@ L:       linux-hexagon@vger.kernel.org
 S:     Supported
 F:     arch/hexagon/
 
+QUICKCAM PARALLEL PORT WEBCAMS
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Odd Fixes
+F:     drivers/media/parport/*-qcam*
+
 RADOS BLOCK DEVICE (RBD)
 M:     Yehuda Sadeh <yehuda@inktank.com>
 M:     Sage Weil <sage@inktank.com>
@@ -6471,6 +6594,14 @@ L:       linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/mmc/host/s3cmci.*
 
+SAA6588 RDS RECEIVER DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Odd Fixes
+F:     drivers/media/i2c/saa6588*
+
 SAA7134 VIDEO4LINUX DRIVER
 M:     Mauro Carvalho Chehab <mchehab@redhat.com>
 L:     linux-media@vger.kernel.org
@@ -6481,10 +6612,9 @@ F:       Documentation/video4linux/saa7134/
 F:     drivers/media/pci/saa7134/
 
 SAA7146 VIDEO4LINUX-2 DRIVER
-M:     Michael Hunold <michael@mihu.de>
+M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     linux-media@vger.kernel.org
 T:     git git://linuxtv.org/media_tree.git
-W:     http://www.mihu.de/linux/saa7146
 S:     Maintained
 F:     drivers/media/common/saa7146/
 F:     drivers/media/pci/saa7146/
@@ -6783,6 +6913,38 @@ M:       Robin Holt <holt@sgi.com>
 S:     Maintained
 F:     drivers/misc/sgi-xp/
 
+SI470X FM RADIO RECEIVER I2C DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Odd Fixes
+F:     drivers/media/radio/si470x/radio-si470x-i2c.c
+
+SI470X FM RADIO RECEIVER USB DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/radio/si470x/radio-si470x-common.c
+F:     drivers/media/radio/si470x/radio-si470x.h
+F:     drivers/media/radio/si470x/radio-si470x-usb.c
+
+SH_VEU V4L2 MEM2MEM DRIVER
+M:     Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/platform/sh_veu.c
+F:     include/media/sh_veu.h
+
+SH_VOU V4L2 OUTPUT DRIVER
+M:     Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/platform/sh_vou.c
+F:     include/media/sh_vou.h
+
 SIMPLE FIRMWARE INTERFACE (SFI)
 M:     Len Brown <lenb@kernel.org>
 L:     sfi-devel@simplefirmware.org
@@ -7455,6 +7617,14 @@ T:       git git://linuxtv.org/mkrufky/tuners.git
 S:     Maintained
 F:     drivers/media/tuners/tda8290.*
 
+TDA9840 MEDIA DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/i2c/tda9840*
+
 TEA5761 TUNER DRIVER
 M:     Mauro Carvalho Chehab <mchehab@redhat.com>
 L:     linux-media@vger.kernel.org
@@ -7471,6 +7641,22 @@ T:       git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/tuners/tea5767.*
 
+TEA6415C MEDIA DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/i2c/tea6415c*
+
+TEA6420 MEDIA DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/i2c/tea6420*
+
 TEAM DRIVER
 M:     Jiri Pirko <jpirko@redhat.com>
 L:     netdev@vger.kernel.org
@@ -8087,6 +8273,14 @@ S:       Maintained
 F:     drivers/media/usb/uvc/
 F:     include/uapi/linux/uvcvideo.h
 
+USB VISION DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Odd Fixes
+F:     drivers/media/usb/usbvision/
+
 USB WEBCAM GADGET
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:     linux-usb@vger.kernel.org
@@ -8234,6 +8428,14 @@ L:       netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/via/via-velocity.*
 
+VIVI VIRTUAL VIDEO DRIVER
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+W:     http://linuxtv.org
+S:     Maintained
+F:     drivers/media/platform/vivi*
+
 VLAN (802.1Q)
 M:     Patrick McHardy <kaber@trash.net>
 L:     netdev@vger.kernel.org
index f5e018de7fa512403fbd62bcf0a82277b9727830..8e1b4ffb5e542411e180401afc36a14af61e744a 100644 (file)
@@ -690,7 +690,7 @@ static struct vpbe_output dm644xevm_vpbe_outputs[] = {
                        .std            = VENC_STD_ALL,
                        .capabilities   = V4L2_OUT_CAP_STD,
                },
-               .subdev_name    = VPBE_VENC_SUBDEV_NAME,
+               .subdev_name    = DM644X_VPBE_VENC_SUBDEV_NAME,
                .default_mode   = "ntsc",
                .num_modes      = ARRAY_SIZE(dm644xevm_enc_std_timing),
                .modes          = dm644xevm_enc_std_timing,
@@ -702,7 +702,7 @@ static struct vpbe_output dm644xevm_vpbe_outputs[] = {
                        .type           = V4L2_OUTPUT_TYPE_ANALOG,
                        .capabilities   = V4L2_OUT_CAP_DV_TIMINGS,
                },
-               .subdev_name    = VPBE_VENC_SUBDEV_NAME,
+               .subdev_name    = DM644X_VPBE_VENC_SUBDEV_NAME,
                .default_mode   = "480p59_94",
                .num_modes      = ARRAY_SIZE(dm644xevm_enc_preset_timing),
                .modes          = dm644xevm_enc_preset_timing,
@@ -713,10 +713,10 @@ static struct vpbe_config dm644xevm_display_cfg = {
        .module_name    = "dm644x-vpbe-display",
        .i2c_adapter_id = 1,
        .osd            = {
-               .module_name    = VPBE_OSD_SUBDEV_NAME,
+               .module_name    = DM644X_VPBE_OSD_SUBDEV_NAME,
        },
        .venc           = {
-               .module_name    = VPBE_VENC_SUBDEV_NAME,
+               .module_name    = DM644X_VPBE_VENC_SUBDEV_NAME,
        },
        .num_outputs    = ARRAY_SIZE(dm644xevm_vpbe_outputs),
        .outputs        = dm644xevm_vpbe_outputs,
index 11c79a3362ef9e3ec1aa7abc67280ddbada9591f..db1dd92e00af44c13f7f55f0ae364f08be1035c4 100644 (file)
@@ -669,19 +669,14 @@ static struct resource dm644x_osd_resources[] = {
        },
 };
 
-static struct osd_platform_data dm644x_osd_data = {
-       .vpbe_type     = VPBE_VERSION_1,
-};
-
 static struct platform_device dm644x_osd_dev = {
-       .name           = VPBE_OSD_SUBDEV_NAME,
+       .name           = DM644X_VPBE_OSD_SUBDEV_NAME,
        .id             = -1,
        .num_resources  = ARRAY_SIZE(dm644x_osd_resources),
        .resource       = dm644x_osd_resources,
        .dev            = {
                .dma_mask               = &dm644x_video_dma_mask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data          = &dm644x_osd_data,
        },
 };
 
@@ -751,12 +746,11 @@ static struct platform_device dm644x_vpbe_display = {
 };
 
 static struct venc_platform_data dm644x_venc_pdata = {
-       .venc_type      = VPBE_VERSION_1,
        .setup_clock    = dm644x_venc_setup_clock,
 };
 
 static struct platform_device dm644x_venc_dev = {
-       .name           = VPBE_VENC_SUBDEV_NAME,
+       .name           = DM644X_VPBE_VENC_SUBDEV_NAME,
        .id             = -1,
        .num_resources  = ARRAY_SIZE(dm644x_venc_resources),
        .resource       = dm644x_venc_resources,
index b3890bd49df6089fa0871f70d7b09abc47375b4c..2652f9155c347a0e9ac2e83f82933c5ddfe40f7b 100644 (file)
@@ -105,7 +105,7 @@ void saa7146_buffer_finish(struct saa7146_dev *dev,
        }
 
        q->curr->vb.state = state;
-       do_gettimeofday(&q->curr->vb.ts);
+       v4l2_get_timestamp(&q->curr->vb.ts);
        wake_up(&q->curr->vb.done);
 
        q->curr = NULL;
index bc5a82082aaae7891d55dd2cd3c6eabff93e9b84..0e3387e0095267b88e1517491be75601bf9f295b 100644 (file)
@@ -212,7 +212,7 @@ static int ix2505v_set_params(struct dvb_frontend *fe)
                lpf = 0xb;
 
        deb_info("Osc=%x b_w=%x lpf=%x\n", local_osc, b_w, lpf);
-       deb_info("Data 0=[%x%x%x%x]\n", data[0], data[1], data[2], data[3]);
+       deb_info("Data 0=[%4phN]\n", data);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
index c625b57b4333e499827ff9e024d98227eda78775..10cfc05791689323b0d4ab5b967eb22ff7e9e1db 100644 (file)
@@ -22,6 +22,8 @@
  *
 */
 
+#define pr_fmt(fmt)    KBUILD_MODNAME ": %s: " fmt, __func__
+
 /*
  * This driver needs external firmware. Please use the command
  * "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
@@ -44,9 +46,7 @@
 
 static int debug;
 #define dprintk(args...) \
-       do { \
-               if (debug) printk(KERN_DEBUG "or51211: " args); \
-       } while (0)
+       do { if (debug) pr_debug(args); } while (0)
 
 static u8 run_buf[] = {0x7f,0x01};
 static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC
@@ -80,8 +80,7 @@ static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
        msg.buf         = (u8 *)buf;
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               printk(KERN_WARNING "or51211: i2c_writebytes error "
-                      "(addr %02x, err == %i)\n", reg, err);
+               pr_warn("error (addr %02x, err == %i)\n", reg, err);
                return -EREMOTEIO;
        }
 
@@ -98,8 +97,7 @@ static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len)
        msg.buf         = buf;
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               printk(KERN_WARNING "or51211: i2c_readbytes error "
-                      "(addr %02x, err == %i)\n", reg, err);
+               pr_warn("error (addr %02x, err == %i)\n", reg, err);
                return -EREMOTEIO;
        }
 
@@ -118,11 +116,11 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
        /* Get eprom data */
        tudata[0] = 17;
        if (i2c_writebytes(state,0x50,tudata,1)) {
-               printk(KERN_WARNING "or51211:load_firmware error eprom addr\n");
+               pr_warn("error eprom addr\n");
                return -1;
        }
        if (i2c_readbytes(state,0x50,&tudata[145],192)) {
-               printk(KERN_WARNING "or51211: load_firmware error eprom\n");
+               pr_warn("error eprom\n");
                return -1;
        }
 
@@ -136,32 +134,32 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
        state->config->reset(fe);
 
        if (i2c_writebytes(state,state->config->demod_address,tudata,585)) {
-               printk(KERN_WARNING "or51211: load_firmware error 1\n");
+               pr_warn("error 1\n");
                return -1;
        }
        msleep(1);
 
        if (i2c_writebytes(state,state->config->demod_address,
                           &fw->data[393],8125)) {
-               printk(KERN_WARNING "or51211: load_firmware error 2\n");
+               pr_warn("error 2\n");
                return -1;
        }
        msleep(1);
 
        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-               printk(KERN_WARNING "or51211: load_firmware error 3\n");
+               pr_warn("error 3\n");
                return -1;
        }
 
        /* Wait at least 5 msec */
        msleep(10);
        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-               printk(KERN_WARNING "or51211: load_firmware error 4\n");
+               pr_warn("error 4\n");
                return -1;
        }
        msleep(10);
 
-       printk("or51211: Done.\n");
+       pr_info("Done.\n");
        return 0;
 };
 
@@ -173,14 +171,14 @@ static int or51211_setmode(struct dvb_frontend* fe, int mode)
        state->config->setmode(fe, mode);
 
        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-               printk(KERN_WARNING "or51211: setmode error 1\n");
+               pr_warn("error 1\n");
                return -1;
        }
 
        /* Wait at least 5 msec */
        msleep(10);
        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-               printk(KERN_WARNING "or51211: setmode error 2\n");
+               pr_warn("error 2\n");
                return -1;
        }
 
@@ -196,7 +194,7 @@ static int or51211_setmode(struct dvb_frontend* fe, int mode)
         *             normal +/-150kHz Carrier acquisition range
         */
        if (i2c_writebytes(state,state->config->demod_address,cmd_buf,3)) {
-               printk(KERN_WARNING "or51211: setmode error 3\n");
+               pr_warn("error 3\n");
                return -1;
        }
 
@@ -206,14 +204,14 @@ static int or51211_setmode(struct dvb_frontend* fe, int mode)
        rec_buf[3] = 0x00;
        msleep(20);
        if (i2c_writebytes(state,state->config->demod_address,rec_buf,3)) {
-               printk(KERN_WARNING "or51211: setmode error 5\n");
+               pr_warn("error 5\n");
        }
        msleep(3);
        if (i2c_readbytes(state,state->config->demod_address,&rec_buf[10],2)) {
-               printk(KERN_WARNING "or51211: setmode error 6");
+               pr_warn("error 6\n");
                return -1;
        }
-       dprintk("setmode rec status %02x %02x\n",rec_buf[10],rec_buf[11]);
+       dprintk("rec status %02x %02x\n", rec_buf[10], rec_buf[11]);
 
        return 0;
 }
@@ -248,15 +246,15 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* Receiver Status */
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
-               printk(KERN_WARNING "or51132: read_status write error\n");
+               pr_warn("write error\n");
                return -1;
        }
        msleep(3);
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-               printk(KERN_WARNING "or51132: read_status read error\n");
+               pr_warn("read error\n");
                return -1;
        }
-       dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]);
+       dprintk("%x %x\n", rec_buf[0], rec_buf[1]);
 
        if (rec_buf[0] &  0x01) { /* Receiver Lock */
                *status |= FE_HAS_SIGNAL;
@@ -306,20 +304,18 @@ static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
        snd_buf[2] = 0x04;
 
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
-               printk(KERN_WARNING "%s: error writing snr reg\n",
-                      __func__);
+               pr_warn("error writing snr reg\n");
                return -1;
        }
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-               printk(KERN_WARNING "%s: read_status read error\n",
-                      __func__);
+               pr_warn("read_status read error\n");
                return -1;
        }
 
        state->snr = calculate_snr(rec_buf[0], 89599047);
        *snr = (state->snr) >> 16;
 
-       dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
+       dprintk("noise = 0x%02x, snr = %d.%02d dB\n", rec_buf[0],
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
@@ -375,25 +371,24 @@ static int or51211_init(struct dvb_frontend* fe)
 
        if (!state->initialized) {
                /* Request the firmware, this will block until it uploads */
-               printk(KERN_INFO "or51211: Waiting for firmware upload "
-                      "(%s)...\n", OR51211_DEFAULT_FIRMWARE);
+               pr_info("Waiting for firmware upload (%s)...\n",
+                       OR51211_DEFAULT_FIRMWARE);
                ret = config->request_firmware(fe, &fw,
                                               OR51211_DEFAULT_FIRMWARE);
-               printk(KERN_INFO "or51211:Got Hotplug firmware\n");
+               pr_info("Got Hotplug firmware\n");
                if (ret) {
-                       printk(KERN_WARNING "or51211: No firmware uploaded "
-                              "(timeout or file not found?)\n");
+                       pr_warn("No firmware uploaded "
+                               "(timeout or file not found?)\n");
                        return ret;
                }
 
                ret = or51211_load_firmware(fe, fw);
                release_firmware(fw);
                if (ret) {
-                       printk(KERN_WARNING "or51211: Writing firmware to "
-                              "device failed!\n");
+                       pr_warn("Writing firmware to device failed!\n");
                        return ret;
                }
-               printk(KERN_INFO "or51211: Firmware upload complete.\n");
+               pr_info("Firmware upload complete.\n");
 
                /* Set operation mode in Receiver 1 register;
                 * type 1:
@@ -406,7 +401,7 @@ static int or51211_init(struct dvb_frontend* fe)
                 */
                if (i2c_writebytes(state,state->config->demod_address,
                                   cmd_buf,3)) {
-                       printk(KERN_WARNING "or51211: Load DVR Error 5\n");
+                       pr_warn("Load DVR Error 5\n");
                        return -1;
                }
 
@@ -419,13 +414,13 @@ static int or51211_init(struct dvb_frontend* fe)
                msleep(30);
                if (i2c_writebytes(state,state->config->demod_address,
                                   rec_buf,3)) {
-                       printk(KERN_WARNING "or51211: Load DVR Error A\n");
+                       pr_warn("Load DVR Error A\n");
                        return -1;
                }
                msleep(3);
                if (i2c_readbytes(state,state->config->demod_address,
                                  &rec_buf[10],2)) {
-                       printk(KERN_WARNING "or51211: Load DVR Error B\n");
+                       pr_warn("Load DVR Error B\n");
                        return -1;
                }
 
@@ -436,13 +431,13 @@ static int or51211_init(struct dvb_frontend* fe)
                msleep(20);
                if (i2c_writebytes(state,state->config->demod_address,
                                   rec_buf,3)) {
-                       printk(KERN_WARNING "or51211: Load DVR Error C\n");
+                       pr_warn("Load DVR Error C\n");
                        return -1;
                }
                msleep(3);
                if (i2c_readbytes(state,state->config->demod_address,
                                  &rec_buf[12],2)) {
-                       printk(KERN_WARNING "or51211: Load DVR Error D\n");
+                       pr_warn("Load DVR Error D\n");
                        return -1;
                }
 
@@ -454,16 +449,14 @@ static int or51211_init(struct dvb_frontend* fe)
                        get_ver_buf[4] = i+1;
                        if (i2c_writebytes(state,state->config->demod_address,
                                           get_ver_buf,5)) {
-                               printk(KERN_WARNING "or51211:Load DVR Error 6"
-                                      " - %d\n",i);
+                               pr_warn("Load DVR Error 6 - %d\n", i);
                                return -1;
                        }
                        msleep(3);
 
                        if (i2c_readbytes(state,state->config->demod_address,
                                          &rec_buf[i*2],2)) {
-                               printk(KERN_WARNING "or51211:Load DVR Error 7"
-                                      " - %d\n",i);
+                               pr_warn("Load DVR Error 7 - %d\n", i);
                                return -1;
                        }
                        /* If we didn't receive the right index, try again */
@@ -471,15 +464,11 @@ static int or51211_init(struct dvb_frontend* fe)
                          i--;
                        }
                }
-               dprintk("read_fwbits %x %x %x %x %x %x %x %x %x %x\n",
-                       rec_buf[0], rec_buf[1], rec_buf[2], rec_buf[3],
-                       rec_buf[4], rec_buf[5], rec_buf[6], rec_buf[7],
-                       rec_buf[8], rec_buf[9]);
+               dprintk("read_fwbits %10ph\n", rec_buf);
 
-               printk(KERN_INFO "or51211: ver TU%02x%02x%02x VSB mode %02x"
-                      " Status %02x\n",
-                      rec_buf[2], rec_buf[4],rec_buf[6],
-                      rec_buf[12],rec_buf[10]);
+               pr_info("ver TU%02x%02x%02x VSB mode %02x Status %02x\n",
+                       rec_buf[2], rec_buf[4], rec_buf[6], rec_buf[12],
+                       rec_buf[10]);
 
                rec_buf[0] = 0x04;
                rec_buf[1] = 0x00;
@@ -488,13 +477,13 @@ static int or51211_init(struct dvb_frontend* fe)
                msleep(20);
                if (i2c_writebytes(state,state->config->demod_address,
                                   rec_buf,3)) {
-                       printk(KERN_WARNING "or51211: Load DVR Error 8\n");
+                       pr_warn("Load DVR Error 8\n");
                        return -1;
                }
                msleep(20);
                if (i2c_readbytes(state,state->config->demod_address,
                                  &rec_buf[8],2)) {
-                       printk(KERN_WARNING "or51211: Load DVR Error 9\n");
+                       pr_warn("Load DVR Error 9\n");
                        return -1;
                }
                state->initialized = 1;
index 16a4bc54dbe79acefc0c63789c05c6f21d0d977b..2521f7e23018f70a33a9ad43e1bb26e79e037ab8 100644 (file)
@@ -30,7 +30,7 @@ static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
        u8 buf[len+1];
        struct i2c_msg msg[1] = {
                {
-                       .addr = priv->cfg.i2c_address,
+                       .addr = priv->cfg.demod_i2c_addr,
                        .flags = 0,
                        .len = sizeof(buf),
                        .buf = buf,
@@ -59,12 +59,12 @@ static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
        u8 buf[len];
        struct i2c_msg msg[2] = {
                {
-                       .addr = priv->cfg.i2c_address,
+                       .addr = priv->cfg.demod_i2c_addr,
                        .flags = 0,
                        .len = 1,
                        .buf = &reg,
                }, {
-                       .addr = priv->cfg.i2c_address,
+                       .addr = priv->cfg.demod_i2c_addr,
                        .flags = I2C_M_RD,
                        .len = sizeof(buf),
                        .buf = buf,
@@ -1064,7 +1064,7 @@ static int tda10071_init(struct dvb_frontend *fe)
                cmd.args[2] = 0x00;
                cmd.args[3] = 0x00;
                cmd.args[4] = 0x00;
-               cmd.args[5] = 0x14;
+               cmd.args[5] = (priv->cfg.tuner_i2c_addr) ? priv->cfg.tuner_i2c_addr : 0x14;
                cmd.args[6] = 0x00;
                cmd.args[7] = 0x03;
                cmd.args[8] = 0x02;
@@ -1202,6 +1202,20 @@ struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
                goto error;
        }
 
+       /* make sure demod i2c address is specified */
+       if (!config->demod_i2c_addr) {
+               dev_dbg(&i2c->dev, "%s: invalid demod i2c address!\n", __func__);
+               ret = -EINVAL;
+               goto error;
+       }
+
+       /* make sure tuner i2c address is specified */
+       if (!config->tuner_i2c_addr) {
+               dev_dbg(&i2c->dev, "%s: invalid tuner i2c address!\n", __func__);
+               ret = -EINVAL;
+               goto error;
+       }
+
        /* setup the priv */
        priv->i2c = i2c;
        memcpy(&priv->cfg, config, sizeof(struct tda10071_config));
index 21163c4b555c9f76b32958d00d1593ba554281f1..bff1c38df8026e98390fb21d74503635008ff807 100644 (file)
@@ -28,7 +28,13 @@ struct tda10071_config {
         * Default: none, must set
         * Values: 0x55,
         */
-       u8 i2c_address;
+       u8 demod_i2c_addr;
+
+       /* Tuner I2C address.
+        * Default: none, must set
+        * Values: 0x14, 0x54, ...
+        */
+       u8 tuner_i2c_addr;
 
        /* Max bytes I2C provider can write at once.
         * Note: Buffer is taken from the stack currently!
index 1af1ee49b5421d07bef42a59fe19fffefb4722b0..46710744173beac68dc7998608876c8801c2e4d6 100644 (file)
@@ -78,7 +78,7 @@ static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
                        return err;
                }
                *bandwidth = t_state.bandwidth;
+               printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
        }
-       printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
        return 0;
 }
index e7c82b297514ce44dae6e7a33ecf5cc556cb09ea..882ddf6f66d31526728b3bd0cdc8ac811b279f49 100644 (file)
@@ -353,7 +353,7 @@ static struct regval_list ov7670_fmt_yuv422[] = {
        { REG_RGB444, 0 },      /* No RGB444 please */
        { REG_COM1, 0 },        /* CCIR601 */
        { REG_COM15, COM15_R00FF },
-       { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */
+       { REG_COM9, 0x48 }, /* 32x gain ceiling; 0x8 is reserved bit */
        { 0x4f, 0x80 },         /* "matrix coefficient 1" */
        { 0x50, 0x80 },         /* "matrix coefficient 2" */
        { 0x51, 0    },         /* vb */
index de6f41f19187dd584be669baadc0398910e71b2b..346458bba2c533c43ccd3cc3337c29ae5ac919ea 100644 (file)
@@ -3835,7 +3835,7 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
 {
        struct timeval ts;
 
-       do_gettimeofday(&ts);
+       v4l2_get_timestamp(&ts);
 
        if (wakeup->top == wakeup->bottom) {
                if (NULL != wakeup->top && curr->top != wakeup->top) {
@@ -3878,7 +3878,7 @@ bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
        if (NULL == wakeup)
                return;
 
-       do_gettimeofday(&ts);
+       v4l2_get_timestamp(&ts);
        wakeup->vb.ts = ts;
        wakeup->vb.field_count = btv->field_count;
        wakeup->vb.state = state;
@@ -3949,7 +3949,7 @@ bttv_irq_wakeup_top(struct bttv *btv)
        btv->curr.top = NULL;
        bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
 
-       do_gettimeofday(&wakeup->vb.ts);
+       v4l2_get_timestamp(&wakeup->vb.ts);
        wakeup->vb.field_count = btv->field_count;
        wakeup->vb.state = VIDEOBUF_DONE;
        wake_up(&wakeup->vb.done);
index eafa1144b17dd34752703746c44ae457884db197..733d6c8ebe4c7aaac75a18e3498067e325de1f47 100644 (file)
@@ -26,6 +26,8 @@ config VIDEO_CX23885
        select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
index 6277e145f0b831809367019d3ae2886d6440dcc1..8d96ae4ebbdd9ca3839ce78d35ee4c7bac212452 100644 (file)
@@ -572,7 +572,11 @@ struct cx23885_board cx23885_boards[] = {
        [CX23885_BOARD_PROF_8000] = {
                .name           = "Prof Revolution DVB-S2 8000",
                .portb          = CX23885_MPEG_DVB,
-       }
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR4400] = {
+               .name           = "Hauppauge WinTV-HVR4400",
+               .portb          = CX23885_MPEG_DVB,
+       },
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -788,6 +792,22 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0x8000,
                .subdevice = 0x3034,
                .card      = CX23885_BOARD_PROF_8000,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0xc108,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR4400,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0xc138,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR4400,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0xc12a,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR4400,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0xc1f8,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR4400,
        },
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1301,6 +1321,16 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                /* enable irq */
                cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR4400:
+               /* GPIO-8 tda10071 demod reset */
+
+               /* Put the parts into reset and back */
+               cx23885_gpio_enable(dev, GPIO_8, 1);
+               cx23885_gpio_clear(dev, GPIO_8);
+               mdelay(100);
+               cx23885_gpio_set(dev, GPIO_8);
+               mdelay(100);
+               break;
        }
 }
 
@@ -1378,6 +1408,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
                break;
        case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
+       case CX23885_BOARD_MYGICA_X8507:
                if (!enable_885_ir)
                        break;
                dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
@@ -1420,6 +1451,7 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
        case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
+       case CX23885_BOARD_MYGICA_X8507:
                cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
                /* sd_ir is a duplicate pointer to the AV Core, just clear it */
                dev->sd_ir = NULL;
@@ -1464,6 +1496,7 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
        case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
+       case CX23885_BOARD_MYGICA_X8507:
                if (dev->sd_ir)
                        cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
                break;
@@ -1509,6 +1542,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1210:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_HAUPPAUGE_HVR4400:
                if (dev->i2c_bus[0].i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0xc0);
                break;
@@ -1581,6 +1615,11 @@ void cx23885_card_setup(struct cx23885_dev *dev)
                ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR4400:
+               ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
index 065ecd54bda3d6127b4ff0ab8e846c41924b3d96..c7572594d43499f2851eb6513f576ccbb19de35f 100644 (file)
@@ -439,7 +439,7 @@ void cx23885_wakeup(struct cx23885_tsport *port,
                if ((s16) (count - buf->count) < 0)
                        break;
 
-               do_gettimeofday(&buf->vb.ts);
+               v4l2_get_timestamp(&buf->vb.ts);
                dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
                        count, buf->count);
                buf->vb.state = VIDEOBUF_DONE;
index 2f5b902e63ae07f71847e89bbbc70a2907ed24fa..a1aae563373928daa406d875c256236edbc4aa95 100644 (file)
@@ -66,6 +66,8 @@
 #include "stv090x.h"
 #include "stb6100.h"
 #include "stb6100_cfg.h"
+#include "tda10071.h"
+#include "a8293.h"
 
 static unsigned int debug;
 
@@ -659,6 +661,20 @@ static struct mt2063_config terratec_mt2063_config[] = {
        },
 };
 
+static const struct tda10071_config hauppauge_tda10071_config = {
+       .demod_i2c_addr = 0x05,
+       .tuner_i2c_addr = 0x54,
+       .i2c_wr_max = 64,
+       .ts_mode = TDA10071_TS_SERIAL,
+       .spec_inv = 0,
+       .xtal = 40444000, /* 40.444 MHz */
+       .pll_multiplier = 20,
+};
+
+static const struct a8293_config hauppauge_a8293_config = {
+       .i2c_addr = 0x0b,
+};
+
 static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
 {
        struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -1242,6 +1258,17 @@ static int dvb_register(struct cx23885_tsport *port)
                        fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
                }
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR4400:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(tda10071_attach,
+                                               &hauppauge_tda10071_config,
+                                               &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(a8293_attach, fe0->dvb.frontend,
+                                  &i2c_bus->i2c_adap,
+                                  &hauppauge_a8293_config);
+               }
+               break;
        default:
                printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
                        " isn't supported yet\n",
index 4f1055a194b51d9446747d52361f7334eef8a51c..7875dfbe09ffae666e8365e877022af4d16a7be2 100644 (file)
@@ -89,6 +89,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
        case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
+       case CX23885_BOARD_MYGICA_X8507:
                /*
                 * The only boards we handle right now.  However other boards
                 * using the CX2388x integrated IR controller should be similar
@@ -140,6 +141,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
+       case CX23885_BOARD_MYGICA_X8507:
                /*
                 * The IR controller on this board only returns pulse widths.
                 * Any other mode setting will fail to set up the device.
@@ -289,6 +291,13 @@ int cx23885_input_init(struct cx23885_dev *dev)
                /* A guess at the remote */
                rc_map = RC_MAP_TEVII_NEC;
                break;
+       case CX23885_BOARD_MYGICA_X8507:
+               /* Integrated CX23885 IR controller */
+               driver_type = RC_DRIVER_IR_RAW;
+               allowed_protos = RC_BIT_ALL;
+               /* A guess at the remote */
+               rc_map = RC_MAP_TOTAL_MEDIA_IN_HAND_02;
+               break;
        default:
                return -ENODEV;
        }
index 1a21926ca412cbdab3cdb00841e40e930818f470..83975313e0f2fb85e12ab1e6de70b89984e83993 100644 (file)
@@ -300,7 +300,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
                if ((s16) (count - buf->count) < 0)
                        break;
 
-               do_gettimeofday(&buf->vb.ts);
+               v4l2_get_timestamp(&buf->vb.ts);
                dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
                        count, buf->count);
                buf->vb.state = VIDEOBUF_DONE;
index 67f40d31450be7e81d79fd24526e5436d7bb336a..61889b25a2afc761e2280a4d1788088065a459a0 100644 (file)
@@ -91,6 +91,7 @@
 #define CX23885_BOARD_TEVII_S471               35
 #define CX23885_BOARD_HAUPPAUGE_HVR1255_22111  36
 #define CX23885_BOARD_PROF_8000                37
+#define CX23885_BOARD_HAUPPAUGE_HVR4400        38
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
index 53b16dd7032054a0afce16de3037350e012214c6..d4de021dc844e88776f67e7b08018cf9ab11b394 100644 (file)
@@ -130,7 +130,7 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
                if ((s16) (count - buf->count) < 0)
                        break;
 
-               do_gettimeofday(&buf->vb.ts);
+               v4l2_get_timestamp(&buf->vb.ts);
                buf->vb.state = VIDEOBUF_DONE;
                list_del(&buf->vb.queue);
                wake_up(&buf->vb.done);
index 19a58754c6e14ee3d91152738464382edf16ab30..39f095c37ffd4462faa98b28c32efde6c112b254 100644 (file)
@@ -549,7 +549,7 @@ void cx88_wakeup(struct cx88_core *core,
                 * up to 32767 buffers in flight... */
                if ((s16) (count - buf->count) < 0)
                        break;
-               do_gettimeofday(&buf->vb.ts);
+               v4l2_get_timestamp(&buf->vb.ts);
                dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
                        count, buf->count);
                buf->vb.state = VIDEOBUF_DONE;
index 74e9a503236432b8c606ebfed56e87bca1fca10d..5d0a5df610782ee52b7f21246f79d9248a683b06 100644 (file)
@@ -304,7 +304,7 @@ static void request_modules(struct ivtv *dev)
 
 static void flush_request_modules(struct ivtv *dev)
 {
-       flush_work_sync(&dev->request_module_wk);
+       flush_work(&dev->request_module_wk);
 }
 #else
 #define request_modules(dev)
index ae7d32027bf726e0e73499880a61a07187fa6744..ac7ab6edb06d078f7aca6abbfdfc8230f593d711 100644 (file)
@@ -811,7 +811,7 @@ again:
                                      mchip_hsize() * mchip_vsize() * 2);
                meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2;
                meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
-               do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
+               v4l2_get_timestamp(&meye.grab_buffer[reqnr].timestamp);
                meye.grab_buffer[reqnr].sequence = sequence++;
                kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
                                sizeof(int), &meye.doneq_lock);
@@ -832,7 +832,7 @@ again:
                       size);
                meye.grab_buffer[reqnr].size = size;
                meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
-               do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
+               v4l2_get_timestamp(&meye.grab_buffer[reqnr].timestamp);
                meye.grab_buffer[reqnr].sequence = sequence++;
                kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
                                sizeof(int), &meye.doneq_lock);
@@ -1426,7 +1426,7 @@ static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
                return -EINVAL;
 
        buf->bytesused = meye.grab_buffer[index].size;
-       buf->flags = V4L2_BUF_FLAG_MAPPED;
+       buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
        if (meye.grab_buffer[index].state == MEYE_BUF_USING)
                buf->flags |= V4L2_BUF_FLAG_QUEUED;
@@ -1499,7 +1499,7 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 
        buf->index = reqnr;
        buf->bytesused = meye.grab_buffer[reqnr].size;
-       buf->flags = V4L2_BUF_FLAG_MAPPED;
+       buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        buf->field = V4L2_FIELD_NONE;
        buf->timestamp = meye.grab_buffer[reqnr].timestamp;
        buf->sequence = meye.grab_buffer[reqnr].sequence;
index 8976d0e65813d26d7c2761d7172fd7549899d1d4..e1aeb51e25ba8a112f0bb233e929cf377c2ab4aa 100644 (file)
@@ -308,7 +308,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev,
 
        /* finish current buffer */
        q->curr->vb.state = state;
-       do_gettimeofday(&q->curr->vb.ts);
+       v4l2_get_timestamp(&q->curr->vb.ts);
        wake_up(&q->curr->vb.done);
        q->curr = NULL;
 }
index b209de40a4f8d69373eb8600f140c613a48310b2..27915e501db9d3bbcdb3944a4bf8237ef9254ba0 100644 (file)
@@ -607,6 +607,9 @@ static int configure_tda827x_fe(struct saa7134_dev *dev,
        /* Get the first frontend */
        fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
 
+       if (!fe0)
+               return -EINVAL;
+
        fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
        if (fe0->dvb.frontend) {
                if (cdec_conf->i2c_gate)
index 4c10205264d4d7c0e2ba25ae48e999bb1aa593a7..ed1337a89a268df51462753ad493bc2b0089272c 100644 (file)
@@ -1088,7 +1088,7 @@ static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip)
 
        REG_WRITE(vip, DVP_CTL, REG_READ(vip, DVP_CTL) & ~DVP_CTL_ENA);
        if (vip->active) {
-               do_gettimeofday(&vip->active->ts);
+               v4l2_get_timestamp(&vip->active->ts);
                vip->active->field_count++;
                vip->active->state = VIDEOBUF_DONE;
                wake_up(&vip->active->done);
index a4cd504b8eeed5001648fb651b3c43f45d1a099a..519164c572c83161ada2bef277ebe5d08ab1d535 100644 (file)
@@ -1169,7 +1169,7 @@ zoran_reap_stat_com (struct zoran *zr)
                }
                frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
                buffer = &zr->jpg_buffers.buffer[frame];
-               do_gettimeofday(&buffer->bs.timestamp);
+               v4l2_get_timestamp(&buffer->bs.timestamp);
 
                if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
                        buffer->bs.length = (stat_com & 0x7fffff) >> 1;
@@ -1407,7 +1407,7 @@ zoran_irq (int             irq,
 
                                                zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE;
                                                zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.seq = zr->v4l_grab_seq;
-                                               do_gettimeofday(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp);
+                                               v4l2_get_timestamp(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp);
                                                zr->v4l_grab_frame = NO_GRAB_ACTIVE;
                                                zr->v4l_pend_tail++;
                                        }
index 53f12c7466b0b971218c2c1c6d769fa0d3f32461..33521a4f23a7186653b20a9e2c13a31bbdb0ada2 100644 (file)
@@ -1334,7 +1334,7 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh,
        struct zoran *zr = fh->zr;
        unsigned long flags;
 
-       buf->flags = V4L2_BUF_FLAG_MAPPED;
+       buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
        switch (fh->map_mode) {
        case ZORAN_MAP_MODE_RAW:
index 3dcfea612c42975615e7d95f5f613918d8d547d1..c071b079de23581ce9e3d973223e564d24b93a74 100644 (file)
@@ -202,6 +202,15 @@ config VIDEO_SAMSUNG_EXYNOS_GSC
        help
          This is a v4l2 driver for Samsung EXYNOS5 SoC G-Scaler.
 
+config VIDEO_SH_VEU
+       tristate "SuperH VEU mem2mem video processing driver"
+       depends on VIDEO_DEV && VIDEO_V4L2
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       help
+           Support for the Video Engine Unit (VEU) on SuperH and
+           SH-Mobile SoCs.
+
 endif # V4L_MEM2MEM_DRIVERS
 
 menuconfig V4L_TEST_DRIVERS
index 4817d280217162ec01b545bcd0164daa1db66b0e..42089ba3600fca76f2ab1a8c5abb3c9ebb9e5b79 100644 (file)
@@ -25,6 +25,8 @@ obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
 obj-$(CONFIG_VIDEO_MX2_EMMAPRP)                += mx2_emmaprp.o
 obj-$(CONFIG_VIDEO_CODA)               += coda.o
 
+obj-$(CONFIG_VIDEO_SH_VEU)             += sh_veu.o
+
 obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)        += m2m-deinterlace.o
 
 obj-$(CONFIG_VIDEO_S3C_CAMIF)          += s3c-camif/
index ecd5323768b76aa5a6224a97db010266241e93d7..519990e1712288b0d4e9194c9f076761f9bb26a7 100644 (file)
@@ -2,9 +2,13 @@ config VIDEO_BLACKFIN_CAPTURE
        tristate "Blackfin Video Capture Driver"
        depends on VIDEO_V4L2 && BLACKFIN && I2C
        select VIDEOBUF2_DMA_CONTIG
+       select VIDEO_BLACKFIN_PPI
        help
          V4L2 bridge driver for Blackfin video capture device.
          Choose PPI or EPPI as its interface.
 
          To compile this driver as a module, choose M here: the
-         module will be called bfin_video_capture.
+         module will be called bfin_capture.
+
+config VIDEO_BLACKFIN_PPI
+       tristate
index aa3a0a21638706f6151f612823ada4a2a165581f..30421bc2308074d70e2c4ef821c7d680298f3bcd 100644 (file)
@@ -1,2 +1,2 @@
-bfin_video_capture-objs := bfin_capture.o ppi.o
-obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o
+obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_capture.o
+obj-$(CONFIG_VIDEO_BLACKFIN_PPI)     += ppi.o
index ec476ef5b709bbe8c56e354e6fecb5d3c70902d5..aa9f846a667e06061a8b0fe24d3f5d8b434e48a7 100644 (file)
@@ -52,6 +52,7 @@ struct bcap_format {
        u32 pixelformat;
        enum v4l2_mbus_pixelcode mbus_code;
        int bpp; /* bits per pixel */
+       int dlen; /* data length for ppi in bits */
 };
 
 struct bcap_buffer {
@@ -76,10 +77,14 @@ struct bcap_device {
        unsigned int cur_input;
        /* current selected standard */
        v4l2_std_id std;
+       /* current selected dv_timings */
+       struct v4l2_dv_timings dv_timings;
        /* used to store pixel format */
        struct v4l2_pix_format fmt;
        /* bits per pixel*/
        int bpp;
+       /* data length for ppi in bits */
+       int dlen;
        /* used to store sensor supported format */
        struct bcap_format *sensor_formats;
        /* number of sensor formats array */
@@ -116,24 +121,35 @@ static const struct bcap_format bcap_formats[] = {
                .pixelformat = V4L2_PIX_FMT_UYVY,
                .mbus_code   = V4L2_MBUS_FMT_UYVY8_2X8,
                .bpp         = 16,
+               .dlen        = 8,
        },
        {
                .desc        = "YCbCr 4:2:2 Interleaved YUYV",
                .pixelformat = V4L2_PIX_FMT_YUYV,
                .mbus_code   = V4L2_MBUS_FMT_YUYV8_2X8,
                .bpp         = 16,
+               .dlen        = 8,
+       },
+       {
+               .desc        = "YCbCr 4:2:2 Interleaved UYVY",
+               .pixelformat = V4L2_PIX_FMT_UYVY,
+               .mbus_code   = V4L2_MBUS_FMT_UYVY8_1X16,
+               .bpp         = 16,
+               .dlen        = 16,
        },
        {
                .desc        = "RGB 565",
                .pixelformat = V4L2_PIX_FMT_RGB565,
                .mbus_code   = V4L2_MBUS_FMT_RGB565_2X8_LE,
                .bpp         = 16,
+               .dlen        = 8,
        },
        {
                .desc        = "RGB 444",
                .pixelformat = V4L2_PIX_FMT_RGB444,
                .mbus_code   = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
                .bpp         = 16,
+               .dlen        = 8,
        },
 
 };
@@ -366,9 +382,39 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
        params.width = bcap_dev->fmt.width;
        params.height = bcap_dev->fmt.height;
        params.bpp = bcap_dev->bpp;
+       params.dlen = bcap_dev->dlen;
        params.ppi_control = bcap_dev->cfg->ppi_control;
        params.int_mask = bcap_dev->cfg->int_mask;
-       params.blank_clocks = bcap_dev->cfg->blank_clocks;
+       if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities
+                       & V4L2_IN_CAP_CUSTOM_TIMINGS) {
+               struct v4l2_bt_timings *bt = &bcap_dev->dv_timings.bt;
+
+               params.hdelay = bt->hsync + bt->hbackporch;
+               params.vdelay = bt->vsync + bt->vbackporch;
+               params.line = bt->hfrontporch + bt->hsync
+                               + bt->hbackporch + bt->width;
+               params.frame = bt->vfrontporch + bt->vsync
+                               + bt->vbackporch + bt->height;
+               if (bt->interlaced)
+                       params.frame += bt->il_vfrontporch + bt->il_vsync
+                                       + bt->il_vbackporch;
+       } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities
+                       & V4L2_IN_CAP_STD) {
+               params.hdelay = 0;
+               params.vdelay = 0;
+               if (bcap_dev->std & V4L2_STD_525_60) {
+                       params.line = 858;
+                       params.frame = 525;
+               } else {
+                       params.line = 864;
+                       params.frame = 625;
+               }
+       } else {
+               params.hdelay = 0;
+               params.vdelay = 0;
+               params.line = params.width + bcap_dev->cfg->blank_pixels;
+               params.frame = params.height;
+       }
        ret = ppi->ops->set_params(ppi, &params);
        if (ret < 0) {
                v4l2_err(&bcap_dev->v4l2_dev,
@@ -484,15 +530,13 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
 {
        struct ppi_if *ppi = dev_id;
        struct bcap_device *bcap_dev = ppi->priv;
-       struct timeval timevalue;
        struct vb2_buffer *vb = &bcap_dev->cur_frm->vb;
        dma_addr_t addr;
 
        spin_lock(&bcap_dev->lock);
 
        if (bcap_dev->cur_frm != bcap_dev->next_frm) {
-               do_gettimeofday(&timevalue);
-               vb->v4l2_buf.timestamp = timevalue;
+               v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
                vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
                bcap_dev->cur_frm = bcap_dev->next_frm;
        }
@@ -602,6 +646,37 @@ static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std)
        return 0;
 }
 
+static int bcap_g_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *timings)
+{
+       struct bcap_device *bcap_dev = video_drvdata(file);
+       int ret;
+
+       ret = v4l2_subdev_call(bcap_dev->sd, video,
+                               g_dv_timings, timings);
+       if (ret < 0)
+               return ret;
+
+       bcap_dev->dv_timings = *timings;
+       return 0;
+}
+
+static int bcap_s_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *timings)
+{
+       struct bcap_device *bcap_dev = video_drvdata(file);
+       int ret;
+       if (vb2_is_busy(&bcap_dev->buffer_queue))
+               return -EBUSY;
+
+       ret = v4l2_subdev_call(bcap_dev->sd, video, s_dv_timings, timings);
+       if (ret < 0)
+               return ret;
+
+       bcap_dev->dv_timings = *timings;
+       return 0;
+}
+
 static int bcap_enum_input(struct file *file, void *priv,
                                struct v4l2_input *input)
 {
@@ -650,13 +725,15 @@ static int bcap_s_input(struct file *file, void *priv, unsigned int index)
                return ret;
        }
        bcap_dev->cur_input = index;
+       /* if this route has specific config, update ppi control */
+       if (route->ppi_control)
+               config->ppi_control = route->ppi_control;
        return 0;
 }
 
 static int bcap_try_format(struct bcap_device *bcap,
                                struct v4l2_pix_format *pixfmt,
-                               enum v4l2_mbus_pixelcode *mbus_code,
-                               int *bpp)
+                               struct bcap_format *bcap_fmt)
 {
        struct bcap_format *sf = bcap->sensor_formats;
        struct bcap_format *fmt = NULL;
@@ -671,16 +748,20 @@ static int bcap_try_format(struct bcap_device *bcap,
        if (i == bcap->num_sensor_formats)
                fmt = &sf[0];
 
-       if (mbus_code)
-               *mbus_code = fmt->mbus_code;
-       if (bpp)
-               *bpp = fmt->bpp;
        v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code);
        ret = v4l2_subdev_call(bcap->sd, video,
                                try_mbus_fmt, &mbus_fmt);
        if (ret < 0)
                return ret;
        v4l2_fill_pix_format(pixfmt, &mbus_fmt);
+       if (bcap_fmt) {
+               for (i = 0; i < bcap->num_sensor_formats; i++) {
+                       fmt = &sf[i];
+                       if (mbus_fmt.code == fmt->mbus_code)
+                               break;
+               }
+               *bcap_fmt = *fmt;
+       }
        pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8;
        pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
        return 0;
@@ -709,7 +790,7 @@ static int bcap_try_fmt_vid_cap(struct file *file, void *priv,
        struct bcap_device *bcap_dev = video_drvdata(file);
        struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
 
-       return bcap_try_format(bcap_dev, pixfmt, NULL, NULL);
+       return bcap_try_format(bcap_dev, pixfmt, NULL);
 }
 
 static int bcap_g_fmt_vid_cap(struct file *file, void *priv,
@@ -726,24 +807,25 @@ static int bcap_s_fmt_vid_cap(struct file *file, void *priv,
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
        struct v4l2_mbus_framefmt mbus_fmt;
-       enum v4l2_mbus_pixelcode mbus_code;
+       struct bcap_format bcap_fmt;
        struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
-       int ret, bpp;
+       int ret;
 
        if (vb2_is_busy(&bcap_dev->buffer_queue))
                return -EBUSY;
 
        /* see if format works */
-       ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp);
+       ret = bcap_try_format(bcap_dev, pixfmt, &bcap_fmt);
        if (ret < 0)
                return ret;
 
-       v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code);
+       v4l2_fill_mbus_format(&mbus_fmt, pixfmt, bcap_fmt.mbus_code);
        ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt);
        if (ret < 0)
                return ret;
        bcap_dev->fmt = *pixfmt;
-       bcap_dev->bpp = bpp;
+       bcap_dev->bpp = bcap_fmt.bpp;
+       bcap_dev->dlen = bcap_fmt.dlen;
        return 0;
 }
 
@@ -834,6 +916,8 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = {
        .vidioc_querystd         = bcap_querystd,
        .vidioc_s_std            = bcap_s_std,
        .vidioc_g_std            = bcap_g_std,
+       .vidioc_s_dv_timings     = bcap_s_dv_timings,
+       .vidioc_g_dv_timings     = bcap_g_dv_timings,
        .vidioc_reqbufs          = bcap_reqbufs,
        .vidioc_querybuf         = bcap_querybuf,
        .vidioc_qbuf             = bcap_qbuf,
@@ -869,6 +953,7 @@ static int __devinit bcap_probe(struct platform_device *pdev)
        struct i2c_adapter *i2c_adap;
        struct bfin_capture_config *config;
        struct vb2_queue *q;
+       struct bcap_route *route;
        int ret;
 
        config = pdev->dev.platform_data;
@@ -978,6 +1063,12 @@ static int __devinit bcap_probe(struct platform_device *pdev)
                                                 NULL);
        if (bcap_dev->sd) {
                int i;
+               if (!config->num_inputs) {
+                       v4l2_err(&bcap_dev->v4l2_dev,
+                                       "Unable to work without input\n");
+                       goto err_unreg_vdev;
+               }
+
                /* update tvnorms from the sub devices */
                for (i = 0; i < config->num_inputs; i++)
                        vfd->tvnorms |= config->inputs[i].std;
@@ -989,8 +1080,24 @@ static int __devinit bcap_probe(struct platform_device *pdev)
 
        v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n");
 
+       /*
+        * explicitly set input, otherwise some boards
+        * may not work at the state as we expected
+        */
+       route = &config->routes[0];
+       ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing,
+                               route->input, route->output, 0);
+       if ((ret < 0) && (ret != -ENOIOCTLCMD)) {
+               v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n");
+               goto err_unreg_vdev;
+       }
+       bcap_dev->cur_input = 0;
+       /* if this route has specific config, update ppi control */
+       if (route->ppi_control)
+               config->ppi_control = route->ppi_control;
+
        /* now we can probe the default state */
-       if (vfd->tvnorms) {
+       if (config->inputs[0].capabilities & V4L2_IN_CAP_STD) {
                v4l2_std_id std;
                ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std);
                if (ret) {
@@ -1000,6 +1107,17 @@ static int __devinit bcap_probe(struct platform_device *pdev)
                }
                bcap_dev->std = std;
        }
+       if (config->inputs[0].capabilities & V4L2_IN_CAP_CUSTOM_TIMINGS) {
+               struct v4l2_dv_timings dv_timings;
+               ret = v4l2_subdev_call(bcap_dev->sd, video,
+                               g_dv_timings, &dv_timings);
+               if (ret) {
+                       v4l2_err(&bcap_dev->v4l2_dev,
+                                       "Unable to get dv timings\n");
+                       goto err_unreg_vdev;
+               }
+               bcap_dev->dv_timings = dv_timings;
+       }
        ret = bcap_init_sensor_formats(bcap_dev);
        if (ret) {
                v4l2_err(&bcap_dev->v4l2_dev,
index d29592186b020427b3464f4c820de4df344fd6b4..1e24584605f28a63aa1231b0085bab6779a7a0b0 100644 (file)
@@ -17,6 +17,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #include <asm/bfin_ppi.h>
@@ -67,6 +68,13 @@ static irqreturn_t ppi_irq_err(int irq, void *dev_id)
                bfin_write16(&reg->status, 0xffff);
                break;
        }
+       case PPI_TYPE_EPPI3:
+       {
+               struct bfin_eppi3_regs *reg = info->base;
+
+               bfin_write32(&reg->stat, 0xc0ff);
+               break;
+       }
        default:
                break;
        }
@@ -128,6 +136,12 @@ static int ppi_start(struct ppi_if *ppi)
                bfin_write32(&reg->control, ppi->ppi_control);
                break;
        }
+       case PPI_TYPE_EPPI3:
+       {
+               struct bfin_eppi3_regs *reg = info->base;
+               bfin_write32(&reg->ctl, ppi->ppi_control);
+               break;
+       }
        default:
                return -EINVAL;
        }
@@ -155,6 +169,12 @@ static int ppi_stop(struct ppi_if *ppi)
                bfin_write32(&reg->control, ppi->ppi_control);
                break;
        }
+       case PPI_TYPE_EPPI3:
+       {
+               struct bfin_eppi3_regs *reg = info->base;
+               bfin_write32(&reg->ctl, ppi->ppi_control);
+               break;
+       }
        default:
                return -EINVAL;
        }
@@ -171,17 +191,23 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params)
 {
        const struct ppi_info *info = ppi->info;
        int dma32 = 0;
-       int dma_config, bytes_per_line, lines_per_frame;
+       int dma_config, bytes_per_line;
+       int hcount, hdelay, samples_per_line;
 
        bytes_per_line = params->width * params->bpp / 8;
-       lines_per_frame = params->height;
+       /* convert parameters unit from pixels to samples */
+       hcount = params->width * params->bpp / params->dlen;
+       hdelay = params->hdelay * params->bpp / params->dlen;
+       samples_per_line = params->line * params->bpp / params->dlen;
        if (params->int_mask == 0xFFFFFFFF)
                ppi->err_int = false;
        else
                ppi->err_int = true;
 
-       dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN);
+       dma_config = (DMA_FLOW_STOP | RESTART | DMA2D | DI_EN_Y);
        ppi->ppi_control = params->ppi_control & ~PORT_EN;
+       if (!(ppi->ppi_control & PORT_DIR))
+               dma_config |= WNR;
        switch (info->type) {
        case PPI_TYPE_PPI:
        {
@@ -191,8 +217,8 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params)
                        dma32 = 1;
 
                bfin_write16(&reg->control, ppi->ppi_control);
-               bfin_write16(&reg->count, bytes_per_line - 1);
-               bfin_write16(&reg->frame, lines_per_frame);
+               bfin_write16(&reg->count, samples_per_line - 1);
+               bfin_write16(&reg->frame, params->frame);
                break;
        }
        case PPI_TYPE_EPPI:
@@ -204,12 +230,31 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params)
                        dma32 = 1;
 
                bfin_write32(&reg->control, ppi->ppi_control);
-               bfin_write16(&reg->line, bytes_per_line + params->blank_clocks);
-               bfin_write16(&reg->frame, lines_per_frame);
-               bfin_write16(&reg->hdelay, 0);
-               bfin_write16(&reg->vdelay, 0);
-               bfin_write16(&reg->hcount, bytes_per_line);
-               bfin_write16(&reg->vcount, lines_per_frame);
+               bfin_write16(&reg->line, samples_per_line);
+               bfin_write16(&reg->frame, params->frame);
+               bfin_write16(&reg->hdelay, hdelay);
+               bfin_write16(&reg->vdelay, params->vdelay);
+               bfin_write16(&reg->hcount, hcount);
+               bfin_write16(&reg->vcount, params->height);
+               break;
+       }
+       case PPI_TYPE_EPPI3:
+       {
+               struct bfin_eppi3_regs *reg = info->base;
+
+               if ((params->ppi_control & PACK_EN)
+                       || (params->ppi_control & 0x70000) > DLEN_16)
+                       dma32 = 1;
+
+               bfin_write32(&reg->ctl, ppi->ppi_control);
+               bfin_write32(&reg->line, samples_per_line);
+               bfin_write32(&reg->frame, params->frame);
+               bfin_write32(&reg->hdly, hdelay);
+               bfin_write32(&reg->vdly, params->vdelay);
+               bfin_write32(&reg->hcnt, hcount);
+               bfin_write32(&reg->vcnt, params->height);
+               if (params->int_mask)
+                       bfin_write32(&reg->imsk, params->int_mask & 0xFF);
                break;
        }
        default:
@@ -217,17 +262,17 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params)
        }
 
        if (dma32) {
-               dma_config |= WDSIZE_32;
+               dma_config |= WDSIZE_32 | PSIZE_32;
                set_dma_x_count(info->dma_ch, bytes_per_line >> 2);
                set_dma_x_modify(info->dma_ch, 4);
                set_dma_y_modify(info->dma_ch, 4);
        } else {
-               dma_config |= WDSIZE_16;
+               dma_config |= WDSIZE_16 | PSIZE_16;
                set_dma_x_count(info->dma_ch, bytes_per_line >> 1);
                set_dma_x_modify(info->dma_ch, 2);
                set_dma_y_modify(info->dma_ch, 2);
        }
-       set_dma_y_count(info->dma_ch, lines_per_frame);
+       set_dma_y_count(info->dma_ch, params->height);
        set_dma_config(info->dma_ch, dma_config);
 
        SSYNC();
@@ -263,9 +308,15 @@ struct ppi_if *ppi_create_instance(const struct ppi_info *info)
        pr_info("ppi probe success\n");
        return ppi;
 }
+EXPORT_SYMBOL(ppi_create_instance);
 
 void ppi_delete_instance(struct ppi_if *ppi)
 {
        peripheral_free_list(ppi->info->pin_req);
        kfree(ppi);
 }
+EXPORT_SYMBOL(ppi_delete_instance);
+
+MODULE_DESCRIPTION("Analog Devices PPI driver");
+MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
+MODULE_LICENSE("GPL v2");
index 7b8b547f2d51867115f9bf5a510495e6c35baebb..2721f839852ff4676b1198e38fa9dda3ffa755f6 100644 (file)
@@ -178,6 +178,10 @@ struct coda_ctx {
        int                             idx;
 };
 
+static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 };
+static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
+
 static inline void coda_write(struct coda_dev *dev, u32 data, u32 reg)
 {
        v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
@@ -944,6 +948,24 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d
        return 0;
 }
 
+static int coda_h264_padding(int size, char *p)
+{
+       int nal_size;
+       int diff;
+
+       diff = size - (size & ~0x7);
+       if (diff == 0)
+               return 0;
+
+       nal_size = coda_filler_size[diff];
+       memcpy(p, coda_filler_nal, nal_size);
+
+       /* Add rbsp stop bit and trailing at the end */
+       *(p + nal_size - 1) = 0x80;
+
+       return nal_size;
+}
+
 static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 {
        struct coda_ctx *ctx = vb2_get_drv_priv(q);
@@ -1171,7 +1193,15 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
                                coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
                memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0),
                       ctx->vpu_header_size[1]);
-               ctx->vpu_header_size[2] = 0;
+               /*
+                * Length of H.264 headers is variable and thus it might not be
+                * aligned for the coda to append the encoded frame. In that is
+                * the case a filler NAL must be added to header 2.
+                */
+               ctx->vpu_header_size[2] = coda_h264_padding(
+                                       (ctx->vpu_header_size[0] +
+                                        ctx->vpu_header_size[1]),
+                                        ctx->vpu_header[2]);
                break;
        case V4L2_PIX_FMT_MPEG4:
                /*
index 3c56037c82fce5e711469b585dbd157da79b01c2..ccfde4eb626acd397ddff2fb4a43d738abbddec8 100644 (file)
@@ -97,25 +97,15 @@ config VIDEO_ISIF
           To compile this driver as a module, choose M here: the
           module will be called vpfe.
 
-config VIDEO_DM644X_VPBE
-       tristate "DM644X VPBE HW module"
-       depends on ARCH_DAVINCI_DM644x
+config VIDEO_DAVINCI_VPBE_DISPLAY
+       tristate "DM644X/DM365/DM355 VPBE HW module"
+       depends on ARCH_DAVINCI_DM644x || ARCH_DAVINCI_DM355 || ARCH_DAVINCI_DM365
        select VIDEO_VPSS_SYSTEM
        select VIDEOBUF2_DMA_CONTIG
        help
-           Enables VPBE modules used for display on a DM644x
-           SoC.
+           Enables Davinci VPBE module used for display devices.
+           This module is common for following DM644x/DM365/DM355
+           based display devices.
 
            To compile this driver as a module, choose M here: the
            module will be called vpbe.
-
-
-config VIDEO_VPBE_DISPLAY
-       tristate "VPBE V4L2 Display driver"
-       depends on ARCH_DAVINCI_DM644x
-       select VIDEO_DM644X_VPBE
-       help
-           Enables VPBE V4L2 Display driver on a DM644x device
-
-           To compile this driver as a module, choose M here: the
-           module will be called vpbe_display.
index 74ed92d09257c6ca828467202c817af627c64e74..f40f5219ca50067d5a4729fb336d7e65760125f2 100644 (file)
@@ -16,5 +16,5 @@ obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o
 obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o
 obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o
 obj-$(CONFIG_VIDEO_ISIF) += isif.o
-obj-$(CONFIG_VIDEO_DM644X_VPBE) += vpbe.o vpbe_osd.o vpbe_venc.o
-obj-$(CONFIG_VIDEO_VPBE_DISPLAY) += vpbe_display.o
+obj-$(CONFIG_VIDEO_DAVINCI_VPBE_DISPLAY) += vpbe.o vpbe_osd.o \
+       vpbe_venc.o vpbe_display.o
index 7f5cf9b347b2c40e22f5056a0fe062a31cfabf86..fe2b9ce0bce876c57f4abf42b98c6fde9118bcde 100644 (file)
@@ -558,9 +558,9 @@ static int platform_device_get(struct device *dev, void *data)
        struct platform_device *pdev = to_platform_device(dev);
        struct vpbe_device *vpbe_dev = data;
 
-       if (strcmp("vpbe-osd", pdev->name) == 0)
+       if (strstr(pdev->name, "vpbe-osd") != NULL)
                vpbe_dev->osd_device = platform_get_drvdata(pdev);
-       if (strcmp("vpbe-venc", pdev->name) == 0)
+       if (strstr(pdev->name, "vpbe-venc") != NULL)
                vpbe_dev->venc_device = dev_get_platdata(&pdev->dev);
 
        return 0;
@@ -584,7 +584,6 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
        struct v4l2_subdev **enc_subdev;
        struct osd_state *osd_device;
        struct i2c_adapter *i2c_adap;
-       int output_index;
        int num_encoders;
        int ret = 0;
        int err;
@@ -731,7 +730,6 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
        /* set the current encoder and output to that of venc by default */
        vpbe_dev->current_sd_index = 0;
        vpbe_dev->current_out_index = 0;
-       output_index = 0;
 
        mutex_unlock(&vpbe_dev->lock);
 
index 2bfde7958fefb700d948d9635a32ae9c4888ab88..d078738b35d63460b594e5d16b729eb3842ae276 100644 (file)
@@ -791,7 +791,6 @@ static int vpbe_display_g_crop(struct file *file, void *priv,
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        struct osd_state *osd_device = fh->disp_dev->osd_device;
        struct v4l2_rect *rect = &crop->c;
-       int ret;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
                        "VIDIOC_G_CROP, layer id = %d\n",
@@ -799,7 +798,7 @@ static int vpbe_display_g_crop(struct file *file, void *priv,
 
        if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buf type\n");
-               ret = -EINVAL;
+               return -EINVAL;
        }
        osd_device->ops.get_layer_config(osd_device,
                                layer->layer_info.id, cfg);
@@ -1393,9 +1392,9 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
        }
        /* Initialize videobuf queue as per the buffer type */
        layer->alloc_ctx = vb2_dma_contig_init_ctx(vpbe_dev->pdev);
-       if (!layer->alloc_ctx) {
+       if (IS_ERR(layer->alloc_ctx)) {
                v4l2_err(&vpbe_dev->v4l2_dev, "Failed to get the context\n");
-               return -EINVAL;
+               return PTR_ERR(layer->alloc_ctx);
        }
        q = &layer->buffer_queue;
        memset(q, 0, sizeof(*q));
@@ -1656,7 +1655,7 @@ static int vpbe_device_get(struct device *dev, void *data)
        if (strcmp("vpbe_controller", pdev->name) == 0)
                vpbe_disp->vpbe_dev = platform_get_drvdata(pdev);
 
-       if (strcmp("vpbe-osd", pdev->name) == 0)
+       if (strstr(pdev->name, "vpbe-osd") != NULL)
                vpbe_disp->osd_device = platform_get_drvdata(pdev);
 
        return 0;
index 707f243f810d806fcc5efc04a13b66bd2a47ca63..12ad17c52ef3467c8b19c2c046de133509519976 100644 (file)
 #include <linux/io.h>
 #include "vpbe_osd_regs.h"
 
-#define MODULE_NAME    VPBE_OSD_SUBDEV_NAME
+#define MODULE_NAME    "davinci-vpbe-osd"
+
+static struct platform_device_id vpbe_osd_devtype[] = {
+       {
+               .name = DM644X_VPBE_OSD_SUBDEV_NAME,
+               .driver_data = VPBE_VERSION_1,
+       }, {
+               .name = DM365_VPBE_OSD_SUBDEV_NAME,
+               .driver_data = VPBE_VERSION_2,
+       }, {
+               .name = DM355_VPBE_OSD_SUBDEV_NAME,
+               .driver_data = VPBE_VERSION_3,
+       },
+};
+
+MODULE_DEVICE_TABLE(platform, vpbe_osd_devtype);
 
 /* register access routines */
 static inline u32 osd_read(struct osd_state *sd, u32 offset)
@@ -129,7 +144,7 @@ static int _osd_dm6446_vid0_pingpong(struct osd_state *sd,
        struct osd_platform_data *pdata;
 
        pdata = (struct osd_platform_data *)sd->dev->platform_data;
-       if (pdata->field_inv_wa_enable) {
+       if (pdata != NULL && pdata->field_inv_wa_enable) {
 
                if (!field_inversion || !lconfig->interlaced) {
                        osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
@@ -1526,7 +1541,7 @@ static const struct vpbe_osd_ops osd_ops = {
 
 static int osd_probe(struct platform_device *pdev)
 {
-       struct osd_platform_data *pdata;
+       const struct platform_device_id *pdev_id;
        struct osd_state *osd;
        struct resource *res;
        int ret = 0;
@@ -1535,16 +1550,15 @@ static int osd_probe(struct platform_device *pdev)
        if (osd == NULL)
                return -ENOMEM;
 
-       osd->dev = &pdev->dev;
-       pdata = (struct osd_platform_data *)pdev->dev.platform_data;
-       osd->vpbe_type = (enum vpbe_version)pdata->vpbe_type;
-       if (NULL == pdev->dev.platform_data) {
-               dev_err(osd->dev, "No platform data defined for OSD"
-                       " sub device\n");
-               ret = -ENOENT;
+       pdev_id = platform_get_device_id(pdev);
+       if (!pdev_id) {
+               ret = -EINVAL;
                goto free_mem;
        }
 
+       osd->dev = &pdev->dev;
+       osd->vpbe_type = pdev_id->driver_data;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(osd->dev, "Unable to get OSD register address map\n");
@@ -1595,6 +1609,7 @@ static struct platform_driver osd_driver = {
                .name   = MODULE_NAME,
                .owner  = THIS_MODULE,
        },
+       .id_table       = vpbe_osd_devtype
 };
 
 module_platform_driver(osd_driver);
index aed7369b962a7da5a5c7e6c826ce06944d12136c..bdbebd59df98b9ee091f3177c8f18ee6c67cb632 100644 (file)
 
 #include "vpbe_venc_regs.h"
 
-#define MODULE_NAME    VPBE_VENC_SUBDEV_NAME
+#define MODULE_NAME    "davinci-vpbe-venc"
+
+static struct platform_device_id vpbe_venc_devtype[] = {
+       {
+               .name = DM644X_VPBE_VENC_SUBDEV_NAME,
+               .driver_data = VPBE_VERSION_1,
+       }, {
+               .name = DM365_VPBE_VENC_SUBDEV_NAME,
+               .driver_data = VPBE_VERSION_2,
+       }, {
+               .name = DM355_VPBE_VENC_SUBDEV_NAME,
+               .driver_data = VPBE_VERSION_3,
+       },
+};
+
+MODULE_DEVICE_TABLE(platform, vpbe_venc_devtype);
 
 static int debug = 2;
 module_param(debug, int, 0644);
@@ -54,6 +69,7 @@ struct venc_state {
        spinlock_t lock;
        void __iomem *venc_base;
        void __iomem *vdaccfg_reg;
+       enum vpbe_version venc_type;
 };
 
 static inline struct venc_state *to_state(struct v4l2_subdev *sd)
@@ -127,7 +143,7 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
 static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
 {
        struct venc_state *venc = to_state(sd);
-       struct venc_platform_data *pdata = venc->pdata;
+
        v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
 
        if (benable) {
@@ -159,7 +175,7 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
 
                /* Disable LCD output control (accepting default polarity) */
                venc_write(sd, VENC_LCDOUT, 0);
-               if (pdata->venc_type != VPBE_VERSION_3)
+               if (venc->venc_type != VPBE_VERSION_3)
                        venc_write(sd, VENC_CMPNT, 0x100);
                venc_write(sd, VENC_HSPLS, 0);
                venc_write(sd, VENC_HINT, 0);
@@ -203,11 +219,11 @@ static int venc_set_ntsc(struct v4l2_subdev *sd)
 
        venc_enabledigitaloutput(sd, 0);
 
-       if (pdata->venc_type == VPBE_VERSION_3) {
+       if (venc->venc_type == VPBE_VERSION_3) {
                venc_write(sd, VENC_CLKCTL, 0x01);
                venc_write(sd, VENC_VIDCTL, 0);
                val = vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
-       } else if (pdata->venc_type == VPBE_VERSION_2) {
+       } else if (venc->venc_type == VPBE_VERSION_2) {
                venc_write(sd, VENC_CLKCTL, 0x01);
                venc_write(sd, VENC_VIDCTL, 0);
                vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
@@ -238,7 +254,6 @@ static int venc_set_ntsc(struct v4l2_subdev *sd)
 static int venc_set_pal(struct v4l2_subdev *sd)
 {
        struct venc_state *venc = to_state(sd);
-       struct venc_platform_data *pdata = venc->pdata;
 
        v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
 
@@ -249,11 +264,11 @@ static int venc_set_pal(struct v4l2_subdev *sd)
 
        venc_enabledigitaloutput(sd, 0);
 
-       if (pdata->venc_type == VPBE_VERSION_3) {
+       if (venc->venc_type == VPBE_VERSION_3) {
                venc_write(sd, VENC_CLKCTL, 0x1);
                venc_write(sd, VENC_VIDCTL, 0);
                vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
-       } else if (pdata->venc_type == VPBE_VERSION_2) {
+       } else if (venc->venc_type == VPBE_VERSION_2) {
                venc_write(sd, VENC_CLKCTL, 0x1);
                venc_write(sd, VENC_VIDCTL, 0);
                vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
@@ -293,8 +308,8 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
        struct venc_platform_data *pdata = venc->pdata;
 
        v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
-       if ((pdata->venc_type != VPBE_VERSION_1) &&
-           (pdata->venc_type != VPBE_VERSION_2))
+       if (venc->venc_type != VPBE_VERSION_1 &&
+           venc->venc_type != VPBE_VERSION_2)
                return -EINVAL;
 
        /* Setup clock at VPSS & VENC for SD */
@@ -303,12 +318,12 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
 
        venc_enabledigitaloutput(sd, 0);
 
-       if (pdata->venc_type == VPBE_VERSION_2)
+       if (venc->venc_type == VPBE_VERSION_2)
                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
        venc_write(sd, VENC_OSDCLK0, 0);
        venc_write(sd, VENC_OSDCLK1, 1);
 
-       if (pdata->venc_type == VPBE_VERSION_1) {
+       if (venc->venc_type == VPBE_VERSION_1) {
                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
                            VENC_VDPRO_DAFRQ);
                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
@@ -341,8 +356,8 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
 
        v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
 
-       if ((pdata->venc_type != VPBE_VERSION_1) &&
-         (pdata->venc_type != VPBE_VERSION_2))
+       if (venc->venc_type != VPBE_VERSION_1 &&
+           venc->venc_type != VPBE_VERSION_2)
                return -EINVAL;
        /* Setup clock at VPSS & VENC for SD */
        if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
@@ -350,13 +365,13 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
 
        venc_enabledigitaloutput(sd, 0);
 
-       if (pdata->venc_type == VPBE_VERSION_2)
+       if (venc->venc_type == VPBE_VERSION_2)
                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
 
        venc_write(sd, VENC_OSDCLK0, 0);
        venc_write(sd, VENC_OSDCLK1, 1);
 
-       if (pdata->venc_type == VPBE_VERSION_1) {
+       if (venc->venc_type == VPBE_VERSION_1) {
                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
                            VENC_VDPRO_DAFRQ);
                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
@@ -460,14 +475,14 @@ static int venc_s_dv_timings(struct v4l2_subdev *sd,
        else if (height == 480)
                return venc_set_480p59_94(sd);
        else if ((height == 720) &&
-                       (venc->pdata->venc_type == VPBE_VERSION_2)) {
+                       (venc->venc_type == VPBE_VERSION_2)) {
                /* TBD setup internal 720p mode here */
                ret = venc_set_720p60_internal(sd);
                /* for DM365 VPBE, there is DAC inside */
                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
                return ret;
        } else if ((height == 1080) &&
-               (venc->pdata->venc_type == VPBE_VERSION_2)) {
+               (venc->venc_type == VPBE_VERSION_2)) {
                /* TBD setup internal 1080i mode here */
                ret = venc_set_1080i30_internal(sd);
                /* for DM365 VPBE, there is DAC inside */
@@ -556,7 +571,7 @@ static int venc_device_get(struct device *dev, void *data)
        struct platform_device *pdev = to_platform_device(dev);
        struct venc_state **venc = data;
 
-       if (strcmp(MODULE_NAME, pdev->name) == 0)
+       if (strstr(pdev->name, "vpbe-venc") != NULL)
                *venc = platform_get_drvdata(pdev);
 
        return 0;
@@ -593,6 +608,7 @@ EXPORT_SYMBOL(venc_sub_dev_init);
 
 static int venc_probe(struct platform_device *pdev)
 {
+       const struct platform_device_id *pdev_id;
        struct venc_state *venc;
        struct resource *res;
        int ret;
@@ -601,6 +617,12 @@ static int venc_probe(struct platform_device *pdev)
        if (venc == NULL)
                return -ENOMEM;
 
+       pdev_id = platform_get_device_id(pdev);
+       if (!pdev_id) {
+               ret = -EINVAL;
+               goto free_mem;
+       }
+       venc->venc_type = pdev_id->driver_data;
        venc->pdev = &pdev->dev;
        venc->pdata = pdev->dev.platform_data;
        if (NULL == venc->pdata) {
@@ -630,7 +652,7 @@ static int venc_probe(struct platform_device *pdev)
                goto release_venc_mem_region;
        }
 
-       if (venc->pdata->venc_type != VPBE_VERSION_1) {
+       if (venc->venc_type != VPBE_VERSION_1) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                if (!res) {
                        dev_err(venc->pdev,
@@ -681,7 +703,7 @@ static int venc_remove(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        iounmap((void *)venc->venc_base);
        release_mem_region(res->start, resource_size(res));
-       if (venc->pdata->venc_type != VPBE_VERSION_1) {
+       if (venc->venc_type != VPBE_VERSION_1) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                iounmap((void *)venc->vdaccfg_reg);
                release_mem_region(res->start, resource_size(res));
@@ -698,6 +720,7 @@ static struct platform_driver venc_driver = {
                .name   = MODULE_NAME,
                .owner  = THIS_MODULE,
        },
+       .id_table       = vpbe_venc_devtype
 };
 
 module_platform_driver(venc_driver);
index 8be492cd8ed46bf58a9cd79ce4d26ed8474404aa..65f4264bd5b448244d132fa4210f58a0d258b890 100644 (file)
@@ -560,10 +560,7 @@ static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev)
 
 static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev)
 {
-       struct timeval timevalue;
-
-       do_gettimeofday(&timevalue);
-       vpfe_dev->cur_frm->ts = timevalue;
+       v4l2_get_timestamp(&vpfe_dev->cur_frm->ts);
        vpfe_dev->cur_frm->state = VIDEOBUF_DONE;
        vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage;
        wake_up_interruptible(&vpfe_dev->cur_frm->done);
index a409ccefb38073ec2c67d74d96ea53079bc6f38a..5892d2bc8eeef5d844d53f144bca0ea35f1fde7a 100644 (file)
@@ -411,7 +411,7 @@ static struct vb2_ops video_qops = {
  */
 static void vpif_process_buffer_complete(struct common_obj *common)
 {
-       do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp);
+       v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp);
        vb2_buffer_done(&common->cur_frm->vb,
                                            VB2_BUF_STATE_DONE);
        /* Make curFrm pointing to nextFrm */
index 9f2b603be9c9b319d56b72bd99c3028df07632aa..dd249c96126dee69e6fd883f0459eefc26418baf 100644 (file)
@@ -402,7 +402,7 @@ static void process_interlaced_mode(int fid, struct common_obj *common)
                /* one frame is displayed If next frame is
                 *  available, release cur_frm and move on */
                /* Copy frame display time */
-               do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp);
+               v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp);
                /* Change status of the cur_frm */
                vb2_buffer_done(&common->cur_frm->vb,
                                            VB2_BUF_STATE_DONE);
@@ -462,8 +462,8 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
                        if (!channel_first_int[i][channel_id]) {
                                /* Mark status of the cur_frm to
                                 * done and unlock semaphore on it */
-                               do_gettimeofday(&common->cur_frm->vb.
-                                               v4l2_buf.timestamp);
+                               v4l2_get_timestamp(&common->cur_frm->vb.
+                                                  v4l2_buf.timestamp);
                                vb2_buffer_done(&common->cur_frm->vb,
                                            VB2_BUF_STATE_DONE);
                                /* Make cur_frm pointing to next_frm */
index 146e4b01ac177593b58ad5c7fadc1724d2118973..d945f94053a8802836f0a98cd4709f2e7138c895 100644 (file)
@@ -51,13 +51,29 @@ MODULE_AUTHOR("Texas Instruments");
 /* VENCINT - vpss_int8 */
 #define DM355_VPSSBL_EVTSEL_DEFAULT    0x4
 
-#define DM365_ISP5_PCCR                0x04
+#define DM365_ISP5_PCCR                                0x04
+#define DM365_ISP5_PCCR_BL_CLK_ENABLE          BIT(0)
+#define DM365_ISP5_PCCR_ISIF_CLK_ENABLE                BIT(1)
+#define DM365_ISP5_PCCR_H3A_CLK_ENABLE         BIT(2)
+#define DM365_ISP5_PCCR_RSZ_CLK_ENABLE         BIT(3)
+#define DM365_ISP5_PCCR_IPIPE_CLK_ENABLE       BIT(4)
+#define DM365_ISP5_PCCR_IPIPEIF_CLK_ENABLE     BIT(5)
+#define DM365_ISP5_PCCR_RSV                    BIT(6)
+
+#define DM365_ISP5_BCR                 0x08
+#define DM365_ISP5_BCR_ISIF_OUT_ENABLE BIT(1)
+
 #define DM365_ISP5_INTSEL1             0x10
 #define DM365_ISP5_INTSEL2             0x14
 #define DM365_ISP5_INTSEL3             0x18
 #define DM365_ISP5_CCDCMUX             0x20
 #define DM365_ISP5_PG_FRAME_SIZE       0x28
 #define DM365_VPBE_CLK_CTRL            0x00
+
+#define VPSS_CLK_CTRL                  0x01c40044
+#define VPSS_CLK_CTRL_VENCCLKEN                BIT(3)
+#define VPSS_CLK_CTRL_DACCLKEN         BIT(4)
+
 /*
  * vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1,
  * AF - vpss_int3
@@ -95,12 +111,19 @@ struct vpss_hw_ops {
        void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
        /* clear wbl overflow bit */
        int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
+       /* set sync polarity */
+       void (*set_sync_pol)(struct vpss_sync_pol);
+       /* set the PG_FRAME_SIZE register*/
+       void (*set_pg_frame_size)(struct vpss_pg_frame_size);
+       /* check and clear interrupt if occured */
+       int (*dma_complete_interrupt)(void);
 };
 
 /* vpss configuration */
 struct vpss_oper_config {
        __iomem void *vpss_regs_base0;
        __iomem void *vpss_regs_base1;
+       resource_size_t *vpss_regs_base2;
        enum vpss_platform_type platform;
        spinlock_t vpss_lock;
        struct vpss_hw_ops hw_ops;
@@ -158,6 +181,14 @@ static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
        bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
 }
 
+int vpss_dma_complete_interrupt(void)
+{
+       if (!oper_cfg.hw_ops.dma_complete_interrupt)
+               return 2;
+       return oper_cfg.hw_ops.dma_complete_interrupt();
+}
+EXPORT_SYMBOL(vpss_dma_complete_interrupt);
+
 int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
 {
        if (!oper_cfg.hw_ops.select_ccdc_source)
@@ -183,6 +214,15 @@ static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
        return 0;
 }
 
+void vpss_set_sync_pol(struct vpss_sync_pol sync)
+{
+       if (!oper_cfg.hw_ops.set_sync_pol)
+               return;
+
+       oper_cfg.hw_ops.set_sync_pol(sync);
+}
+EXPORT_SYMBOL(vpss_set_sync_pol);
+
 int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
 {
        if (!oper_cfg.hw_ops.clear_wbl_overflow)
@@ -348,6 +388,15 @@ void dm365_vpss_set_sync_pol(struct vpss_sync_pol sync)
 }
 EXPORT_SYMBOL(dm365_vpss_set_sync_pol);
 
+void vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size)
+{
+       if (!oper_cfg.hw_ops.set_pg_frame_size)
+               return;
+
+       oper_cfg.hw_ops.set_pg_frame_size(frame_size);
+}
+EXPORT_SYMBOL(vpss_set_pg_frame_size);
+
 void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size)
 {
        int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16;
@@ -426,6 +475,16 @@ static int __devinit vpss_probe(struct platform_device *pdev)
                oper_cfg.hw_ops.enable_clock = dm365_enable_clock;
                oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source;
                /* Setup vpss interrupts */
+               isp5_write((isp5_read(DM365_ISP5_PCCR) |
+                                     DM365_ISP5_PCCR_BL_CLK_ENABLE |
+                                     DM365_ISP5_PCCR_ISIF_CLK_ENABLE |
+                                     DM365_ISP5_PCCR_H3A_CLK_ENABLE |
+                                     DM365_ISP5_PCCR_RSZ_CLK_ENABLE |
+                                     DM365_ISP5_PCCR_IPIPE_CLK_ENABLE |
+                                     DM365_ISP5_PCCR_IPIPEIF_CLK_ENABLE |
+                                     DM365_ISP5_PCCR_RSV), DM365_ISP5_PCCR);
+               isp5_write((isp5_read(DM365_ISP5_BCR) |
+                           DM365_ISP5_BCR_ISIF_OUT_ENABLE), DM365_ISP5_BCR);
                isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1);
                isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2);
                isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3);
@@ -471,11 +530,20 @@ static struct platform_driver vpss_driver = {
 
 static void vpss_exit(void)
 {
+       iounmap(oper_cfg.vpss_regs_base2);
+       release_mem_region(VPSS_CLK_CTRL, 4);
        platform_driver_unregister(&vpss_driver);
 }
 
 static int __init vpss_init(void)
 {
+       if (!request_mem_region(VPSS_CLK_CTRL, 4, "vpss_clock_control"))
+               return -EBUSY;
+
+       oper_cfg.vpss_regs_base2 = ioremap(VPSS_CLK_CTRL, 4);
+       writel(VPSS_CLK_CTRL_VENCCLKEN |
+                    VPSS_CLK_CTRL_DACCLKEN, oper_cfg.vpss_regs_base2);
+
        return platform_driver_register(&vpss_driver);
 }
 subsys_initcall(vpss_init);
index cc7b218d047cffb5e48e0e031eaae6ae7a0bbffb..ae885c7ebc41eef2ba9266b526d1b57164b7d940 100644 (file)
@@ -185,6 +185,15 @@ static const struct gsc_fmt gsc_formats[] = {
                .corder         = GSC_CRCB,
                .num_planes     = 3,
                .num_comp       = 3,
+       }, {
+               .name           = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled",
+               .pixelformat    = V4L2_PIX_FMT_NV12MT_16X16,
+               .depth          = { 8, 4 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 2,
+               .num_comp       = 2,
        }
 };
 
@@ -935,8 +944,8 @@ static struct gsc_variant gsc_v_100_variant = {
        .pix_max                = &gsc_v_100_max,
        .pix_min                = &gsc_v_100_min,
        .pix_align              = &gsc_v_100_align,
-       .in_buf_cnt             = 8,
-       .out_buf_cnt            = 16,
+       .in_buf_cnt             = 32,
+       .out_buf_cnt            = 32,
        .sc_up_max              = 8,
        .sc_down_max            = 16,
        .poly_sc_down_max       = 4,
@@ -993,12 +1002,8 @@ static void *gsc_get_drv_data(struct platform_device *pdev)
 
 static void gsc_clk_put(struct gsc_dev *gsc)
 {
-       if (IS_ERR_OR_NULL(gsc->clock))
-               return;
-
-       clk_unprepare(gsc->clock);
-       clk_put(gsc->clock);
-       gsc->clock = NULL;
+       if (!IS_ERR(gsc->clock))
+               clk_unprepare(gsc->clock);
 }
 
 static int gsc_clk_get(struct gsc_dev *gsc)
@@ -1007,27 +1012,22 @@ static int gsc_clk_get(struct gsc_dev *gsc)
 
        dev_dbg(&gsc->pdev->dev, "gsc_clk_get Called\n");
 
-       gsc->clock = clk_get(&gsc->pdev->dev, GSC_CLOCK_GATE_NAME);
-       if (IS_ERR(gsc->clock))
-               goto err_print;
+       gsc->clock = devm_clk_get(&gsc->pdev->dev, GSC_CLOCK_GATE_NAME);
+       if (IS_ERR(gsc->clock)) {
+               dev_err(&gsc->pdev->dev, "failed to get clock~~~: %s\n",
+                       GSC_CLOCK_GATE_NAME);
+               return PTR_ERR(gsc->clock);
+       }
 
        ret = clk_prepare(gsc->clock);
        if (ret < 0) {
-               clk_put(gsc->clock);
-               gsc->clock = NULL;
-               goto err;
+               dev_err(&gsc->pdev->dev, "clock prepare failed for clock: %s\n",
+                       GSC_CLOCK_GATE_NAME);
+               gsc->clock = ERR_PTR(-EINVAL);
+               return ret;
        }
 
        return 0;
-
-err:
-       dev_err(&gsc->pdev->dev, "clock prepare failed for clock: %s\n",
-                                       GSC_CLOCK_GATE_NAME);
-       gsc_clk_put(gsc);
-err_print:
-       dev_err(&gsc->pdev->dev, "failed to get clock~~~: %s\n",
-                                       GSC_CLOCK_GATE_NAME);
-       return -ENXIO;
 }
 
 static int gsc_m2m_suspend(struct gsc_dev *gsc)
@@ -1096,6 +1096,7 @@ static int gsc_probe(struct platform_device *pdev)
        init_waitqueue_head(&gsc->irq_queue);
        spin_lock_init(&gsc->slock);
        mutex_init(&gsc->lock);
+       gsc->clock = ERR_PTR(-EINVAL);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        gsc->regs = devm_request_and_ioremap(dev, res);
@@ -1159,6 +1160,7 @@ static int __devexit gsc_remove(struct platform_device *pdev)
 
        vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx);
        pm_runtime_disable(&pdev->dev);
+       gsc_clk_put(gsc);
 
        dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
        return 0;
index 5f157efd24f0fcc36f0bf72f7bf8fdf1b4a362c0..cc19bba09bd173720b2e8fc7b35813ea409da703 100644 (file)
@@ -427,6 +427,11 @@ static inline void gsc_ctx_state_lock_clear(u32 state, struct gsc_ctx *ctx)
        spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags);
 }
 
+static inline int is_tiled(const struct gsc_fmt *fmt)
+{
+       return fmt->pixelformat == V4L2_PIX_FMT_NV12MT_16X16;
+}
+
 static inline void gsc_hw_enable_control(struct gsc_dev *dev, bool on)
 {
        u32 cfg = readl(dev->regs + GSC_ENABLE);
index c267c57c76fdeec23c6fb51c0609929f630c0e91..0d06d6c6f37376f8b8a3e48e0c225c235f74f53e 100644 (file)
@@ -99,22 +99,28 @@ static void gsc_m2m_job_abort(void *priv)
                gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 }
 
-static int gsc_fill_addr(struct gsc_ctx *ctx)
+static int gsc_get_bufs(struct gsc_ctx *ctx)
 {
        struct gsc_frame *s_frame, *d_frame;
-       struct vb2_buffer *vb = NULL;
+       struct vb2_buffer *src_vb, *dst_vb;
        int ret;
 
        s_frame = &ctx->s_frame;
        d_frame = &ctx->d_frame;
 
-       vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
-       ret = gsc_prepare_addr(ctx, vb, s_frame, &s_frame->addr);
+       src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+       ret = gsc_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 = gsc_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
        if (ret)
                return ret;
 
-       vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
-       return gsc_prepare_addr(ctx, vb, d_frame, &d_frame->addr);
+       dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
+
+       return 0;
 }
 
 static void gsc_m2m_device_run(void *priv)
@@ -148,7 +154,7 @@ static void gsc_m2m_device_run(void *priv)
                goto put_device;
        }
 
-       ret = gsc_fill_addr(ctx);
+       ret = gsc_get_bufs(ctx);
        if (ret) {
                pr_err("Wrong address");
                goto put_device;
@@ -597,7 +603,7 @@ static int gsc_m2m_open(struct file *file)
        if (mutex_lock_interruptible(&gsc->lock))
                return -ERESTARTSYS;
 
-       ctx = kzalloc(sizeof (*ctx), GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                ret = -ENOMEM;
                goto unlock;
index 0146b354dc22a785961dfe0e1dd5df6214311c53..6f5b5a486cf361f8c52f74db5bc5e62e94a31491 100644 (file)
@@ -214,6 +214,9 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
                break;
        }
 
+       if (is_tiled(frame->fmt))
+               cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
+
        writel(cfg, dev->regs + GSC_IN_CON);
 }
 
@@ -334,6 +337,9 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
                break;
        }
 
+       if (is_tiled(frame->fmt))
+               cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
+
 end_set:
        writel(cfg, dev->regs + GSC_OUT_CON);
 }
index a8ddb0cacab82cc7d81e5c3f17b6d4d5f29d9a2a..d464509d0f0e1dbd8e0149f0e340ba6042e68602 100644 (file)
@@ -1181,7 +1181,7 @@ static void viu_capture_intr(struct viu_dev *dev, u32 status)
 
                if (waitqueue_active(&buf->vb.done)) {
                        list_del(&buf->vb.queue);
-                       do_gettimeofday(&buf->vb.ts);
+                       v4l2_get_timestamp(&buf->vb.ts);
                        buf->vb.state = VIDEOBUF_DONE;
                        buf->vb.field_count++;
                        wake_up(&buf->vb.done);
index 05c560f2ef062c8f21ba44a943fe004942de0e81..ed77a645e99266408143862f973eb6e277156276 100644 (file)
@@ -28,7 +28,7 @@ MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.0.1");
 
-static bool debug = true;
+static bool debug;
 module_param(debug, bool, 0644);
 
 /* Flags that indicate a format can be used for capture/output */
index 35cc526e6c9379626a647dfeb36e22c58d7bfd56..dade3ceab0927282e3d08d6f10e705f3bd1759c8 100644 (file)
@@ -595,7 +595,7 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus)
                return;
 
        spin_lock(&vout->vbq_lock);
-       do_gettimeofday(&timevalue);
+       v4l2_get_timestamp(&timevalue);
 
        switch (cur_display->type) {
        case OMAP_DISPLAY_TYPE_DSI:
@@ -1230,21 +1230,6 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
        return ret;
 }
 
-static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh,
-                       struct v4l2_fmtdesc *fmt)
-{
-       int index = fmt->index;
-
-       if (index >= NUM_OUTPUT_FORMATS)
-               return -EINVAL;
-
-       fmt->flags = omap_formats[index].flags;
-       strlcpy(fmt->description, omap_formats[index].description,
-                       sizeof(fmt->description));
-       fmt->pixelformat = omap_formats[index].pixelformat;
-       return 0;
-}
-
 static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
                        struct v4l2_format *f)
 {
@@ -1858,10 +1843,9 @@ static const struct v4l2_ioctl_ops vout_ioctl_ops = {
        .vidioc_s_fbuf                          = vidioc_s_fbuf,
        .vidioc_g_fbuf                          = vidioc_g_fbuf,
        .vidioc_s_ctrl                          = vidioc_s_ctrl,
-       .vidioc_try_fmt_vid_overlay             = vidioc_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_overlay               = vidioc_s_fmt_vid_overlay,
-       .vidioc_enum_fmt_vid_overlay            = vidioc_enum_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_overlay               = vidioc_g_fmt_vid_overlay,
+       .vidioc_try_fmt_vid_out_overlay         = vidioc_try_fmt_vid_overlay,
+       .vidioc_s_fmt_vid_out_overlay           = vidioc_s_fmt_vid_overlay,
+       .vidioc_g_fmt_vid_out_overlay           = vidioc_g_fmt_vid_overlay,
        .vidioc_cropcap                         = vidioc_cropcap,
        .vidioc_g_crop                          = vidioc_g_crop,
        .vidioc_s_crop                          = vidioc_s_crop,
index 70f45c381318929f4b80b70025fb368305a0b788..eda3274abf8edab4149e9c4c1d0ef4a80c174ed8 100644 (file)
@@ -402,7 +402,7 @@ static void omap24xxcam_vbq_complete(struct omap24xxcam_sgdma *sgdma,
                omap24xxcam_core_disable(cam);
        spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags);
 
-       do_gettimeofday(&vb->ts);
+       v4l2_get_timestamp(&vb->ts);
        vb->field_count = atomic_add_return(2, &fh->field_count);
        if (csr & csr_error) {
                vb->state = VIDEOBUF_ERROR;
index 15bf3eab2224ab3d835380c4a55b1e83e1269636..6599963cdd9ba25ccfcff1f326321542300f254a 100644 (file)
@@ -674,6 +674,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
                buf->vbuf.index = i;
                buf->vbuf.length = size;
                buf->vbuf.type = queue->type;
+               buf->vbuf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
                buf->vbuf.field = V4L2_FIELD_NONE;
                buf->vbuf.memory = memory;
 
index fdb6740248a73f58bd2c7ab42c72f03991d907f0..95e6a7820b5e3e91aad51aec83ebbc13e5c31b2b 100644 (file)
@@ -626,8 +626,8 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
 {
        bool rotation = ctx->rotation == 90 || ctx->rotation == 270;
        struct fimc_dev *fimc = ctx->fimc_dev;
-       struct fimc_variant *var = fimc->variant;
-       struct fimc_pix_limit *pl = var->pix_limit;
+       const struct fimc_variant *var = fimc->variant;
+       const struct fimc_pix_limit *pl = var->pix_limit;
        struct fimc_frame *dst = &ctx->d_frame;
        u32 depth, min_w, max_w, min_h, align_h = 3;
        u32 mask = FMT_FLAGS_CAM;
@@ -699,8 +699,8 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx,
 {
        bool rotate = ctx->rotation == 90 || ctx->rotation == 270;
        struct fimc_dev *fimc = ctx->fimc_dev;
-       struct fimc_variant *var = fimc->variant;
-       struct fimc_pix_limit *pl = var->pix_limit;
+       const struct fimc_variant *var = fimc->variant;
+       const struct fimc_pix_limit *pl = var->pix_limit;
        struct fimc_frame *sink = &ctx->s_frame;
        u32 max_w, max_h, min_w = 0, min_h = 0, min_sz;
        u32 align_sz = 0, align_h = 4;
@@ -793,6 +793,21 @@ static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv,
        return 0;
 }
 
+static struct media_entity *fimc_pipeline_get_head(struct media_entity *me)
+{
+       struct media_pad *pad = &me->pads[0];
+
+       while (!(pad->flags & MEDIA_PAD_FL_SOURCE)) {
+               pad = media_entity_remote_source(pad);
+               if (!pad)
+                       break;
+               me = pad->entity;
+               pad = &me->pads[0];
+       }
+
+       return me;
+}
+
 /**
  * fimc_pipeline_try_format - negotiate and/or set formats at pipeline
  *                            elements
@@ -808,19 +823,23 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
 {
        struct fimc_dev *fimc = ctx->fimc_dev;
        struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
-       struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
        struct v4l2_subdev_format sfmt;
        struct v4l2_mbus_framefmt *mf = &sfmt.format;
-       struct fimc_fmt *ffmt = NULL;
-       int ret, i = 0;
+       struct media_entity *me;
+       struct fimc_fmt *ffmt;
+       struct media_pad *pad;
+       int ret, i = 1;
+       u32 fcc;
 
        if (WARN_ON(!sd || !tfmt))
                return -EINVAL;
 
        memset(&sfmt, 0, sizeof(sfmt));
        sfmt.format = *tfmt;
-
        sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY;
+
+       me = fimc_pipeline_get_head(&sd->entity);
+
        while (1) {
                ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL,
                                        FMT_FLAGS_CAM, i++);
@@ -833,40 +852,52 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                }
                mf->code = tfmt->code = ffmt->mbus_code;
 
-               ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt);
-               if (ret)
-                       return ret;
-               if (mf->code != tfmt->code) {
-                       mf->code = 0;
-                       continue;
-               }
-               if (mf->width != tfmt->width || mf->height != tfmt->height) {
-                       u32 fcc = ffmt->fourcc;
-                       tfmt->width  = mf->width;
-                       tfmt->height = mf->height;
-                       ffmt = fimc_capture_try_format(ctx,
-                                              &tfmt->width, &tfmt->height,
-                                              NULL, &fcc, FIMC_SD_PAD_SOURCE);
-                       if (ffmt && ffmt->mbus_code)
-                               mf->code = ffmt->mbus_code;
-                       if (mf->width != tfmt->width ||
-                           mf->height != tfmt->height)
-                               continue;
-                       tfmt->code = mf->code;
+               /* set format on all pipeline subdevs */
+               while (me != &fimc->vid_cap.subdev.entity) {
+                       sd = media_entity_to_v4l2_subdev(me);
+
+                       sfmt.pad = 0;
+                       ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt);
+                       if (ret)
+                               return ret;
+
+                       if (me->pads[0].flags & MEDIA_PAD_FL_SINK) {
+                               sfmt.pad = me->num_pads - 1;
+                               mf->code = tfmt->code;
+                               ret = v4l2_subdev_call(sd, pad, set_fmt, NULL,
+                                                                       &sfmt);
+                               if (ret)
+                                       return ret;
+                       }
+
+                       pad = media_entity_remote_source(&me->pads[sfmt.pad]);
+                       if (!pad)
+                               return -EINVAL;
+                       me = pad->entity;
                }
-               if (csis)
-                       ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
 
-               if (mf->code == tfmt->code &&
-                   mf->width == tfmt->width && mf->height == tfmt->height)
-                       break;
+               if (mf->code != tfmt->code)
+                       continue;
+
+               fcc = ffmt->fourcc;
+               tfmt->width  = mf->width;
+               tfmt->height = mf->height;
+               ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height,
+                                       NULL, &fcc, FIMC_SD_PAD_SINK);
+               ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height,
+                                       NULL, &fcc, FIMC_SD_PAD_SOURCE);
+               if (ffmt && ffmt->mbus_code)
+                       mf->code = ffmt->mbus_code;
+               if (mf->width != tfmt->width || mf->height != tfmt->height)
+                       continue;
+               tfmt->code = mf->code;
+               break;
        }
 
        if (fmt_id && ffmt)
                *fmt_id = ffmt;
        *tfmt = *mf;
 
-       dbg("code: 0x%x, %dx%d, %p", mf->code, mf->width, mf->height, ffmt);
        return 0;
 }
 
@@ -884,14 +915,16 @@ static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
 {
        struct v4l2_mbus_frame_desc fd;
        int i, ret;
+       int pad;
 
        for (i = 0; i < num_planes; i++)
                fd.entry[i].length = plane_fmt[i].sizeimage;
 
+       pad = sensor->entity.num_pads - 1;
        if (try)
-               ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd);
+               ret = v4l2_subdev_call(sensor, pad, set_frame_desc, pad, &fd);
        else
-               ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd);
+               ret = v4l2_subdev_call(sensor, pad, get_frame_desc, pad, &fd);
 
        if (ret < 0)
                return ret;
index 8d0d2b94a135f45b0d8fa2c1378fd287aff7ef27..2a1558a37a41ec85db04e8976c4e765a4af364a8 100644 (file)
@@ -241,7 +241,7 @@ static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
 
 int fimc_set_scaler_info(struct fimc_ctx *ctx)
 {
-       struct fimc_variant *variant = ctx->fimc_dev->variant;
+       const struct fimc_variant *variant = ctx->fimc_dev->variant;
        struct device *dev = &ctx->fimc_dev->pdev->dev;
        struct fimc_scaler *sc = &ctx->scaler;
        struct fimc_frame *s_frame = &ctx->s_frame;
@@ -440,7 +440,7 @@ void fimc_set_yuv_order(struct fimc_ctx *ctx)
 
 void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
 {
-       struct fimc_variant *variant = ctx->fimc_dev->variant;
+       const struct fimc_variant *variant = ctx->fimc_dev->variant;
        u32 i, depth = 0;
 
        for (i = 0; i < f->fmt->colplanes; i++)
@@ -524,7 +524,7 @@ static int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx
 static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
 {
        struct fimc_dev *fimc = ctx->fimc_dev;
-       struct fimc_variant *variant = fimc->variant;
+       const struct fimc_variant *variant = fimc->variant;
        unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT;
        int ret = 0;
 
@@ -591,7 +591,7 @@ static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
 
 int fimc_ctrls_create(struct fimc_ctx *ctx)
 {
-       struct fimc_variant *variant = ctx->fimc_dev->variant;
+       const struct fimc_variant *variant = ctx->fimc_dev->variant;
        unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt);
        struct fimc_ctrls *ctrls = &ctx->ctrls;
        struct v4l2_ctrl_handler *handler = &ctrls->handler;
@@ -881,7 +881,7 @@ static int fimc_m2m_resume(struct fimc_dev *fimc)
 
 static int fimc_probe(struct platform_device *pdev)
 {
-       struct fimc_drvdata *drv_data = fimc_get_drvdata(pdev);
+       const struct fimc_drvdata *drv_data = fimc_get_drvdata(pdev);
        struct s5p_platform_fimc *pdata;
        struct fimc_dev *fimc;
        struct resource *res;
@@ -1053,7 +1053,7 @@ static int __devexit fimc_remove(struct platform_device *pdev)
 }
 
 /* Image pixel limits, similar across several FIMC HW revisions. */
-static struct fimc_pix_limit s5p_pix_limit[4] = {
+static const struct fimc_pix_limit s5p_pix_limit[4] = {
        [0] = {
                .scaler_en_w    = 3264,
                .scaler_dis_w   = 8192,
@@ -1088,7 +1088,7 @@ static struct fimc_pix_limit s5p_pix_limit[4] = {
        },
 };
 
-static struct fimc_variant fimc0_variant_s5p = {
+static const struct fimc_variant fimc0_variant_s5p = {
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
        .has_cam_if      = 1,
@@ -1100,7 +1100,7 @@ static struct fimc_variant fimc0_variant_s5p = {
        .pix_limit       = &s5p_pix_limit[0],
 };
 
-static struct fimc_variant fimc2_variant_s5p = {
+static const struct fimc_variant fimc2_variant_s5p = {
        .has_cam_if      = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
@@ -1110,7 +1110,7 @@ static struct fimc_variant fimc2_variant_s5p = {
        .pix_limit       = &s5p_pix_limit[1],
 };
 
-static struct fimc_variant fimc0_variant_s5pv210 = {
+static const struct fimc_variant fimc0_variant_s5pv210 = {
        .pix_hoff        = 1,
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
@@ -1123,7 +1123,7 @@ static struct fimc_variant fimc0_variant_s5pv210 = {
        .pix_limit       = &s5p_pix_limit[1],
 };
 
-static struct fimc_variant fimc1_variant_s5pv210 = {
+static const struct fimc_variant fimc1_variant_s5pv210 = {
        .pix_hoff        = 1,
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
@@ -1137,7 +1137,7 @@ static struct fimc_variant fimc1_variant_s5pv210 = {
        .pix_limit       = &s5p_pix_limit[2],
 };
 
-static struct fimc_variant fimc2_variant_s5pv210 = {
+static const struct fimc_variant fimc2_variant_s5pv210 = {
        .has_cam_if      = 1,
        .pix_hoff        = 1,
        .min_inp_pixsize = 16,
@@ -1148,7 +1148,7 @@ static struct fimc_variant fimc2_variant_s5pv210 = {
        .pix_limit       = &s5p_pix_limit[2],
 };
 
-static struct fimc_variant fimc0_variant_exynos4 = {
+static const struct fimc_variant fimc0_variant_exynos4210 = {
        .pix_hoff        = 1,
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
@@ -1164,9 +1164,8 @@ static struct fimc_variant fimc0_variant_exynos4 = {
        .pix_limit       = &s5p_pix_limit[1],
 };
 
-static struct fimc_variant fimc3_variant_exynos4 = {
+static const struct fimc_variant fimc3_variant_exynos4210 = {
        .pix_hoff        = 1,
-       .has_cam_if      = 1,
        .has_cistatus2   = 1,
        .has_mainscaler_ext = 1,
        .has_alpha       = 1,
@@ -1178,8 +1177,38 @@ static struct fimc_variant fimc3_variant_exynos4 = {
        .pix_limit       = &s5p_pix_limit[3],
 };
 
+static const struct fimc_variant fimc0_variant_exynos4x12 = {
+       .pix_hoff               = 1,
+       .has_inp_rot            = 1,
+       .has_out_rot            = 1,
+       .has_cam_if             = 1,
+       .has_isp_wb             = 1,
+       .has_cistatus2          = 1,
+       .has_mainscaler_ext     = 1,
+       .has_alpha              = 1,
+       .min_inp_pixsize        = 16,
+       .min_out_pixsize        = 16,
+       .hor_offs_align         = 2,
+       .min_vsize_align        = 1,
+       .out_buf_count          = 32,
+       .pix_limit              = &s5p_pix_limit[1],
+};
+
+static const struct fimc_variant fimc3_variant_exynos4x12 = {
+       .pix_hoff               = 1,
+       .has_cistatus2          = 1,
+       .has_mainscaler_ext     = 1,
+       .has_alpha              = 1,
+       .min_inp_pixsize        = 16,
+       .min_out_pixsize        = 16,
+       .hor_offs_align         = 2,
+       .min_vsize_align        = 1,
+       .out_buf_count          = 32,
+       .pix_limit              = &s5p_pix_limit[3],
+};
+
 /* S5PC100 */
-static struct fimc_drvdata fimc_drvdata_s5p = {
+static const struct fimc_drvdata fimc_drvdata_s5p = {
        .variant = {
                [0] = &fimc0_variant_s5p,
                [1] = &fimc0_variant_s5p,
@@ -1190,7 +1219,7 @@ static struct fimc_drvdata fimc_drvdata_s5p = {
 };
 
 /* S5PV210, S5PC110 */
-static struct fimc_drvdata fimc_drvdata_s5pv210 = {
+static const struct fimc_drvdata fimc_drvdata_s5pv210 = {
        .variant = {
                [0] = &fimc0_variant_s5pv210,
                [1] = &fimc1_variant_s5pv210,
@@ -1201,18 +1230,30 @@ static struct fimc_drvdata fimc_drvdata_s5pv210 = {
 };
 
 /* EXYNOS4210, S5PV310, S5PC210 */
-static struct fimc_drvdata fimc_drvdata_exynos4 = {
+static const struct fimc_drvdata fimc_drvdata_exynos4210 = {
+       .variant = {
+               [0] = &fimc0_variant_exynos4210,
+               [1] = &fimc0_variant_exynos4210,
+               [2] = &fimc0_variant_exynos4210,
+               [3] = &fimc3_variant_exynos4210,
+       },
+       .num_entities = 4,
+       .lclk_frequency = 166000000UL,
+};
+
+/* EXYNOS4212, EXYNOS4412 */
+static const struct fimc_drvdata fimc_drvdata_exynos4x12 = {
        .variant = {
-               [0] = &fimc0_variant_exynos4,
-               [1] = &fimc0_variant_exynos4,
-               [2] = &fimc0_variant_exynos4,
-               [3] = &fimc3_variant_exynos4,
+               [0] = &fimc0_variant_exynos4x12,
+               [1] = &fimc0_variant_exynos4x12,
+               [2] = &fimc0_variant_exynos4x12,
+               [3] = &fimc3_variant_exynos4x12,
        },
        .num_entities = 4,
        .lclk_frequency = 166000000UL,
 };
 
-static struct platform_device_id fimc_driver_ids[] = {
+static const struct platform_device_id fimc_driver_ids[] = {
        {
                .name           = "s5p-fimc",
                .driver_data    = (unsigned long)&fimc_drvdata_s5p,
@@ -1221,7 +1262,10 @@ static struct platform_device_id fimc_driver_ids[] = {
                .driver_data    = (unsigned long)&fimc_drvdata_s5pv210,
        }, {
                .name           = "exynos4-fimc",
-               .driver_data    = (unsigned long)&fimc_drvdata_exynos4,
+               .driver_data    = (unsigned long)&fimc_drvdata_exynos4210,
+       }, {
+               .name           = "exynos4x12-fimc",
+               .driver_data    = (unsigned long)&fimc_drvdata_exynos4x12,
        },
        {},
 };
index c0040d7924995051e71faaed70942cb2b74ec7c6..424ff960f0d97c0b98aa843bc6deff757635ec65 100644 (file)
@@ -372,6 +372,7 @@ struct fimc_pix_limit {
  * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register
  *                      are present in this IP revision
  * @has_cam_if: set if this instance has a camera input interface
+ * @has_isp_wb: set if this instance has ISP writeback input
  * @pix_limit: pixel size constraints for the scaler
  * @min_inp_pixsize: minimum input pixel size
  * @min_out_pixsize: minimum output pixel size
@@ -386,8 +387,9 @@ struct fimc_variant {
        unsigned int    has_cistatus2:1;
        unsigned int    has_mainscaler_ext:1;
        unsigned int    has_cam_if:1;
+       unsigned int    has_isp_wb:1;
        unsigned int    has_alpha:1;
-       struct fimc_pix_limit *pix_limit;
+       const struct fimc_pix_limit *pix_limit;
        u16             min_inp_pixsize;
        u16             min_out_pixsize;
        u16             hor_offs_align;
@@ -402,7 +404,7 @@ struct fimc_variant {
  * @lclk_frequency: local bus clock frequency
  */
 struct fimc_drvdata {
-       struct fimc_variant *variant[FIMC_MAX_DEVS];
+       const struct fimc_variant *variant[FIMC_MAX_DEVS];
        int num_entities;
        unsigned long lclk_frequency;
 };
@@ -435,7 +437,7 @@ struct fimc_dev {
        struct mutex                    lock;
        struct platform_device          *pdev;
        struct s5p_platform_fimc        *pdata;
-       struct fimc_variant             *variant;
+       const struct fimc_variant       *variant;
        u16                             id;
        struct clk                      *clock[MAX_FIMC_CLOCKS];
        void __iomem                    *regs;
index a22d7eb05c828b56f6083bd8782be258d98a8443..ad63ebf082c5b22fb646a6ca1b63825601cb82a3 100644 (file)
@@ -292,9 +292,11 @@ void flite_hw_dump_regs(struct fimc_lite *dev, const char *label)
        };
        u32 i;
 
-       pr_info("--- %s ---\n", label);
+       v4l2_info(&dev->subdev, "--- %s ---\n", label);
+
        for (i = 0; i < ARRAY_SIZE(registers); i++) {
                u32 cfg = readl(dev->regs + registers[i].offset);
-               pr_info("%s: %s:\t0x%08x\n", __func__, registers[i].name, cfg);
+               v4l2_info(&dev->subdev, "%9s: 0x%08x\n",
+                         registers[i].name, cfg);
        }
 }
index 1b309a72f09fbe847c1b4ac2178c1717a68f5a04..765b8e4cbf4e77074deac54c66378096c0cd45b6 100644 (file)
@@ -120,25 +120,29 @@ static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat,
        return def_fmt;
 }
 
-static int fimc_lite_hw_init(struct fimc_lite *fimc)
+static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output)
 {
        struct fimc_pipeline *pipeline = &fimc->pipeline;
-       struct fimc_sensor_info *sensor;
+       struct v4l2_subdev *sensor;
+       struct fimc_sensor_info *si;
        unsigned long flags;
 
-       if (pipeline->subdevs[IDX_SENSOR] == NULL)
+       sensor = isp_output ? fimc->sensor : pipeline->subdevs[IDX_SENSOR];
+
+       if (sensor == NULL)
                return -ENXIO;
 
        if (fimc->fmt == NULL)
                return -EINVAL;
 
-       sensor = v4l2_get_subdev_hostdata(pipeline->subdevs[IDX_SENSOR]);
+       /* Get sensor configuration data from the sensor subdev */
+       si = v4l2_get_subdev_hostdata(sensor);
        spin_lock_irqsave(&fimc->slock, flags);
 
-       flite_hw_set_camera_bus(fimc, &sensor->pdata);
+       flite_hw_set_camera_bus(fimc, &si->pdata);
        flite_hw_set_source_format(fimc, &fimc->inp_frame);
        flite_hw_set_window_offset(fimc, &fimc->inp_frame);
-       flite_hw_set_output_dma(fimc, &fimc->out_frame, true);
+       flite_hw_set_output_dma(fimc, &fimc->out_frame, !isp_output);
        flite_hw_set_interrupt_mask(fimc);
        flite_hw_set_test_pattern(fimc, fimc->test_pattern->val);
 
@@ -296,7 +300,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 
        fimc->frame_count = 0;
 
-       ret = fimc_lite_hw_init(fimc);
+       ret = fimc_lite_hw_init(fimc, false);
        if (ret) {
                fimc_lite_reinit(fimc, false);
                return ret;
@@ -460,6 +464,11 @@ static int fimc_lite_open(struct file *file)
        if (mutex_lock_interruptible(&fimc->lock))
                return -ERESTARTSYS;
 
+       if (fimc->out_path != FIMC_IO_DMA) {
+               ret = -EBUSY;
+               goto done;
+       }
+
        set_bit(ST_FLITE_IN_USE, &fimc->state);
        ret = pm_runtime_get_sync(&fimc->pdev->dev);
        if (ret < 0)
@@ -962,6 +971,29 @@ static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = {
        .vidioc_streamoff               = fimc_lite_streamoff,
 };
 
+/* Called with the media graph mutex held */
+static struct v4l2_subdev *__find_remote_sensor(struct media_entity *me)
+{
+       struct media_pad *pad = &me->pads[0];
+       struct v4l2_subdev *sd;
+
+       while (pad->flags & MEDIA_PAD_FL_SINK) {
+               /* source pad */
+               pad = media_entity_remote_source(pad);
+               if (pad == NULL ||
+                   media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+                       break;
+
+               sd = media_entity_to_v4l2_subdev(pad->entity);
+
+               if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR)
+                       return sd;
+               /* sink pad */
+               pad = &sd->entity.pads[0];
+       }
+       return NULL;
+}
+
 /* Capture subdev media entity operations */
 static int fimc_lite_link_setup(struct media_entity *entity,
                                const struct media_pad *local,
@@ -970,46 +1002,59 @@ static int fimc_lite_link_setup(struct media_entity *entity,
        struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
        unsigned int remote_ent_type = media_entity_type(remote->entity);
+       int ret = 0;
 
        if (WARN_ON(fimc == NULL))
                return 0;
 
        v4l2_dbg(1, debug, sd, "%s: %s --> %s, flags: 0x%x. source_id: 0x%x",
-                __func__, local->entity->name, remote->entity->name,
+                __func__, remote->entity->name, local->entity->name,
                 flags, fimc->source_subdev_grp_id);
 
-       switch (local->index) {
-       case FIMC_SD_PAD_SINK:
-               if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV)
-                       return -EINVAL;
+       mutex_lock(&fimc->lock);
 
+       switch (local->index) {
+       case FLITE_SD_PAD_SINK:
+               if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+                       ret = -EINVAL;
+                       break;
+               }
                if (flags & MEDIA_LNK_FL_ENABLED) {
-                       if (fimc->source_subdev_grp_id != 0)
-                               return -EBUSY;
-                       fimc->source_subdev_grp_id = sd->grp_id;
-                       return 0;
+                       if (fimc->source_subdev_grp_id == 0)
+                               fimc->source_subdev_grp_id = sd->grp_id;
+                       else
+                               ret = -EBUSY;
+               } else {
+                       fimc->source_subdev_grp_id = 0;
+                       fimc->sensor = NULL;
                }
+               break;
 
-               fimc->source_subdev_grp_id = 0;
+       case FLITE_SD_PAD_SOURCE_DMA:
+               if (!(flags & MEDIA_LNK_FL_ENABLED))
+                       fimc->out_path = FIMC_IO_NONE;
+               else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+                       fimc->out_path = FIMC_IO_DMA;
+               else
+                       ret = -EINVAL;
                break;
 
-       case FIMC_SD_PAD_SOURCE:
-               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+       case FLITE_SD_PAD_SOURCE_ISP:
+               if (!(flags & MEDIA_LNK_FL_ENABLED))
                        fimc->out_path = FIMC_IO_NONE;
-                       return 0;
-               }
-               if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+               else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
                        fimc->out_path = FIMC_IO_ISP;
                else
-                       fimc->out_path = FIMC_IO_DMA;
+                       ret = -EINVAL;
                break;
 
        default:
                v4l2_err(sd, "Invalid pad index\n");
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
-       return 0;
+       mutex_unlock(&fimc->lock);
+       return ret;
 }
 
 static const struct media_entity_operations fimc_lite_subdev_media_ops = {
@@ -1188,13 +1233,49 @@ static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd,
 static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on)
 {
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
+       unsigned long flags;
+       int ret;
 
-       if (fimc->out_path == FIMC_IO_DMA)
+       /*
+        * Find sensor subdev linked to FIMC-LITE directly or through
+        * MIPI-CSIS. This is required for configuration where FIMC-LITE
+        * is used as a subdev only and feeds data internally to FIMC-IS.
+        * The pipeline links are protected through entity.stream_count
+        * so there is no need to take the media graph mutex here.
+        */
+       fimc->sensor = __find_remote_sensor(&sd->entity);
+
+       mutex_lock(&fimc->lock);
+       if (fimc->out_path != FIMC_IO_ISP) {
+               mutex_unlock(&fimc->lock);
                return -ENOIOCTLCMD;
+       }
 
-       /* TODO: */
+       if (on) {
+               flite_hw_reset(fimc);
+               ret = fimc_lite_hw_init(fimc, true);
+               if (!ret) {
+                       spin_lock_irqsave(&fimc->slock, flags);
+                       flite_hw_capture_start(fimc);
+                       spin_unlock_irqrestore(&fimc->slock, flags);
+               }
+       } else {
+               set_bit(ST_FLITE_OFF, &fimc->state);
 
-       return 0;
+               spin_lock_irqsave(&fimc->slock, flags);
+               flite_hw_capture_stop(fimc);
+               spin_unlock_irqrestore(&fimc->slock, flags);
+
+               ret = wait_event_timeout(fimc->irq_queue,
+                               !test_bit(ST_FLITE_OFF, &fimc->state),
+                               msecs_to_jiffies(200));
+               if (ret == 0)
+                       v4l2_err(sd, "s_stream(0) timeout\n");
+               clear_bit(ST_FLITE_RUN, &fimc->state);
+       }
+
+       mutex_unlock(&fimc->lock);
+       return ret;
 }
 
 static int fimc_lite_subdev_s_power(struct v4l2_subdev *sd, int on)
@@ -1347,9 +1428,10 @@ static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc)
        sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
        snprintf(sd->name, sizeof(sd->name), "FIMC-LITE.%d", fimc->index);
 
-       fimc->subdev_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-       fimc->subdev_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-       ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
+       fimc->subdev_pads[FLITE_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       fimc->subdev_pads[FLITE_SD_PAD_SOURCE_DMA].flags = MEDIA_PAD_FL_SOURCE;
+       fimc->subdev_pads[FLITE_SD_PAD_SOURCE_ISP].flags = MEDIA_PAD_FL_SOURCE;
+       ret = media_entity_init(&sd->entity, FLITE_SD_PADS_NUM,
                                fimc->subdev_pads, 0);
        if (ret)
                return ret;
@@ -1518,7 +1600,7 @@ static int fimc_lite_resume(struct device *dev)
        INIT_LIST_HEAD(&fimc->active_buf_q);
        fimc_pipeline_call(fimc, open, &fimc->pipeline,
                           &fimc->vfd.entity, false);
-       fimc_lite_hw_init(fimc);
+       fimc_lite_hw_init(fimc, fimc->out_path == FIMC_IO_ISP);
        clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
 
        for (i = 0; i < fimc->reqbufs_count; i++) {
index 3081db35c5b0bfd60001f1e92483c22241adf1b7..4576922952f3e8c67b51146e81383b3e97a73d10 100644 (file)
@@ -45,8 +45,9 @@ enum {
 };
 
 #define FLITE_SD_PAD_SINK      0
-#define FLITE_SD_PAD_SOURCE    1
-#define FLITE_SD_PADS_NUM      2
+#define FLITE_SD_PAD_SOURCE_DMA        1
+#define FLITE_SD_PAD_SOURCE_ISP        2
+#define FLITE_SD_PADS_NUM      3
 
 struct flite_variant {
        unsigned short max_width;
@@ -104,6 +105,7 @@ struct flite_buffer {
  * @subdev: FIMC-LITE subdev
  * @vd_pad: media (sink) pad for the capture video node
  * @subdev_pads: the subdev media pads
+ * @sensor: sensor subdev attached to FIMC-LITE directly or through MIPI-CSIS
  * @ctrl_handler: v4l2 control handler
  * @test_pattern: test pattern controls
  * @index: FIMC-LITE platform device index
@@ -139,6 +141,7 @@ struct fimc_lite {
        struct v4l2_subdev      subdev;
        struct media_pad        vd_pad;
        struct media_pad        subdev_pads[FLITE_SD_PADS_NUM];
+       struct v4l2_subdev      *sensor;
        struct v4l2_ctrl_handler ctrl_handler;
        struct v4l2_ctrl        *test_pattern;
        u32                     index;
index 1d21da4bd24be130dbcdd2b15032ff198390804a..1d57f3b87aa361a2e5a3e6a73641670eb7b91342 100644 (file)
@@ -300,7 +300,7 @@ static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh,
 static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
 {
        struct fimc_dev *fimc = ctx->fimc_dev;
-       struct fimc_variant *variant = fimc->variant;
+       const struct fimc_variant *variant = fimc->variant;
        struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
        struct fimc_fmt *fmt;
        u32 max_w, mod_x, mod_y;
index 1bd5678cfeb9d13f4bfd4b1dc0f7ffccac5ce33b..8b43f982c12d512c8fa409d3f9c7ae3dc6eba835 100644 (file)
@@ -62,16 +62,17 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
                sd = media_entity_to_v4l2_subdev(pad->entity);
 
                switch (sd->grp_id) {
-               case SENSOR_GROUP_ID:
+               case GRP_ID_FIMC_IS_SENSOR:
+               case GRP_ID_SENSOR:
                        p->subdevs[IDX_SENSOR] = sd;
                        break;
-               case CSIS_GROUP_ID:
+               case GRP_ID_CSIS:
                        p->subdevs[IDX_CSIS] = sd;
                        break;
-               case FLITE_GROUP_ID:
+               case GRP_ID_FLITE:
                        p->subdevs[IDX_FLITE] = sd;
                        break;
-               case FIMC_GROUP_ID:
+               case GRP_ID_FIMC:
                        /* No need to control FIMC subdev through subdev ops */
                        break;
                default:
@@ -269,7 +270,7 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
                return ERR_PTR(-EPROBE_DEFER);
        }
        v4l2_set_subdev_hostdata(sd, s_info);
-       sd->grp_id = SENSOR_GROUP_ID;
+       sd->grp_id = GRP_ID_SENSOR;
 
        v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
                  s_info->pdata.board_info->type);
@@ -351,7 +352,7 @@ static int fimc_register_callback(struct device *dev, void *p)
                return 0;
 
        sd = &fimc->vid_cap.subdev;
-       sd->grp_id = FIMC_GROUP_ID;
+       sd->grp_id = GRP_ID_FIMC;
        v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops);
 
        ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
@@ -374,7 +375,7 @@ static int fimc_lite_register_callback(struct device *dev, void *p)
        if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS)
                return 0;
 
-       fimc->subdev.grp_id = FLITE_GROUP_ID;
+       fimc->subdev.grp_id = GRP_ID_FLITE;
        v4l2_set_subdev_hostdata(&fimc->subdev, (void *)&fimc_pipeline_ops);
 
        ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev);
@@ -404,7 +405,7 @@ static int csis_register_callback(struct device *dev, void *p)
        v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
 
        id = pdev->id < 0 ? 0 : pdev->id;
-       sd->grp_id = CSIS_GROUP_ID;
+       sd->grp_id = GRP_ID_CSIS;
 
        ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
        if (!ret)
@@ -602,7 +603,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
                source = &fimc->subdev.entity;
                sink = &fimc->vfd.entity;
                /* FIMC-LITE's subdev and video node */
-               ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
+               ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_DMA,
                                               sink, 0, flags);
                if (ret)
                        break;
@@ -658,7 +659,8 @@ static int fimc_md_create_links(struct fimc_md *fmd)
                                 "but s5p-csis module is not loaded!\n"))
                                return -EINVAL;
 
-                       ret = media_entity_create_link(&sensor->entity, 0,
+                       pad = sensor->entity.num_pads - 1;
+                       ret = media_entity_create_link(&sensor->entity, pad,
                                              &csis->entity, CSIS_PAD_SINK,
                                              MEDIA_LNK_FL_IMMUTABLE |
                                              MEDIA_LNK_FL_ENABLED);
@@ -828,11 +830,11 @@ static int fimc_md_link_notify(struct media_pad *source,
        sd = media_entity_to_v4l2_subdev(sink->entity);
 
        switch (sd->grp_id) {
-       case FLITE_GROUP_ID:
+       case GRP_ID_FLITE:
                fimc_lite = v4l2_get_subdevdata(sd);
                pipeline = &fimc_lite->pipeline;
                break;
-       case FIMC_GROUP_ID:
+       case GRP_ID_FIMC:
                fimc = v4l2_get_subdevdata(sd);
                pipeline = &fimc->pipeline;
                break;
index 2d8d41d8262042c156d834d24b8649cff0f268b1..da7d9922cf5892bd339132878acfcbd226c50de8 100644 (file)
 #include "mipi-csis.h"
 
 /* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */
-#define SENSOR_GROUP_ID                (1 << 8)
-#define CSIS_GROUP_ID          (1 << 9)
-#define WRITEBACK_GROUP_ID     (1 << 10)
-#define FIMC_GROUP_ID          (1 << 11)
-#define FLITE_GROUP_ID         (1 << 12)
+#define GRP_ID_SENSOR          (1 << 8)
+#define GRP_ID_FIMC_IS_SENSOR  (1 << 9)
+#define GRP_ID_WRITEBACK       (1 << 10)
+#define GRP_ID_CSIS            (1 << 11)
+#define GRP_ID_FIMC            (1 << 12)
+#define GRP_ID_FLITE           (1 << 13)
+#define GRP_ID_FIMC_IS         (1 << 14)
 
 #define FIMC_MAX_SENSORS       8
 #define FIMC_MAX_CAMCLKS       2
index 2c9d0c06c9e8faef0be5645508ad8495b9356844..c05d0444192f72e2e97cdf8bd21d5607812f5626 100644 (file)
@@ -44,9 +44,9 @@ static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
        u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL;
 
        if (ctx->hflip)
-               flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
-       if (ctx->vflip)
                flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR;
+       if (ctx->vflip)
+               flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
 
        if (ctx->rotation <= 90)
                return flip;
@@ -59,9 +59,9 @@ static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
        u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL;
 
        if (ctx->hflip)
-               flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
-       if (ctx->vflip)
                flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR;
+       if (ctx->vflip)
+               flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
 
        if (ctx->rotation <= 90)
                return flip;
@@ -312,7 +312,7 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
 void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
 {
        struct fimc_dev *dev = ctx->fimc_dev;
-       struct fimc_variant *variant = dev->variant;
+       const struct fimc_variant *variant = dev->variant;
        struct fimc_scaler *sc = &ctx->scaler;
        u32 cfg;
 
@@ -344,30 +344,31 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
        }
 }
 
-void fimc_hw_en_capture(struct fimc_ctx *ctx)
+void fimc_hw_enable_capture(struct fimc_ctx *ctx)
 {
        struct fimc_dev *dev = ctx->fimc_dev;
+       u32 cfg;
 
-       u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
-
-       if (ctx->out_path == FIMC_IO_DMA) {
-               /* one shot mode */
-               cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE |
-                       FIMC_REG_CIIMGCPT_IMGCPTEN;
-       } else {
-               /* Continuous frame capture mode (freerun). */
-               cfg &= ~(FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE |
-                        FIMC_REG_CIIMGCPT_CPT_FRMOD_CNT);
-               cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
-       }
+       cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
+       cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE;
 
        if (ctx->scaler.enabled)
                cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
+       else
+               cfg &= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
 
        cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
        writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
 }
 
+void fimc_hw_disable_capture(struct fimc_dev *dev)
+{
+       u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
+       cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN |
+                FIMC_REG_CIIMGCPT_IMGCPTEN_SC);
+       writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
+}
+
 void fimc_hw_set_effect(struct fimc_ctx *ctx)
 {
        struct fimc_dev *dev = ctx->fimc_dev;
@@ -737,13 +738,6 @@ void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
        writel(cfg, dev->regs + FIMC_REG_MSCTRL);
 }
 
-void fimc_hw_dis_capture(struct fimc_dev *dev)
-{
-       u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
-       cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN | FIMC_REG_CIIMGCPT_IMGCPTEN_SC);
-       writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
-}
-
 /* Return an index to the buffer actually being written. */
 s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
 {
@@ -776,13 +770,13 @@ s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
 void fimc_activate_capture(struct fimc_ctx *ctx)
 {
        fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
-       fimc_hw_en_capture(ctx);
+       fimc_hw_enable_capture(ctx);
 }
 
 void fimc_deactivate_capture(struct fimc_dev *fimc)
 {
        fimc_hw_en_lastirq(fimc, true);
-       fimc_hw_dis_capture(fimc);
+       fimc_hw_disable_capture(fimc);
        fimc_hw_enable_scaler(fimc, false);
        fimc_hw_en_lastirq(fimc, false);
 }
index b6abfc7b72ace7472c7caea9d398500f3402be08..f3e0b78a37366cf3a96abaf261b2d53a95eb68a6 100644 (file)
@@ -287,7 +287,7 @@ void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable);
 void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
 void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
 void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
-void fimc_hw_en_capture(struct fimc_ctx *ctx);
+void fimc_hw_enable_capture(struct fimc_ctx *ctx);
 void fimc_hw_set_effect(struct fimc_ctx *ctx);
 void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx);
 void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
@@ -306,7 +306,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
 void fimc_hw_clear_irq(struct fimc_dev *dev);
 void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on);
 void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on);
-void fimc_hw_dis_capture(struct fimc_dev *dev);
+void fimc_hw_disable_capture(struct fimc_dev *dev);
 s32 fimc_hw_get_frame_index(struct fimc_dev *dev);
 s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev);
 void fimc_activate_capture(struct fimc_ctx *ctx);
index 4c961b1b68e6004ab1dd98d578b0e6cc407e97f9..8a06f1402f378c0bc56d58ab0b446981a49ecfc0 100644 (file)
@@ -220,6 +220,18 @@ static const struct csis_pix_format s5pcsis_formats[] = {
                .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
                .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
                .data_alignment = 32,
+       }, {
+               .code = V4L2_MBUS_FMT_SGRBG8_1X8,
+               .fmt_reg = S5PCSIS_CFG_FMT_RAW8,
+               .data_alignment = 24,
+       }, {
+               .code = V4L2_MBUS_FMT_SGRBG10_1X10,
+               .fmt_reg = S5PCSIS_CFG_FMT_RAW10,
+               .data_alignment = 24,
+       }, {
+               .code = V4L2_MBUS_FMT_SGRBG12_1X12,
+               .fmt_reg = S5PCSIS_CFG_FMT_RAW12,
+               .data_alignment = 24,
        }
 };
 
@@ -261,7 +273,8 @@ static void s5pcsis_reset(struct csis_state *state)
 
 static void s5pcsis_system_enable(struct csis_state *state, int on)
 {
-       u32 val;
+       struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data;
+       u32 val, mask;
 
        val = s5pcsis_read(state, S5PCSIS_CTRL);
        if (on)
@@ -271,10 +284,11 @@ static void s5pcsis_system_enable(struct csis_state *state, int on)
        s5pcsis_write(state, S5PCSIS_CTRL, val);
 
        val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
-       if (on)
-               val |= S5PCSIS_DPHYCTRL_ENABLE;
-       else
-               val &= ~S5PCSIS_DPHYCTRL_ENABLE;
+       val &= ~S5PCSIS_DPHYCTRL_ENABLE;
+       if (on) {
+               mask = (1 << (pdata->lanes + 1)) - 1;
+               val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
+       }
        s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
 }
 
@@ -369,6 +383,30 @@ err:
        return -ENXIO;
 }
 
+static void dump_regs(struct csis_state *state, const char *label)
+{
+       struct {
+               u32 offset;
+               const char * const name;
+       } registers[] = {
+               { 0x00, "CTRL" },
+               { 0x04, "DPHYCTRL" },
+               { 0x08, "CONFIG" },
+               { 0x0c, "DPHYSTS" },
+               { 0x10, "INTMSK" },
+               { 0x2c, "RESOL" },
+               { 0x38, "SDW_CONFIG" },
+       };
+       u32 i;
+
+       v4l2_info(&state->sd, "--- %s ---\n", label);
+
+       for (i = 0; i < ARRAY_SIZE(registers); i++) {
+               u32 cfg = s5pcsis_read(state, registers[i].offset);
+               v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg);
+       }
+}
+
 static void s5pcsis_start_stream(struct csis_state *state)
 {
        s5pcsis_reset(state);
@@ -401,12 +439,12 @@ static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
 
        spin_lock_irqsave(&state->slock, flags);
 
-       for (i--; i >= 0; i--)
-               if (state->events[i].counter >= 0)
+       for (i--; i >= 0; i--) {
+               if (state->events[i].counter > 0 || debug)
                        v4l2_info(&state->sd, "%s events: %d\n",
                                  state->events[i].name,
                                  state->events[i].counter);
-
+       }
        spin_unlock_irqrestore(&state->slock, flags);
 }
 
@@ -569,7 +607,11 @@ static int s5pcsis_log_status(struct v4l2_subdev *sd)
 {
        struct csis_state *state = sd_to_csis_state(sd);
 
+       mutex_lock(&state->lock);
        s5pcsis_log_counters(state, true);
+       if (debug && (state->flags & ST_POWERED))
+               dump_regs(state, __func__);
+       mutex_unlock(&state->lock);
        return 0;
 }
 
index 716d4846f8bdba7cadf04e992fc36ece0ffac226..4597342cdfbe9f9bf58c23a0e6189605cf1bf313 100644 (file)
@@ -338,7 +338,7 @@ static int __devinit sii9234_probe(struct i2c_client *client,
        }
 
        ctx->gpio_n_reset = pdata->gpio_n_reset;
-       ret = gpio_request(ctx->gpio_n_reset, "MHL_RST");
+       ret = devm_gpio_request(dev, ctx->gpio_n_reset, "MHL_RST");
        if (ret) {
                dev_err(dev, "failed to acquire MHL_RST gpio\n");
                return ret;
@@ -370,7 +370,6 @@ fail_pm_get:
 
 fail_pm:
        pm_runtime_disable(dev);
-       gpio_free(ctx->gpio_n_reset);
 
 fail:
        dev_err(dev, "probe failed\n");
@@ -381,11 +380,8 @@ fail:
 static int __devexit sii9234_remove(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-       struct sii9234_context *ctx = sd_to_context(sd);
 
        pm_runtime_disable(dev);
-       gpio_free(ctx->gpio_n_reset);
 
        dev_info(dev, "remove successful\n");
 
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
new file mode 100644 (file)
index 0000000..a018676
--- /dev/null
@@ -0,0 +1,1266 @@
+/*
+ * sh-mobile VEU mem2mem driver
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define VEU_STR 0x00 /* start register */
+#define VEU_SWR 0x10 /* src: line length */
+#define VEU_SSR 0x14 /* src: image size */
+#define VEU_SAYR 0x18 /* src: y/rgb plane address */
+#define VEU_SACR 0x1c /* src: c plane address */
+#define VEU_BSSR 0x20 /* bundle mode register */
+#define VEU_EDWR 0x30 /* dst: line length */
+#define VEU_DAYR 0x34 /* dst: y/rgb plane address */
+#define VEU_DACR 0x38 /* dst: c plane address */
+#define VEU_TRCR 0x50 /* transform control */
+#define VEU_RFCR 0x54 /* resize scale */
+#define VEU_RFSR 0x58 /* resize clip */
+#define VEU_ENHR 0x5c /* enhance */
+#define VEU_FMCR 0x70 /* filter mode */
+#define VEU_VTCR 0x74 /* lowpass vertical */
+#define VEU_HTCR 0x78 /* lowpass horizontal */
+#define VEU_APCR 0x80 /* color match */
+#define VEU_ECCR 0x84 /* color replace */
+#define VEU_AFXR 0x90 /* fixed mode */
+#define VEU_SWPR 0x94 /* swap */
+#define VEU_EIER 0xa0 /* interrupt mask */
+#define VEU_EVTR 0xa4 /* interrupt event */
+#define VEU_STAR 0xb0 /* status */
+#define VEU_BSRR 0xb4 /* reset */
+
+#define VEU_MCR00 0x200 /* color conversion matrix coefficient 00 */
+#define VEU_MCR01 0x204 /* color conversion matrix coefficient 01 */
+#define VEU_MCR02 0x208 /* color conversion matrix coefficient 02 */
+#define VEU_MCR10 0x20c /* color conversion matrix coefficient 10 */
+#define VEU_MCR11 0x210 /* color conversion matrix coefficient 11 */
+#define VEU_MCR12 0x214 /* color conversion matrix coefficient 12 */
+#define VEU_MCR20 0x218 /* color conversion matrix coefficient 20 */
+#define VEU_MCR21 0x21c /* color conversion matrix coefficient 21 */
+#define VEU_MCR22 0x220 /* color conversion matrix coefficient 22 */
+#define VEU_COFFR 0x224 /* color conversion offset */
+#define VEU_CBR   0x228 /* color conversion clip */
+
+/*
+ * 4092x4092 max size is the normal case. In some cases it can be reduced to
+ * 2048x2048, in other cases it can be 4092x8188 or even 8188x8188.
+ */
+#define MAX_W 4092
+#define MAX_H 4092
+#define MIN_W 8
+#define MIN_H 8
+#define ALIGN_W 4
+
+/* 3 buffers of 2048 x 1536 - 3 megapixels @ 16bpp */
+#define VIDEO_MEM_LIMIT ALIGN(2048 * 1536 * 2 * 3, 1024 * 1024)
+
+#define MEM2MEM_DEF_TRANSLEN 1
+
+struct sh_veu_dev;
+
+struct sh_veu_file {
+       struct sh_veu_dev *veu_dev;
+       bool cfg_needed;
+};
+
+struct sh_veu_format {
+       char *name;
+       u32 fourcc;
+       unsigned int depth;
+       unsigned int ydepth;
+};
+
+/* video data format */
+struct sh_veu_vfmt {
+       /* Replace with v4l2_rect */
+       struct v4l2_rect                frame;
+       unsigned int                    bytesperline;
+       unsigned int                    offset_y;
+       unsigned int                    offset_c;
+       const struct sh_veu_format      *fmt;
+};
+
+struct sh_veu_dev {
+       struct v4l2_device v4l2_dev;
+       struct video_device vdev;
+       struct v4l2_m2m_dev *m2m_dev;
+       struct device *dev;
+       struct v4l2_m2m_ctx *m2m_ctx;
+       struct sh_veu_vfmt vfmt_out;
+       struct sh_veu_vfmt vfmt_in;
+       /* Only single user per direction so far */
+       struct sh_veu_file *capture;
+       struct sh_veu_file *output;
+       struct mutex fop_lock;
+       void __iomem *base;
+       struct vb2_alloc_ctx *alloc_ctx;
+       spinlock_t lock;
+       bool is_2h;
+       unsigned int xaction;
+       bool aborting;
+};
+
+enum sh_veu_fmt_idx {
+       SH_VEU_FMT_NV12,
+       SH_VEU_FMT_NV16,
+       SH_VEU_FMT_NV24,
+       SH_VEU_FMT_RGB332,
+       SH_VEU_FMT_RGB444,
+       SH_VEU_FMT_RGB565,
+       SH_VEU_FMT_RGB666,
+       SH_VEU_FMT_RGB24,
+};
+
+#define VGA_WIDTH      640
+#define VGA_HEIGHT     480
+
+#define DEFAULT_IN_WIDTH       VGA_WIDTH
+#define DEFAULT_IN_HEIGHT      VGA_HEIGHT
+#define DEFAULT_IN_FMTIDX      SH_VEU_FMT_NV12
+#define DEFAULT_OUT_WIDTH      VGA_WIDTH
+#define DEFAULT_OUT_HEIGHT     VGA_HEIGHT
+#define DEFAULT_OUT_FMTIDX     SH_VEU_FMT_RGB565
+
+/*
+ * Alignment: Y-plane should be 4-byte aligned for NV12 and NV16, and 8-byte
+ * aligned for NV24.
+ */
+static const struct sh_veu_format sh_veu_fmt[] = {
+       [SH_VEU_FMT_NV12]   = { .ydepth = 8, .depth = 12, .name = "NV12", .fourcc = V4L2_PIX_FMT_NV12 },
+       [SH_VEU_FMT_NV16]   = { .ydepth = 8, .depth = 16, .name = "NV16", .fourcc = V4L2_PIX_FMT_NV16 },
+       [SH_VEU_FMT_NV24]   = { .ydepth = 8, .depth = 24, .name = "NV24", .fourcc = V4L2_PIX_FMT_NV24 },
+       [SH_VEU_FMT_RGB332] = { .ydepth = 8, .depth = 8, .name = "RGB332", .fourcc = V4L2_PIX_FMT_RGB332 },
+       [SH_VEU_FMT_RGB444] = { .ydepth = 16, .depth = 16, .name = "RGB444", .fourcc = V4L2_PIX_FMT_RGB444 },
+       [SH_VEU_FMT_RGB565] = { .ydepth = 16, .depth = 16, .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565 },
+       [SH_VEU_FMT_RGB666] = { .ydepth = 32, .depth = 32, .name = "BGR666", .fourcc = V4L2_PIX_FMT_BGR666 },
+       [SH_VEU_FMT_RGB24]  = { .ydepth = 24, .depth = 24, .name = "RGB24", .fourcc = V4L2_PIX_FMT_RGB24 },
+};
+
+#define DEFAULT_IN_VFMT (struct sh_veu_vfmt){                                          \
+       .frame = {                                                                      \
+               .width = VGA_WIDTH,                                                     \
+               .height = VGA_HEIGHT,                                                   \
+       },                                                                              \
+       .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_IN_FMTIDX].ydepth) >> 3,        \
+       .fmt = &sh_veu_fmt[DEFAULT_IN_FMTIDX],                                          \
+}
+
+#define DEFAULT_OUT_VFMT (struct sh_veu_vfmt){                                         \
+       .frame = {                                                                      \
+               .width = VGA_WIDTH,                                                     \
+               .height = VGA_HEIGHT,                                                   \
+       },                                                                              \
+       .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_OUT_FMTIDX].ydepth) >> 3,       \
+       .fmt = &sh_veu_fmt[DEFAULT_OUT_FMTIDX],                                         \
+}
+
+/*
+ * TODO: add support for further output formats:
+ *     SH_VEU_FMT_NV12,
+ *     SH_VEU_FMT_NV16,
+ *     SH_VEU_FMT_NV24,
+ *     SH_VEU_FMT_RGB332,
+ *     SH_VEU_FMT_RGB444,
+ *     SH_VEU_FMT_RGB666,
+ *     SH_VEU_FMT_RGB24,
+ */
+
+static const int sh_veu_fmt_out[] = {
+       SH_VEU_FMT_RGB565,
+};
+
+/*
+ * TODO: add support for further input formats:
+ *     SH_VEU_FMT_NV16,
+ *     SH_VEU_FMT_NV24,
+ *     SH_VEU_FMT_RGB565,
+ *     SH_VEU_FMT_RGB666,
+ *     SH_VEU_FMT_RGB24,
+ */
+static const int sh_veu_fmt_in[] = {
+       SH_VEU_FMT_NV12,
+};
+
+static enum v4l2_colorspace sh_veu_4cc2cspace(u32 fourcc)
+{
+       switch (fourcc) {
+       default:
+               BUG();
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV24:
+               return V4L2_COLORSPACE_JPEG;
+       case V4L2_PIX_FMT_RGB332:
+       case V4L2_PIX_FMT_RGB444:
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_BGR666:
+       case V4L2_PIX_FMT_RGB24:
+               return V4L2_COLORSPACE_SRGB;
+       }
+}
+
+static u32 sh_veu_reg_read(struct sh_veu_dev *veu, unsigned int reg)
+{
+       return ioread32(veu->base + reg);
+}
+
+static void sh_veu_reg_write(struct sh_veu_dev *veu, unsigned int reg,
+                            u32 value)
+{
+       iowrite32(value, veu->base + reg);
+}
+
+               /* ========== mem2mem callbacks ========== */
+
+static void sh_veu_job_abort(void *priv)
+{
+       struct sh_veu_dev *veu = priv;
+
+       /* Will cancel the transaction in the next interrupt handler */
+       veu->aborting = true;
+}
+
+static void sh_veu_lock(void *priv)
+{
+       struct sh_veu_dev *veu = priv;
+
+       mutex_lock(&veu->fop_lock);
+}
+
+static void sh_veu_unlock(void *priv)
+{
+       struct sh_veu_dev *veu = priv;
+
+       mutex_unlock(&veu->fop_lock);
+}
+
+static void sh_veu_process(struct sh_veu_dev *veu,
+                          struct vb2_buffer *src_buf,
+                          struct vb2_buffer *dst_buf)
+{
+       dma_addr_t addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+
+       sh_veu_reg_write(veu, VEU_DAYR, addr + veu->vfmt_out.offset_y);
+       sh_veu_reg_write(veu, VEU_DACR, veu->vfmt_out.offset_c ?
+                        addr + veu->vfmt_out.offset_c : 0);
+       dev_dbg(veu->dev, "%s(): dst base %lx, y: %x, c: %x\n", __func__,
+               (unsigned long)addr,
+               veu->vfmt_out.offset_y, veu->vfmt_out.offset_c);
+
+       addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+       sh_veu_reg_write(veu, VEU_SAYR, addr + veu->vfmt_in.offset_y);
+       sh_veu_reg_write(veu, VEU_SACR, veu->vfmt_in.offset_c ?
+                        addr + veu->vfmt_in.offset_c : 0);
+       dev_dbg(veu->dev, "%s(): src base %lx, y: %x, c: %x\n", __func__,
+               (unsigned long)addr,
+               veu->vfmt_in.offset_y, veu->vfmt_in.offset_c);
+
+       sh_veu_reg_write(veu, VEU_STR, 1);
+
+       sh_veu_reg_write(veu, VEU_EIER, 1); /* enable interrupt in VEU */
+}
+
+/**
+ * sh_veu_device_run() - prepares and starts the device
+ *
+ * This will be called by the framework when it decides to schedule a particular
+ * instance.
+ */
+static void sh_veu_device_run(void *priv)
+{
+       struct sh_veu_dev *veu = priv;
+       struct vb2_buffer *src_buf, *dst_buf;
+
+       src_buf = v4l2_m2m_next_src_buf(veu->m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(veu->m2m_ctx);
+
+       if (src_buf && dst_buf)
+               sh_veu_process(veu, src_buf, dst_buf);
+}
+
+               /* ========== video ioctls ========== */
+
+static bool sh_veu_is_streamer(struct sh_veu_dev *veu, struct sh_veu_file *veu_file,
+                              enum v4l2_buf_type type)
+{
+       return (type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+               veu_file == veu->capture) ||
+               (type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+                veu_file == veu->output);
+}
+
+static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
+                            struct vb2_queue *dst_vq);
+
+/*
+ * It is not unusual to have video nodes open()ed multiple times. While some
+ * V4L2 operations are non-intrusive, like querying formats and various
+ * parameters, others, like setting formats, starting and stopping streaming,
+ * queuing and dequeuing buffers, directly affect hardware configuration and /
+ * or execution. This function verifies availability of the requested interface
+ * and, if available, reserves it for the requesting user.
+ */
+static int sh_veu_stream_init(struct sh_veu_dev *veu, struct sh_veu_file *veu_file,
+                             enum v4l2_buf_type type)
+{
+       struct sh_veu_file **stream;
+
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               stream = &veu->capture;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               stream = &veu->output;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (*stream == veu_file)
+               return 0;
+
+       if (*stream)
+               return -EBUSY;
+
+       *stream = veu_file;
+
+       return 0;
+}
+
+static int sh_veu_context_init(struct sh_veu_dev *veu)
+{
+       if (veu->m2m_ctx)
+               return 0;
+
+       veu->m2m_ctx = v4l2_m2m_ctx_init(veu->m2m_dev, veu,
+                                        sh_veu_queue_init);
+
+       if (IS_ERR(veu->m2m_ctx))
+               return PTR_ERR(veu->m2m_ctx);
+
+       return 0;
+}
+
+static int sh_veu_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strlcpy(cap->driver, "sh-veu", sizeof(cap->driver));
+       strlcpy(cap->card, "sh-mobile VEU", sizeof(cap->card));
+       strlcpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+static int sh_veu_enum_fmt(struct v4l2_fmtdesc *f, const int *fmt, int fmt_num)
+{
+       if (f->index >= fmt_num)
+               return -EINVAL;
+
+       strlcpy(f->description, sh_veu_fmt[fmt[f->index]].name, sizeof(f->description));
+       f->pixelformat = sh_veu_fmt[fmt[f->index]].fourcc;
+       return 0;
+}
+
+static int sh_veu_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return sh_veu_enum_fmt(f, sh_veu_fmt_out, ARRAY_SIZE(sh_veu_fmt_out));
+}
+
+static int sh_veu_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return sh_veu_enum_fmt(f, sh_veu_fmt_in, ARRAY_SIZE(sh_veu_fmt_in));
+}
+
+static struct sh_veu_vfmt *sh_veu_get_vfmt(struct sh_veu_dev *veu,
+                                          enum v4l2_buf_type type)
+{
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return &veu->vfmt_out;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               return &veu->vfmt_in;
+       default:
+               return NULL;
+       }
+}
+
+static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
+{
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct sh_veu_dev *veu = veu_file->veu_dev;
+       struct sh_veu_vfmt *vfmt;
+
+       vfmt = sh_veu_get_vfmt(veu, f->type);
+
+       pix->width              = vfmt->frame.width;
+       pix->height             = vfmt->frame.height;
+       pix->field              = V4L2_FIELD_NONE;
+       pix->pixelformat        = vfmt->fmt->fourcc;
+       pix->colorspace         = sh_veu_4cc2cspace(pix->pixelformat);
+       pix->bytesperline       = vfmt->bytesperline;
+       pix->sizeimage          = vfmt->bytesperline * pix->height *
+               vfmt->fmt->depth / vfmt->fmt->ydepth;
+       pix->priv               = 0;
+       dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
+               f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
+
+       return 0;
+}
+
+static int sh_veu_g_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return sh_veu_g_fmt(priv, f);
+}
+
+static int sh_veu_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return sh_veu_g_fmt(priv, f);
+}
+
+static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt)
+{
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       unsigned int y_bytes_used;
+
+       /*
+        * V4L2 specification suggests, that the driver should correct the
+        * format struct if any of the dimensions is unsupported
+        */
+       switch (pix->field) {
+       default:
+       case V4L2_FIELD_ANY:
+               pix->field = V4L2_FIELD_NONE;
+               /* fall through: continue handling V4L2_FIELD_NONE */
+       case V4L2_FIELD_NONE:
+               break;
+       }
+
+       v4l_bound_align_image(&pix->width, MIN_W, MAX_W, ALIGN_W,
+                             &pix->height, MIN_H, MAX_H, 0, 0);
+
+       y_bytes_used = (pix->width * fmt->ydepth) >> 3;
+
+       if (pix->bytesperline < y_bytes_used)
+               pix->bytesperline = y_bytes_used;
+       pix->sizeimage = pix->height * pix->bytesperline * fmt->depth / fmt->ydepth;
+
+       pix->pixelformat        = fmt->fourcc;
+       pix->colorspace         = sh_veu_4cc2cspace(pix->pixelformat);
+       pix->priv               = 0;
+
+       pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
+
+       return 0;
+}
+
+static const struct sh_veu_format *sh_veu_find_fmt(const struct v4l2_format *f)
+{
+       const int *fmt;
+       int i, n, dflt;
+
+       pr_debug("%s(%d;%d)\n", __func__, f->type, f->fmt.pix.field);
+
+       switch (f->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               fmt = sh_veu_fmt_out;
+               n = ARRAY_SIZE(sh_veu_fmt_out);
+               dflt = DEFAULT_OUT_FMTIDX;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       default:
+               fmt = sh_veu_fmt_in;
+               n = ARRAY_SIZE(sh_veu_fmt_in);
+               dflt = DEFAULT_IN_FMTIDX;
+               break;
+       }
+
+       for (i = 0; i < n; i++)
+               if (sh_veu_fmt[fmt[i]].fourcc == f->fmt.pix.pixelformat)
+                       return &sh_veu_fmt[fmt[i]];
+
+       return &sh_veu_fmt[dflt];
+}
+
+static int sh_veu_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       const struct sh_veu_format *fmt;
+
+       fmt = sh_veu_find_fmt(f);
+       if (!fmt)
+               /* wrong buffer type */
+               return -EINVAL;
+
+       return sh_veu_try_fmt(f, fmt);
+}
+
+static int sh_veu_try_fmt_vid_out(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       const struct sh_veu_format *fmt;
+
+       fmt = sh_veu_find_fmt(f);
+       if (!fmt)
+               /* wrong buffer type */
+               return -EINVAL;
+
+       return sh_veu_try_fmt(f, fmt);
+}
+
+static void sh_veu_colour_offset(struct sh_veu_dev *veu, struct sh_veu_vfmt *vfmt)
+{
+       /* dst_left and dst_top validity will be verified in CROP / COMPOSE */
+       unsigned int left = vfmt->frame.left & ~0x03;
+       unsigned int top = vfmt->frame.top;
+       dma_addr_t offset = ((left * veu->vfmt_out.fmt->depth) >> 3) +
+               top * veu->vfmt_out.bytesperline;
+       unsigned int y_line;
+
+       vfmt->offset_y = offset;
+
+       switch (vfmt->fmt->fourcc) {
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV24:
+               y_line = ALIGN(vfmt->frame.width, 16);
+               vfmt->offset_c = offset + y_line * vfmt->frame.height;
+               break;
+       case V4L2_PIX_FMT_RGB332:
+       case V4L2_PIX_FMT_RGB444:
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_BGR666:
+       case V4L2_PIX_FMT_RGB24:
+               vfmt->offset_c = 0;
+               break;
+       default:
+               BUG();
+       }
+}
+
+static int sh_veu_s_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
+{
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct sh_veu_dev *veu = veu_file->veu_dev;
+       struct sh_veu_vfmt *vfmt;
+       struct vb2_queue *vq;
+       int ret = sh_veu_context_init(veu);
+       if (ret < 0)
+               return ret;
+
+       vq = v4l2_m2m_get_vq(veu->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&veu_file->veu_dev->v4l2_dev, "%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       vfmt = sh_veu_get_vfmt(veu, f->type);
+       /* called after try_fmt(), hence vfmt != NULL. Implicit BUG_ON() below */
+
+       vfmt->fmt               = sh_veu_find_fmt(f);
+       /* vfmt->fmt != NULL following the same argument as above */
+       vfmt->frame.width       = pix->width;
+       vfmt->frame.height      = pix->height;
+       vfmt->bytesperline      = pix->bytesperline;
+
+       sh_veu_colour_offset(veu, vfmt);
+
+       /*
+        * We could also verify and require configuration only if any parameters
+        * actually have changed, but it is unlikely, that the user requests the
+        * same configuration several times without closing the device.
+        */
+       veu_file->cfg_needed = true;
+
+       dev_dbg(veu->dev,
+               "Setting format for type %d, wxh: %dx%d, fmt: %x\n",
+               f->type, pix->width, pix->height, vfmt->fmt->fourcc);
+
+       return 0;
+}
+
+static int sh_veu_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret = sh_veu_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+
+       return sh_veu_s_fmt(priv, f);
+}
+
+static int sh_veu_s_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret = sh_veu_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       return sh_veu_s_fmt(priv, f);
+}
+
+static int sh_veu_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct sh_veu_file *veu_file = priv;
+       struct sh_veu_dev *veu = veu_file->veu_dev;
+       int ret = sh_veu_context_init(veu);
+       if (ret < 0)
+               return ret;
+
+       ret = sh_veu_stream_init(veu, veu_file, reqbufs->type);
+       if (ret < 0)
+               return ret;
+
+       return v4l2_m2m_reqbufs(file, veu->m2m_ctx, reqbufs);
+}
+
+static int sh_veu_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *buf)
+{
+       struct sh_veu_file *veu_file = priv;
+
+       if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
+               return -EBUSY;
+
+       return v4l2_m2m_querybuf(file, veu_file->veu_dev->m2m_ctx, buf);
+}
+
+static int sh_veu_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct sh_veu_file *veu_file = priv;
+
+       dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type);
+       if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
+               return -EBUSY;
+
+       return v4l2_m2m_qbuf(file, veu_file->veu_dev->m2m_ctx, buf);
+}
+
+static int sh_veu_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct sh_veu_file *veu_file = priv;
+
+       dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type);
+       if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
+               return -EBUSY;
+
+       return v4l2_m2m_dqbuf(file, veu_file->veu_dev->m2m_ctx, buf);
+}
+
+static void sh_veu_calc_scale(struct sh_veu_dev *veu,
+                             int size_in, int size_out, int crop_out,
+                             u32 *mant, u32 *frac, u32 *rep)
+{
+       u32 fixpoint;
+
+       /* calculate FRAC and MANT */
+       *rep = *mant = *frac = 0;
+
+       if (size_in == size_out) {
+               if (crop_out != size_out)
+                       *mant = 1; /* needed for cropping */
+               return;
+       }
+
+       /* VEU2H special upscale */
+       if (veu->is_2h && size_out > size_in) {
+               u32 fixpoint = (4096 * size_in) / size_out;
+               *mant = fixpoint / 4096;
+               *frac = (fixpoint - (*mant * 4096)) & ~0x07;
+
+               switch (*frac) {
+               case 0x800:
+                       *rep = 1;
+                       break;
+               case 0x400:
+                       *rep = 3;
+                       break;
+               case 0x200:
+                       *rep = 7;
+                       break;
+               }
+               if (*rep)
+                       return;
+       }
+
+       fixpoint = (4096 * (size_in - 1)) / (size_out + 1);
+       *mant = fixpoint / 4096;
+       *frac = fixpoint - (*mant * 4096);
+
+       if (*frac & 0x07) {
+               /*
+                * FIXME: do we really have to round down twice in the
+                * up-scaling case?
+                */
+               *frac &= ~0x07;
+               if (size_out > size_in)
+                       *frac -= 8; /* round down if scaling up */
+               else
+                       *frac += 8; /* round up if scaling down */
+       }
+}
+
+static unsigned long sh_veu_scale_v(struct sh_veu_dev *veu,
+                                   int size_in, int size_out, int crop_out)
+{
+       u32 mant, frac, value, rep;
+
+       sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep);
+
+       /* set scale */
+       value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff0000) |
+               (((mant << 12) | frac) << 16);
+
+       sh_veu_reg_write(veu, VEU_RFCR, value);
+
+       /* set clip */
+       value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff0000) |
+               (((rep << 12) | crop_out) << 16);
+
+       sh_veu_reg_write(veu, VEU_RFSR, value);
+
+       return ALIGN((size_in * crop_out) / size_out, 4);
+}
+
+static unsigned long sh_veu_scale_h(struct sh_veu_dev *veu,
+                                   int size_in, int size_out, int crop_out)
+{
+       u32 mant, frac, value, rep;
+
+       sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep);
+
+       /* set scale */
+       value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff) |
+               (mant << 12) | frac;
+
+       sh_veu_reg_write(veu, VEU_RFCR, value);
+
+       /* set clip */
+       value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff) |
+               (rep << 12) | crop_out;
+
+       sh_veu_reg_write(veu, VEU_RFSR, value);
+
+       return ALIGN((size_in * crop_out) / size_out, 4);
+}
+
+static void sh_veu_configure(struct sh_veu_dev *veu)
+{
+       u32 src_width, src_stride, src_height;
+       u32 dst_width, dst_stride, dst_height;
+       u32 real_w, real_h;
+
+       /* reset VEU */
+       sh_veu_reg_write(veu, VEU_BSRR, 0x100);
+
+       src_width = veu->vfmt_in.frame.width;
+       src_height = veu->vfmt_in.frame.height;
+       src_stride = ALIGN(veu->vfmt_in.frame.width, 16);
+
+       dst_width = real_w = veu->vfmt_out.frame.width;
+       dst_height = real_h = veu->vfmt_out.frame.height;
+       /* Datasheet is unclear - whether it's always number of bytes or not */
+       dst_stride = veu->vfmt_out.bytesperline;
+
+       /*
+        * So far real_w == dst_width && real_h == dst_height, but it wasn't
+        * necessarily the case in the original vidix driver, so, it may change
+        * here in the future too.
+        */
+       src_width = sh_veu_scale_h(veu, src_width, real_w, dst_width);
+       src_height = sh_veu_scale_v(veu, src_height, real_h, dst_height);
+
+       sh_veu_reg_write(veu, VEU_SWR, src_stride);
+       sh_veu_reg_write(veu, VEU_SSR, src_width | (src_height << 16));
+       sh_veu_reg_write(veu, VEU_BSSR, 0); /* not using bundle mode */
+
+       sh_veu_reg_write(veu, VEU_EDWR, dst_stride);
+       sh_veu_reg_write(veu, VEU_DACR, 0); /* unused for RGB */
+
+       sh_veu_reg_write(veu, VEU_SWPR, 0x67);
+       sh_veu_reg_write(veu, VEU_TRCR, (6 << 16) | (0 << 14) | 2 | 4);
+
+       if (veu->is_2h) {
+               sh_veu_reg_write(veu, VEU_MCR00, 0x0cc5);
+               sh_veu_reg_write(veu, VEU_MCR01, 0x0950);
+               sh_veu_reg_write(veu, VEU_MCR02, 0x0000);
+
+               sh_veu_reg_write(veu, VEU_MCR10, 0x397f);
+               sh_veu_reg_write(veu, VEU_MCR11, 0x0950);
+               sh_veu_reg_write(veu, VEU_MCR12, 0x3ccd);
+
+               sh_veu_reg_write(veu, VEU_MCR20, 0x0000);
+               sh_veu_reg_write(veu, VEU_MCR21, 0x0950);
+               sh_veu_reg_write(veu, VEU_MCR22, 0x1023);
+
+               sh_veu_reg_write(veu, VEU_COFFR, 0x00800010);
+       }
+}
+
+static int sh_veu_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct sh_veu_file *veu_file = priv;
+
+       if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type))
+               return -EBUSY;
+
+       if (veu_file->cfg_needed) {
+               struct sh_veu_dev *veu = veu_file->veu_dev;
+               veu_file->cfg_needed = false;
+               sh_veu_configure(veu_file->veu_dev);
+               veu->xaction = 0;
+               veu->aborting = false;
+       }
+
+       return v4l2_m2m_streamon(file, veu_file->veu_dev->m2m_ctx, type);
+}
+
+static int sh_veu_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct sh_veu_file *veu_file = priv;
+
+       if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type))
+               return -EBUSY;
+
+       return v4l2_m2m_streamoff(file, veu_file->veu_dev->m2m_ctx, type);
+}
+
+static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = {
+       .vidioc_querycap        = sh_veu_querycap,
+
+       .vidioc_enum_fmt_vid_cap = sh_veu_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = sh_veu_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = sh_veu_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = sh_veu_s_fmt_vid_cap,
+
+       .vidioc_enum_fmt_vid_out = sh_veu_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_out   = sh_veu_g_fmt_vid_out,
+       .vidioc_try_fmt_vid_out = sh_veu_try_fmt_vid_out,
+       .vidioc_s_fmt_vid_out   = sh_veu_s_fmt_vid_out,
+
+       .vidioc_reqbufs         = sh_veu_reqbufs,
+       .vidioc_querybuf        = sh_veu_querybuf,
+
+       .vidioc_qbuf            = sh_veu_qbuf,
+       .vidioc_dqbuf           = sh_veu_dqbuf,
+
+       .vidioc_streamon        = sh_veu_streamon,
+       .vidioc_streamoff       = sh_veu_streamoff,
+};
+
+               /* ========== Queue operations ========== */
+
+static int sh_veu_queue_setup(struct vb2_queue *vq,
+                             const struct v4l2_format *f,
+                             unsigned int *nbuffers, unsigned int *nplanes,
+                             unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct sh_veu_dev *veu = vb2_get_drv_priv(vq);
+       struct sh_veu_vfmt *vfmt;
+       unsigned int size, count = *nbuffers;
+
+       if (f) {
+               const struct v4l2_pix_format *pix = &f->fmt.pix;
+               const struct sh_veu_format *fmt = sh_veu_find_fmt(f);
+               struct v4l2_format ftmp = *f;
+
+               if (fmt->fourcc != pix->pixelformat)
+                       return -EINVAL;
+               sh_veu_try_fmt(&ftmp, fmt);
+               if (ftmp.fmt.pix.width != pix->width ||
+                   ftmp.fmt.pix.height != pix->height)
+                       return -EINVAL;
+               size = pix->bytesperline ? pix->bytesperline * pix->height :
+                       pix->width * pix->height * fmt->depth >> 3;
+       } else {
+               vfmt = sh_veu_get_vfmt(veu, vq->type);
+               size = vfmt->bytesperline * vfmt->frame.height;
+       }
+
+       if (count < 2)
+               *nbuffers = count = 2;
+
+       if (size * count > VIDEO_MEM_LIMIT) {
+               count = VIDEO_MEM_LIMIT / size;
+               *nbuffers = count;
+       }
+
+       *nplanes = 1;
+       sizes[0] = size;
+       alloc_ctxs[0] = veu->alloc_ctx;
+
+       dev_dbg(veu->dev, "get %d buffer(s) of size %d each.\n", count, size);
+
+       return 0;
+}
+
+static int sh_veu_buf_prepare(struct vb2_buffer *vb)
+{
+       struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
+       struct sh_veu_vfmt *vfmt;
+       unsigned int sizeimage;
+
+       vfmt = sh_veu_get_vfmt(veu, vb->vb2_queue->type);
+       sizeimage = vfmt->bytesperline * vfmt->frame.height *
+               vfmt->fmt->depth / vfmt->fmt->ydepth;
+
+       if (vb2_plane_size(vb, 0) < sizeimage) {
+               dev_dbg(veu->dev, "%s data will not fit into plane (%lu < %u)\n",
+                       __func__, vb2_plane_size(vb, 0), sizeimage);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, sizeimage);
+
+       return 0;
+}
+
+static void sh_veu_buf_queue(struct vb2_buffer *vb)
+{
+       struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
+       dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->v4l2_buf.type);
+       v4l2_m2m_buf_queue(veu->m2m_ctx, vb);
+}
+
+static void sh_veu_wait_prepare(struct vb2_queue *q)
+{
+       sh_veu_unlock(vb2_get_drv_priv(q));
+}
+
+static void sh_veu_wait_finish(struct vb2_queue *q)
+{
+       sh_veu_lock(vb2_get_drv_priv(q));
+}
+
+static const struct vb2_ops sh_veu_qops = {
+       .queue_setup     = sh_veu_queue_setup,
+       .buf_prepare     = sh_veu_buf_prepare,
+       .buf_queue       = sh_veu_buf_queue,
+       .wait_prepare    = sh_veu_wait_prepare,
+       .wait_finish     = sh_veu_wait_finish,
+};
+
+static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
+                            struct vb2_queue *dst_vq)
+{
+       int ret;
+
+       memset(src_vq, 0, sizeof(*src_vq));
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->drv_priv = priv;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       src_vq->ops = &sh_veu_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+
+       ret = vb2_queue_init(src_vq);
+       if (ret < 0)
+               return ret;
+
+       memset(dst_vq, 0, sizeof(*dst_vq));
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->drv_priv = priv;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &sh_veu_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+
+       return vb2_queue_init(dst_vq);
+}
+
+               /* ========== File operations ========== */
+
+static int sh_veu_open(struct file *file)
+{
+       struct sh_veu_dev *veu = video_drvdata(file);
+       struct sh_veu_file *veu_file;
+
+       veu_file = kzalloc(sizeof(*veu_file), GFP_KERNEL);
+       if (!veu_file)
+               return -ENOMEM;
+
+       veu_file->veu_dev = veu;
+       veu_file->cfg_needed = true;
+
+       file->private_data = veu_file;
+
+       pm_runtime_get_sync(veu->dev);
+
+       dev_dbg(veu->dev, "Created instance %p\n", veu_file);
+
+       return 0;
+}
+
+static int sh_veu_release(struct file *file)
+{
+       struct sh_veu_dev *veu = video_drvdata(file);
+       struct sh_veu_file *veu_file = file->private_data;
+
+       dev_dbg(veu->dev, "Releasing instance %p\n", veu_file);
+
+       pm_runtime_put(veu->dev);
+
+       if (veu_file == veu->capture) {
+               veu->capture = NULL;
+               vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE));
+       }
+
+       if (veu_file == veu->output) {
+               veu->output = NULL;
+               vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT));
+       }
+
+       if (!veu->output && !veu->capture && veu->m2m_ctx) {
+               v4l2_m2m_ctx_release(veu->m2m_ctx);
+               veu->m2m_ctx = NULL;
+       }
+
+       kfree(veu_file);
+
+       return 0;
+}
+
+static unsigned int sh_veu_poll(struct file *file,
+                               struct poll_table_struct *wait)
+{
+       struct sh_veu_file *veu_file = file->private_data;
+
+       return v4l2_m2m_poll(file, veu_file->veu_dev->m2m_ctx, wait);
+}
+
+static int sh_veu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct sh_veu_file *veu_file = file->private_data;
+
+       return v4l2_m2m_mmap(file, veu_file->veu_dev->m2m_ctx, vma);
+}
+
+static const struct v4l2_file_operations sh_veu_fops = {
+       .owner          = THIS_MODULE,
+       .open           = sh_veu_open,
+       .release        = sh_veu_release,
+       .poll           = sh_veu_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = sh_veu_mmap,
+};
+
+static const struct video_device sh_veu_videodev = {
+       .name           = "sh-veu",
+       .fops           = &sh_veu_fops,
+       .ioctl_ops      = &sh_veu_ioctl_ops,
+       .minor          = -1,
+       .release        = video_device_release_empty,
+       .vfl_dir        = VFL_DIR_M2M,
+};
+
+static const struct v4l2_m2m_ops sh_veu_m2m_ops = {
+       .device_run     = sh_veu_device_run,
+       .job_abort      = sh_veu_job_abort,
+};
+
+static irqreturn_t sh_veu_bh(int irq, void *dev_id)
+{
+       struct sh_veu_dev *veu = dev_id;
+
+       if (veu->xaction == MEM2MEM_DEF_TRANSLEN || veu->aborting) {
+               v4l2_m2m_job_finish(veu->m2m_dev, veu->m2m_ctx);
+               veu->xaction = 0;
+       } else {
+               sh_veu_device_run(veu);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t sh_veu_isr(int irq, void *dev_id)
+{
+       struct sh_veu_dev *veu = dev_id;
+       struct vb2_buffer *dst;
+       struct vb2_buffer *src;
+       u32 status = sh_veu_reg_read(veu, VEU_EVTR);
+
+       /* bundle read mode not used */
+       if (!(status & 1))
+               return IRQ_NONE;
+
+       /* disable interrupt in VEU */
+       sh_veu_reg_write(veu, VEU_EIER, 0);
+       /* halt operation */
+       sh_veu_reg_write(veu, VEU_STR, 0);
+       /* ack int, write 0 to clear bits */
+       sh_veu_reg_write(veu, VEU_EVTR, status & ~1);
+
+       /* conversion completed */
+       dst = v4l2_m2m_dst_buf_remove(veu->m2m_ctx);
+       src = v4l2_m2m_src_buf_remove(veu->m2m_ctx);
+       if (!src || !dst)
+               return IRQ_NONE;
+
+       spin_lock(&veu->lock);
+       v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
+       v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
+       spin_unlock(&veu->lock);
+
+       veu->xaction++;
+
+       if (!veu->aborting)
+               return IRQ_WAKE_THREAD;
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit sh_veu_probe(struct platform_device *pdev)
+{
+       struct sh_veu_dev *veu;
+       struct resource *reg_res;
+       struct video_device *vdev;
+       int irq, ret;
+
+       reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+
+       if (!reg_res || irq <= 0) {
+               dev_err(&pdev->dev, "Insufficient VEU platform information.\n");
+               return -ENODEV;
+       }
+
+       veu = devm_kzalloc(&pdev->dev, sizeof(*veu), GFP_KERNEL);
+       if (!veu)
+               return -ENOMEM;
+
+       veu->is_2h = resource_size(reg_res) == 0x22c;
+
+       veu->base = devm_request_and_ioremap(&pdev->dev, reg_res);
+       if (!veu->base)
+               return -ENOMEM;
+
+       ret = devm_request_threaded_irq(&pdev->dev, irq, sh_veu_isr, sh_veu_bh,
+                                       0, "veu", veu);
+       if (ret < 0)
+               return ret;
+
+       ret = v4l2_device_register(&pdev->dev, &veu->v4l2_dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Error registering v4l2 device\n");
+               return ret;
+       }
+
+       vdev = &veu->vdev;
+
+       veu->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(veu->alloc_ctx)) {
+               ret = PTR_ERR(veu->alloc_ctx);
+               goto einitctx;
+       }
+
+       *vdev = sh_veu_videodev;
+       spin_lock_init(&veu->lock);
+       mutex_init(&veu->fop_lock);
+       vdev->lock = &veu->fop_lock;
+
+       video_set_drvdata(vdev, veu);
+
+       veu->dev        = &pdev->dev;
+       veu->vfmt_out   = DEFAULT_OUT_VFMT;
+       veu->vfmt_in    = DEFAULT_IN_VFMT;
+
+       veu->m2m_dev = v4l2_m2m_init(&sh_veu_m2m_ops);
+       if (IS_ERR(veu->m2m_dev)) {
+               ret = PTR_ERR(veu->m2m_dev);
+               v4l2_err(&veu->v4l2_dev, "Failed to init mem2mem device: %d\n", ret);
+               goto em2minit;
+       }
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_resume(&pdev->dev);
+
+       ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+       pm_runtime_suspend(&pdev->dev);
+       if (ret < 0)
+               goto evidreg;
+
+       return ret;
+
+evidreg:
+       pm_runtime_disable(&pdev->dev);
+       v4l2_m2m_release(veu->m2m_dev);
+em2minit:
+       vb2_dma_contig_cleanup_ctx(veu->alloc_ctx);
+einitctx:
+       v4l2_device_unregister(&veu->v4l2_dev);
+       return ret;
+}
+
+static int __devexit sh_veu_remove(struct platform_device *pdev)
+{
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+       struct sh_veu_dev *veu = container_of(v4l2_dev,
+                                             struct sh_veu_dev, v4l2_dev);
+
+       video_unregister_device(&veu->vdev);
+       pm_runtime_disable(&pdev->dev);
+       v4l2_m2m_release(veu->m2m_dev);
+       vb2_dma_contig_cleanup_ctx(veu->alloc_ctx);
+       v4l2_device_unregister(&veu->v4l2_dev);
+
+       return 0;
+}
+
+static struct platform_driver __refdata sh_veu_pdrv = {
+       .remove         = __devexit_p(sh_veu_remove),
+       .driver         = {
+               .name   = "sh_veu",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init sh_veu_init(void)
+{
+       return platform_driver_probe(&sh_veu_pdrv, sh_veu_probe);
+}
+
+static void __exit sh_veu_exit(void)
+{
+       platform_driver_unregister(&sh_veu_pdrv);
+}
+
+module_init(sh_veu_init);
+module_exit(sh_veu_exit);
+
+MODULE_DESCRIPTION("sh-mobile VEU mem2mem driver");
+MODULE_AUTHOR("Guennadi Liakhovetski, <g.liakhovetski@gmx.de>");
+MODULE_LICENSE("GPL v2");
index a1c87f0ceaabe0285ddd2d6b03dd3ead5303d22d..1039ae82401bfbe37dd4209815ed7c611231c967 100644 (file)
@@ -207,6 +207,7 @@ static void sh_vou_stream_start(struct sh_vou_device *vou_dev,
 #endif
 
        switch (vou_dev->pix.pixelformat) {
+       default:
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV16:
                row_coeff = 1;
@@ -595,9 +596,9 @@ static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std)
  */
 static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std)
 {
-       unsigned int best_err = UINT_MAX, best, width_max, height_max,
-               img_height_max;
-       int i, idx;
+       unsigned int best_err = UINT_MAX, best = geo->in_width,
+               width_max, height_max, img_height_max;
+       int i, idx = 0;
 
        if (std & V4L2_STD_525_60) {
                width_max = 858;
@@ -1091,7 +1092,7 @@ static irqreturn_t sh_vou_isr(int irq, void *dev_id)
        list_del(&vb->queue);
 
        vb->state = VIDEOBUF_DONE;
-       do_gettimeofday(&vb->ts);
+       v4l2_get_timestamp(&vb->ts);
        vb->field_count++;
        wake_up(&vb->done);
 
index 6274a91c25c74b711f30510a584056697edaa6ed..c8d748a31944e2d7ab2921a3c2b173f77124e789 100644 (file)
@@ -166,7 +166,7 @@ static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi)
                struct frame_buffer *buf = isi->active;
 
                list_del_init(&buf->list);
-               do_gettimeofday(&vb->v4l2_buf.timestamp);
+               v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
                vb->v4l2_buf.sequence = isi->sequence++;
                vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
        }
index 032b8c9097f99a7d35866a242b7897302b260860..674ded646b66fc257ffe141a5d919098faca44ed 100644 (file)
@@ -307,7 +307,7 @@ static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev,
        /* _init is used to debug races, see comment in mx1_camera_reqbufs() */
        list_del_init(&vb->queue);
        vb->state = VIDEOBUF_DONE;
-       do_gettimeofday(&vb->ts);
+       v4l2_get_timestamp(&vb->ts);
        vb->field_count++;
        wake_up(&vb->done);
 
index 791cd1d54a769c5321cca32d8fa7cc6665467324..28d5c84eef82a8c21ab34175ea83ed61bf975066 100644 (file)
@@ -559,7 +559,7 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
        dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
                vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
-       do_gettimeofday(&vb->v4l2_buf.timestamp);
+       v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
        vb->v4l2_buf.sequence++;
        vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 
@@ -922,7 +922,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
                pcdev->discard_size = icd->user_height * bytesperline;
                pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
                                pcdev->discard_size, &pcdev->discard_buffer_dma,
-                               GFP_KERNEL);
+                               GFP_ATOMIC);
                if (!pcdev->discard_buffer) {
                        spin_unlock_irqrestore(&pcdev->lock, flags);
                        return -ENOMEM;
@@ -1437,8 +1437,6 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
                return -EINVAL;
        }
 
-       /* FIXME: implement MX27 limits */
-
        /* limit to MX25 hardware capabilities */
        if (is_imx25_camera(pcdev)) {
                if (xlate->host_fmt->bits_per_sample <= 8)
@@ -1470,6 +1468,12 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
                        pix->sizeimage = soc_mbus_image_size(xlate->host_fmt,
                                                pix->bytesperline, pix->height);
                }
+       } else {
+               /*
+                * Width must be a multiple of 8 as requested by the CSI.
+                * (Table 39-2 in the i.MX27 Reference Manual).
+                */
+               pix->width &= ~0x7;
        }
 
        /* limit to sensor capabilities */
@@ -1600,7 +1604,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
                                vb2_get_plane_payload(vb, 0));
 
                list_del_init(&buf->internal.queue);
-               do_gettimeofday(&vb->v4l2_buf.timestamp);
+               v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
                vb->v4l2_buf.sequence = pcdev->frame_count;
                if (err)
                        vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
index 06d16de763773b54f11941a73e2806fcbad30dab..574d12522f956469e485b36f3640eac25b7ec9ef 100644 (file)
@@ -156,7 +156,7 @@ static void mx3_cam_dma_done(void *arg)
                struct mx3_camera_buffer *buf = to_mx3_vb(vb);
 
                list_del_init(&buf->queue);
-               do_gettimeofday(&vb->v4l2_buf.timestamp);
+               v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
                vb->v4l2_buf.field = mx3_cam->field;
                vb->v4l2_buf.sequence = mx3_cam->sequence++;
                vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
index 39a77f0b886066daa82aad7be5e3bf968d6309bf..8f9c1f44544c21d2628ee58ff3bf3dc6781896d2 100644 (file)
@@ -592,7 +592,7 @@ static void videobuf_done(struct omap1_cam_dev *pcdev,
                        suspend_capture(pcdev);
                }
                vb->state = result;
-               do_gettimeofday(&vb->ts);
+               v4l2_get_timestamp(&vb->ts);
                if (result != VIDEOBUF_ERROR)
                        vb->field_count++;
                wake_up(&vb->done);
index 3434ffe79c6ecc445a8b451dc2c55767b552c217..8ff961eec39d43d2ebe0c540f6ebbef80f0b2911 100644 (file)
@@ -681,7 +681,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
        /* _init is used to debug races, see comment in pxa_camera_reqbufs() */
        list_del_init(&vb->queue);
        vb->state = VIDEOBUF_DONE;
-       do_gettimeofday(&vb->ts);
+       v4l2_get_timestamp(&vb->ts);
        vb->field_count++;
        wake_up(&vb->done);
        dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s dequeud buffer (vb=0x%p)\n",
index 2d8861c0e8f2c23baae9908a0fdf2955e458ead3..9f021043cfe679d68ee1510da9005698698f6897 100644 (file)
@@ -516,7 +516,7 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
                pcdev->active = NULL;
 
        ret = sh_mobile_ceu_capture(pcdev);
-       do_gettimeofday(&vb->v4l2_buf.timestamp);
+       v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
        if (!ret) {
                vb->v4l2_buf.field = pcdev->field;
                vb->v4l2_buf.sequence = pcdev->sequence++;
@@ -572,7 +572,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
 
        ret = v4l2_subdev_call(csi2_sd, core, s_power, 1);
        if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
-               pm_runtime_put_sync(ici->v4l2_dev.dev);
+               pm_runtime_put(ici->v4l2_dev.dev);
                return ret;
        }
 
@@ -612,7 +612,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
        }
        spin_unlock_irq(&pcdev->lock);
 
-       pm_runtime_put_sync(ici->v4l2_dev.dev);
+       pm_runtime_put(ici->v4l2_dev.dev);
 
        dev_info(icd->parent,
                 "SuperH Mobile CEU driver detached from camera %d\n",
@@ -2088,15 +2088,13 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (!res || (int)irq <= 0) {
                dev_err(&pdev->dev, "Not enough CEU platform resources.\n");
-               err = -ENODEV;
-               goto exit;
+               return -ENODEV;
        }
 
-       pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
+       pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
        if (!pcdev) {
                dev_err(&pdev->dev, "Could not allocate pcdev\n");
-               err = -ENOMEM;
-               goto exit;
+               return -ENOMEM;
        }
 
        INIT_LIST_HEAD(&pcdev->capture);
@@ -2105,19 +2103,17 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
 
        pcdev->pdata = pdev->dev.platform_data;
        if (!pcdev->pdata) {
-               err = -EINVAL;
                dev_err(&pdev->dev, "CEU platform data not set.\n");
-               goto exit_kfree;
+               return -EINVAL;
        }
 
        pcdev->max_width = pcdev->pdata->max_width ? : 2560;
        pcdev->max_height = pcdev->pdata->max_height ? : 1920;
 
-       base = ioremap_nocache(res->start, resource_size(res));
+       base = devm_request_and_ioremap(&pdev->dev, res);
        if (!base) {
-               err = -ENXIO;
                dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n");
-               goto exit_kfree;
+               return -ENXIO;
        }
 
        pcdev->irq = irq;
@@ -2133,16 +2129,15 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
                                                  DMA_MEMORY_EXCLUSIVE);
                if (!err) {
                        dev_err(&pdev->dev, "Unable to declare CEU memory.\n");
-                       err = -ENXIO;
-                       goto exit_iounmap;
+                       return -ENXIO;
                }
 
                pcdev->video_limit = resource_size(res);
        }
 
        /* request irq */
-       err = request_irq(pcdev->irq, sh_mobile_ceu_irq, IRQF_DISABLED,
-                         dev_name(&pdev->dev), pcdev);
+       err = devm_request_irq(&pdev->dev, pcdev->irq, sh_mobile_ceu_irq,
+                              IRQF_DISABLED, dev_name(&pdev->dev), pcdev);
        if (err) {
                dev_err(&pdev->dev, "Unable to register CEU interrupt.\n");
                goto exit_release_mem;
@@ -2246,15 +2241,9 @@ exit_free_ctx:
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 exit_free_clk:
        pm_runtime_disable(&pdev->dev);
-       free_irq(pcdev->irq, pcdev);
 exit_release_mem:
        if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
                dma_release_declared_memory(&pdev->dev);
-exit_iounmap:
-       iounmap(base);
-exit_kfree:
-       kfree(pcdev);
-exit:
        return err;
 }
 
@@ -2267,10 +2256,8 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev)
 
        soc_camera_host_unregister(soc_host);
        pm_runtime_disable(&pdev->dev);
-       free_irq(pcdev->irq, pcdev);
        if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
                dma_release_declared_memory(&pdev->dev);
-       iounmap(pcdev->base);
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
        if (csi2_pdev && csi2_pdev->dev.driver) {
                struct module *csi2_drv = csi2_pdev->dev.driver->owner;
@@ -2279,7 +2266,6 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev)
                platform_device_put(csi2_pdev);
                module_put(csi2_drv);
        }
-       kfree(pcdev);
 
        return 0;
 }
index 05286500b4d432de590fa206070c2611bcb57a5a..c573be7026414fb6a54e9193aecbc14fd4637a3c 100644 (file)
@@ -318,23 +318,16 @@ static __devinit int sh_csi2_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       priv = kzalloc(sizeof(struct sh_csi2), GFP_KERNEL);
+       priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_csi2), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        priv->irq = irq;
 
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               dev_err(&pdev->dev, "CSI2 register region already claimed\n");
-               ret = -EBUSY;
-               goto ereqreg;
-       }
-
-       priv->base = ioremap(res->start, resource_size(res));
+       priv->base = devm_request_and_ioremap(&pdev->dev, res);
        if (!priv->base) {
-               ret = -ENXIO;
                dev_err(&pdev->dev, "Unable to ioremap CSI2 registers.\n");
-               goto eremap;
+               return -ENXIO;
        }
 
        priv->pdev = pdev;
@@ -357,11 +350,7 @@ static __devinit int sh_csi2_probe(struct platform_device *pdev)
        return 0;
 
 esdreg:
-       iounmap(priv->base);
-eremap:
-       release_mem_region(res->start, resource_size(res));
-ereqreg:
-       kfree(priv);
+       platform_set_drvdata(pdev, NULL);
 
        return ret;
 }
@@ -369,14 +358,10 @@ ereqreg:
 static __devexit int sh_csi2_remove(struct platform_device *pdev)
 {
        struct sh_csi2 *priv = platform_get_drvdata(pdev);
-       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
        v4l2_device_unregister_subdev(&priv->subdev);
        pm_runtime_disable(&pdev->dev);
-       iounmap(priv->base);
-       release_mem_region(res->start, resource_size(res));
        platform_set_drvdata(pdev, NULL);
-       kfree(priv);
 
        return 0;
 }
index 4e3735679f172fa3daf9620e3364a26987649da3..a8ca956e7a40e10aaf4aec13eb9c25938a5fe080 100644 (file)
@@ -908,6 +908,8 @@ static int soc_camera_s_crop(struct file *file, void *fh,
        dev_dbg(icd->pdev, "S_CROP(%ux%u@%u:%u)\n",
                rect->width, rect->height, rect->left, rect->top);
 
+       current_crop.type = a->type;
+
        /* If get_crop fails, we'll let host and / or client drivers decide */
        ret = ici->ops->get_crop(icd, &current_crop);
 
@@ -1137,8 +1139,8 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        if (ret < 0)
                return ret;
 
-       ret = regulator_bulk_get(icd->pdev, icl->num_regulators,
-                                icl->regulators);
+       ret = devm_regulator_bulk_get(icd->pdev, icl->num_regulators,
+                                     icl->regulators);
        if (ret < 0)
                goto ereg;
 
@@ -1242,7 +1244,6 @@ eadddev:
 evdc:
        ici->ops->remove(icd);
 eadd:
-       regulator_bulk_free(icl->num_regulators, icl->regulators);
 ereg:
        v4l2_ctrl_handler_free(&icd->ctrl_handler);
        return ret;
@@ -1276,8 +1277,6 @@ static int soc_camera_remove(struct soc_camera_device *icd)
        }
        soc_camera_free_user_formats(icd);
 
-       regulator_bulk_free(icl->num_regulators, icl->regulators);
-
        return 0;
 }
 
index a397812635d6a6a05d2a0ba4606794f2566a8786..89dce097a827a57d918702b0a4cd415b48ee409e 100644 (file)
@@ -378,9 +378,6 @@ EXPORT_SYMBOL(soc_mbus_samples_per_pixel);
 
 s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
 {
-       if (mf->fourcc == V4L2_PIX_FMT_JPEG)
-               return 0;
-
        if (mf->layout != SOC_MBUS_LAYOUT_PACKED)
                return width * mf->bits_per_sample / 8;
 
@@ -403,9 +400,6 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line);
 s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
                        u32 bytes_per_line, u32 height)
 {
-       if (mf->fourcc == V4L2_PIX_FMT_JPEG)
-               return 0;
-
        if (mf->layout == SOC_MBUS_LAYOUT_PACKED)
                return bytes_per_line * height;
 
index 02194c056b005f601d5d6743221f38c7f67971ab..9de014100a0fcce6ba85c4efa40438fce5e9f879 100644 (file)
@@ -130,7 +130,7 @@ static void timblogiw_dma_cb(void *data)
 
        if (vb->state != VIDEOBUF_ERROR) {
                list_del(&vb->queue);
-               do_gettimeofday(&vb->ts);
+               v4l2_get_timestamp(&vb->ts);
                vb->field_count = fh->frame_count * 2;
                vb->state = VIDEOBUF_DONE;
 
index 70b0bf4b2900ecd5e5619e85cf66dcc7c36de636..eb5d6f955709fbdbad6130f4b36cb74c59737608 100644 (file)
@@ -2474,8 +2474,8 @@ static irqreturn_t vino_interrupt(int irq, void *dev_id)
 
                if ((!handled_a) && (done_a || skip_a)) {
                        if (!skip_a) {
-                               do_gettimeofday(&vino_drvdata->
-                                               a.int_data.timestamp);
+                               v4l2_get_timestamp(
+                                       &vino_drvdata->a.int_data.timestamp);
                                vino_drvdata->a.int_data.frame_counter = fc_a;
                        }
                        vino_drvdata->a.int_data.skip = skip_a;
@@ -2489,8 +2489,8 @@ static irqreturn_t vino_interrupt(int irq, void *dev_id)
 
                if ((!handled_b) && (done_b || skip_b)) {
                        if (!skip_b) {
-                               do_gettimeofday(&vino_drvdata->
-                                               b.int_data.timestamp);
+                               v4l2_get_timestamp(
+                                       &vino_drvdata->b.int_data.timestamp);
                                vino_drvdata->b.int_data.frame_counter = fc_b;
                        }
                        vino_drvdata->b.int_data.skip = skip_b;
@@ -3410,6 +3410,9 @@ static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
        if (fb->map_count > 0)
                b->flags |= V4L2_BUF_FLAG_MAPPED;
 
+       b->flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK;
+       b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+
        b->index = fb->id;
        b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
                V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
index 0d59b9db83cb90b4d2ec1f38482111cdadbb77f5..ec6508909f02f944441ca06676353c3b1c4e7413 100644 (file)
 
 #define VIVI_MODULE_NAME "vivi"
 
-/* Wake up at about 30 fps */
-#define WAKE_NUMERATOR 30
-#define WAKE_DENOMINATOR 1001
+/* Maximum allowed frame rate
+ *
+ * Vivi will allow setting timeperframe in [1/FPS_MAX - FPS_MAX/1] range.
+ *
+ * Ideally FPS_MAX should be infinity, i.e. practically UINT_MAX, but that
+ * might hit application errors when they manipulate these values.
+ *
+ * Besides, for tpf < 1ms image-generation logic should be changed, to avoid
+ * producing frames with equal content.
+ */
+#define FPS_MAX 1000
 
 #define MAX_WIDTH 1920
 #define MAX_HEIGHT 1200
@@ -69,6 +77,12 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
 /* Global font descriptor */
 static const u8 *font8x16;
 
+/* timeperframe: min/max and default */
+static const struct v4l2_fract
+       tpf_min     = {.numerator = 1,          .denominator = FPS_MAX},
+       tpf_max     = {.numerator = FPS_MAX,    .denominator = 1},
+       tpf_default = {.numerator = 1001,       .denominator = 30000};  /* NTSC */
+
 #define dprintk(dev, level, fmt, arg...) \
        v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
 
@@ -150,14 +164,14 @@ static struct vivi_fmt formats[] = {
        },
 };
 
-static struct vivi_fmt *get_format(struct v4l2_format *f)
+static struct vivi_fmt *__get_format(u32 pixelformat)
 {
        struct vivi_fmt *fmt;
        unsigned int k;
 
        for (k = 0; k < ARRAY_SIZE(formats); k++) {
                fmt = &formats[k];
-               if (fmt->fourcc == f->fmt.pix.pixelformat)
+               if (fmt->fourcc == pixelformat)
                        break;
        }
 
@@ -167,6 +181,11 @@ static struct vivi_fmt *get_format(struct v4l2_format *f)
        return &formats[k];
 }
 
+static struct vivi_fmt *get_format(struct v4l2_format *f)
+{
+       return __get_format(f->fmt.pix.pixelformat);
+}
+
 /* buffer for one video frame */
 struct vivi_buffer {
        /* common v4l buffer stuff -- must be first */
@@ -232,14 +251,16 @@ struct vivi_dev {
 
        /* video capture */
        struct vivi_fmt            *fmt;
+       struct v4l2_fract          timeperframe;
        unsigned int               width, height;
        struct vb2_queue           vb_vidq;
        unsigned int               field_count;
 
        u8                         bars[9][3];
-       u8                         line[MAX_WIDTH * 8];
+       u8                         line[MAX_WIDTH * 8] __attribute__((__aligned__(4)));
        unsigned int               pixelsize;
        u8                         alpha_component;
+       u32                        textfg, textbg;
 };
 
 /* ------------------------------------------------------------------
@@ -511,66 +532,100 @@ static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd)
 
 static void precalculate_line(struct vivi_dev *dev)
 {
-       int w;
-
-       for (w = 0; w < dev->width * 2; w++) {
-               int colorpos = w / (dev->width / 8) % 8;
-
-               gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1);
+       unsigned pixsize  = dev->pixelsize;
+       unsigned pixsize2 = 2*pixsize;
+       int colorpos;
+       u8 *pos;
+
+       for (colorpos = 0; colorpos < 16; ++colorpos) {
+               u8 pix[8];
+               int wstart =  colorpos    * dev->width / 8;
+               int wend   = (colorpos+1) * dev->width / 8;
+               int w;
+
+               gen_twopix(dev, &pix[0],        colorpos % 8, 0);
+               gen_twopix(dev, &pix[pixsize],  colorpos % 8, 1);
+
+               for (w = wstart/2*2, pos = dev->line + w*pixsize; w < wend; w += 2, pos += pixsize2)
+                       memcpy(pos, pix, pixsize2);
        }
 }
 
+/* need this to do rgb24 rendering */
+typedef struct { u16 __; u8 _; } __attribute__((packed)) x24;
+
 static void gen_text(struct vivi_dev *dev, char *basep,
                                        int y, int x, char *text)
 {
        int line;
+       unsigned int width = dev->width;
 
        /* Checks if it is possible to show string */
-       if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
+       if (y + 16 >= dev->height || x + strlen(text) * 8 >= width)
                return;
 
        /* Print stream time */
-       for (line = y; line < y + 16; line++) {
-               int j = 0;
-               char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize;
-               char *s;
-
-               for (s = text; *s; s++) {
-                       u8 chr = font8x16[*s * 16 + line - y];
-                       int i;
-
-                       for (i = 0; i < 7; i++, j++) {
-                               /* Draw white font on black background */
-                               if (chr & (1 << (7 - i)))
-                                       gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1);
-                               else
-                                       gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1);
-                       }
-               }
+#define PRINTSTR(PIXTYPE) do { \
+       PIXTYPE fg;     \
+       PIXTYPE bg;     \
+       memcpy(&fg, &dev->textfg, sizeof(PIXTYPE));     \
+       memcpy(&bg, &dev->textbg, sizeof(PIXTYPE));     \
+       \
+       for (line = 0; line < 16; line++) {     \
+               PIXTYPE *pos = (PIXTYPE *)( basep + ((y + line) * width + x) * sizeof(PIXTYPE) );       \
+               u8 *s;  \
+       \
+               for (s = text; *s; s++) {       \
+                       u8 chr = font8x16[*s * 16 + line];      \
+       \
+                       pos[0] = (chr & (0x01 << 7) ? fg : bg); \
+                       pos[1] = (chr & (0x01 << 6) ? fg : bg); \
+                       pos[2] = (chr & (0x01 << 5) ? fg : bg); \
+                       pos[3] = (chr & (0x01 << 4) ? fg : bg); \
+                       pos[4] = (chr & (0x01 << 3) ? fg : bg); \
+                       pos[5] = (chr & (0x01 << 2) ? fg : bg); \
+                       pos[6] = (chr & (0x01 << 1) ? fg : bg); \
+                       pos[7] = (chr & (0x01 << 0) ? fg : bg); \
+       \
+                       pos += 8;       \
+               }       \
+       }       \
+} while (0)
+
+       switch (dev->pixelsize) {
+       case 2:
+               PRINTSTR(u16); break;
+       case 4:
+               PRINTSTR(u32); break;
+       case 3:
+               PRINTSTR(x24); break;
        }
 }
 
 static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
 {
-       int wmax = dev->width;
+       int stride = dev->width * dev->pixelsize;
        int hmax = dev->height;
-       struct timeval ts;
        void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
        unsigned ms;
        char str[100];
        int h, line = 1;
+       u8 *linestart;
        s32 gain;
 
        if (!vbuf)
                return;
 
+       linestart = dev->line + (dev->mv_count % dev->width) * dev->pixelsize;
+
        for (h = 0; h < hmax; h++)
-               memcpy(vbuf + h * wmax * dev->pixelsize,
-                      dev->line + (dev->mv_count % wmax) * dev->pixelsize,
-                      wmax * dev->pixelsize);
+               memcpy(vbuf + h * stride, linestart, stride);
 
        /* Updates stream time */
 
+       gen_twopix(dev, (u8 *)&dev->textbg, TEXT_BLACK, /*odd=*/ 0);
+       gen_twopix(dev, (u8 *)&dev->textfg, WHITE, /*odd=*/ 0);
+
        dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
        dev->jiffies = jiffies;
        ms = dev->ms;
@@ -622,8 +677,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
        buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
        dev->field_count++;
        buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
-       do_gettimeofday(&ts);
-       buf->vb.v4l2_buf.timestamp = ts;
+       v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 }
 
 static void vivi_thread_tick(struct vivi_dev *dev)
@@ -645,7 +699,7 @@ static void vivi_thread_tick(struct vivi_dev *dev)
        list_del(&buf->list);
        spin_unlock_irqrestore(&dev->slock, flags);
 
-       do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
+       v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 
        /* Fill buffer */
        vivi_fillbuff(dev, buf);
@@ -655,8 +709,8 @@ static void vivi_thread_tick(struct vivi_dev *dev)
        dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
 }
 
-#define frames_to_ms(frames)                                   \
-       ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
+#define frames_to_ms(dev, frames)                              \
+       ((frames * dev->timeperframe.numerator * 1000) / dev->timeperframe.denominator)
 
 static void vivi_sleep(struct vivi_dev *dev)
 {
@@ -672,7 +726,7 @@ static void vivi_sleep(struct vivi_dev *dev)
                goto stop_task;
 
        /* Calculate time to wake up */
-       timeout = msecs_to_jiffies(frames_to_ms(1));
+       timeout = msecs_to_jiffies(frames_to_ms(dev, 1));
 
        vivi_thread_tick(dev);
 
@@ -1044,6 +1098,70 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        return 0;
 }
 
+/* timeperframe is arbitrary and continous */
+static int vidioc_enum_frameintervals(struct file *file, void *priv,
+                                            struct v4l2_frmivalenum *fival)
+{
+       struct vivi_fmt *fmt;
+
+       if (fival->index)
+               return -EINVAL;
+
+       fmt = __get_format(fival->pixel_format);
+       if (!fmt)
+               return -EINVAL;
+
+       /* regarding width & height - we support any */
+
+       fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
+
+       /* fill in stepwise (step=1.0 is requred by V4L2 spec) */
+       fival->stepwise.min  = tpf_min;
+       fival->stepwise.max  = tpf_max;
+       fival->stepwise.step = (struct v4l2_fract) {1, 1};
+
+       return 0;
+}
+
+static int vidioc_g_parm(struct file *file, void *priv,
+                         struct v4l2_streamparm *parm)
+{
+       struct vivi_dev *dev = video_drvdata(file);
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       parm->parm.capture.capability   = V4L2_CAP_TIMEPERFRAME;
+       parm->parm.capture.timeperframe = dev->timeperframe;
+       parm->parm.capture.readbuffers  = 1;
+       return 0;
+}
+
+#define FRACT_CMP(a, OP, b)    \
+       ((u64)(a).numerator * (b).denominator  OP  (u64)(b).numerator * (a).denominator)
+
+static int vidioc_s_parm(struct file *file, void *priv,
+                         struct v4l2_streamparm *parm)
+{
+       struct vivi_dev *dev = video_drvdata(file);
+       struct v4l2_fract tpf;
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       tpf = parm->parm.capture.timeperframe;
+
+       /* tpf: {*, 0} resets timing; clip to [min, max]*/
+       tpf = tpf.denominator ? tpf : tpf_default;
+       tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf;
+       tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf;
+
+       dev->timeperframe = tpf;
+       parm->parm.capture.timeperframe = tpf;
+       parm->parm.capture.readbuffers  = 1;
+       return 0;
+}
+
 /* --- controls ---------------------------------------------- */
 
 static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
@@ -1202,6 +1320,9 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
        .vidioc_enum_input    = vidioc_enum_input,
        .vidioc_g_input       = vidioc_g_input,
        .vidioc_s_input       = vidioc_s_input,
+       .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+       .vidioc_g_parm        = vidioc_g_parm,
+       .vidioc_s_parm        = vidioc_s_parm,
        .vidioc_streamon      = vb2_ioctl_streamon,
        .vidioc_streamoff     = vb2_ioctl_streamoff,
        .vidioc_log_status    = v4l2_ctrl_log_status,
@@ -1260,6 +1381,7 @@ static int __init vivi_create_instance(int inst)
                goto free_dev;
 
        dev->fmt = &formats[0];
+       dev->timeperframe = tpf_default;
        dev->width = 640;
        dev->height = 480;
        dev->pixelsize = dev->fmt->depth / 8;
index 2d6fb26a017094a1fa23828b7ce5c546a2cdad80..4d6a63fe6c5e210f878b132c6f6ea386e185fa66 100644 (file)
@@ -872,11 +872,11 @@ static int ati_remote_probe(struct usb_interface *interface,
        ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
        rc_dev = rc_allocate_device();
        if (!ati_remote || !rc_dev)
-               goto fail1;
+               goto exit_free_dev_rdev;
 
        /* Allocate URB buffers, URBs */
        if (ati_remote_alloc_buffers(udev, ati_remote))
-               goto fail2;
+               goto exit_free_buffers;
 
        ati_remote->endpoint_in = endpoint_in;
        ati_remote->endpoint_out = endpoint_out;
@@ -924,12 +924,12 @@ static int ati_remote_probe(struct usb_interface *interface,
        /* Device Hardware Initialization - fills in ati_remote->idev from udev. */
        err = ati_remote_initialize(ati_remote);
        if (err)
-               goto fail3;
+               goto exit_kill_urbs;
 
        /* Set up and register rc device */
        err = rc_register_device(ati_remote->rdev);
        if (err)
-               goto fail3;
+               goto exit_kill_urbs;
 
        /* use our delay for rc_dev */
        ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay;
@@ -939,7 +939,7 @@ static int ati_remote_probe(struct usb_interface *interface,
                input_dev = input_allocate_device();
                if (!input_dev) {
                        err = -ENOMEM;
-                       goto fail4;
+                       goto exit_unregister_device;
                }
 
                ati_remote->idev = input_dev;
@@ -947,19 +947,24 @@ static int ati_remote_probe(struct usb_interface *interface,
                err = input_register_device(input_dev);
 
                if (err)
-                       goto fail5;
+                       goto exit_free_input_device;
        }
 
        usb_set_intfdata(interface, ati_remote);
        return 0;
 
- fail5:        input_free_device(input_dev);
- fail4:        rc_unregister_device(rc_dev);
+ exit_free_input_device:
+       input_free_device(input_dev);
+ exit_unregister_device:
+       rc_unregister_device(rc_dev);
        rc_dev = NULL;
- fail3:        usb_kill_urb(ati_remote->irq_urb);
+ exit_kill_urbs:
+       usb_kill_urb(ati_remote->irq_urb);
        usb_kill_urb(ati_remote->out_urb);
- fail2:        ati_remote_free_buffers(ati_remote);
- fail1:        rc_free_device(rc_dev);
+ exit_free_buffers:
+       ati_remote_free_buffers(ati_remote);
+ exit_free_dev_rdev:
+        rc_free_device(rc_dev);
        kfree(ati_remote);
        return err;
 }
index 22231dd4f62b9432039bc41fdf954c86d60415b0..e601166c1edb5e1a1a07f8e5340df1a4669e0e93 100644 (file)
@@ -1003,7 +1003,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
        dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
        rdev = rc_allocate_device();
        if (!dev || !rdev)
-               goto failure;
+               goto exit_free_dev_rdev;
 
        /* validate resources */
        error = -ENODEV;
@@ -1014,10 +1014,10 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 
        if (!pnp_port_valid(pnp_dev, 0) ||
            pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
-               goto failure;
+               goto exit_free_dev_rdev;
 
        if (!pnp_irq_valid(pnp_dev, 0))
-               goto failure;
+               goto exit_free_dev_rdev;
 
        spin_lock_init(&dev->hw_lock);
 
@@ -1033,7 +1033,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
        /* detect hardware version and features */
        error = ene_hw_detect(dev);
        if (error)
-               goto failure;
+               goto exit_free_dev_rdev;
 
        if (!dev->hw_learning_and_tx_capable && txsim) {
                dev->hw_learning_and_tx_capable = true;
@@ -1075,30 +1075,30 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
        device_set_wakeup_capable(&pnp_dev->dev, true);
        device_set_wakeup_enable(&pnp_dev->dev, true);
 
+       error = rc_register_device(rdev);
+       if (error < 0)
+               goto exit_free_dev_rdev;
+
        /* claim the resources */
        error = -EBUSY;
        if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
-               goto failure;
+               goto exit_unregister_device;
        }
 
        dev->irq = pnp_irq(pnp_dev, 0);
        if (request_irq(dev->irq, ene_isr,
                        IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
-               goto failure2;
+               goto exit_release_hw_io;
        }
 
-       error = rc_register_device(rdev);
-       if (error < 0)
-               goto failure3;
-
        pr_notice("driver has been successfully loaded\n");
        return 0;
 
-failure3:
-       free_irq(dev->irq, dev);
-failure2:
+exit_release_hw_io:
        release_region(dev->hw_io, ENE_IO_SIZE);
-failure:
+exit_unregister_device:
+       rc_unregister_device(rdev);
+exit_free_dev_rdev:
        rc_free_device(rdev);
        kfree(dev);
        return error;
index 936c3f79b62cba500b8e53ba4adffb899bfda007..5eefe65760a4aadfa9f73e43f1a9ca3814890ffd 100644 (file)
@@ -500,18 +500,18 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
        /* input device for IR remote (and tx) */
        rdev = rc_allocate_device();
        if (!rdev)
-               goto failure;
+               goto exit_free_dev_rdev;
 
        ret = -ENODEV;
        /* validate pnp resources */
        if (!pnp_port_valid(pdev, 0)) {
                dev_err(&pdev->dev, "IR PNP Port not valid!\n");
-               goto failure;
+               goto exit_free_dev_rdev;
        }
 
        if (!pnp_irq_valid(pdev, 0)) {
                dev_err(&pdev->dev, "IR PNP IRQ not valid!\n");
-               goto failure;
+               goto exit_free_dev_rdev;
        }
 
        fintek->cir_addr = pnp_port_start(pdev, 0);
@@ -528,7 +528,7 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
 
        ret = fintek_hw_detect(fintek);
        if (ret)
-               goto failure;
+               goto exit_free_dev_rdev;
 
        /* Initialize CIR & CIR Wake Logical Devices */
        fintek_config_mode_enable(fintek);
@@ -557,33 +557,35 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
        /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
        rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD);
 
+       fintek->rdev = rdev;
+
        ret = -EBUSY;
        /* now claim resources */
        if (!request_region(fintek->cir_addr,
                            fintek->cir_port_len, FINTEK_DRIVER_NAME))
-               goto failure;
+               goto exit_free_dev_rdev;
 
        if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
                        FINTEK_DRIVER_NAME, (void *)fintek))
-               goto failure2;
+               goto exit_free_cir_addr;
 
        ret = rc_register_device(rdev);
        if (ret)
-               goto failure3;
+               goto exit_free_irq;
 
        device_init_wakeup(&pdev->dev, true);
-       fintek->rdev = rdev;
+
        fit_pr(KERN_NOTICE, "driver has been successfully loaded\n");
        if (debug)
                cir_dump_regs(fintek);
 
        return 0;
 
-failure3:
+exit_free_irq:
        free_irq(fintek->cir_irq, fintek);
-failure2:
+exit_free_cir_addr:
        release_region(fintek->cir_addr, fintek->cir_port_len);
-failure:
+exit_free_dev_rdev:
        rc_free_device(rdev);
        kfree(fintek);
 
index ba1a1eb356cf765d47d48b0e829f37b0133b5259..03e3cf6eb68f602d487550c0082f72209662abc3 100644 (file)
@@ -129,12 +129,12 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
 err_request_irq:
        platform_set_drvdata(pdev, NULL);
        rc_unregister_device(rcdev);
+       rcdev = NULL;
 err_register_rc_device:
 err_gpio_direction_input:
        gpio_free(pdata->gpio_nr);
 err_gpio_request:
        rc_free_device(rcdev);
-       rcdev = NULL;
 err_allocate_device:
        kfree(gpio_dev);
        return rc;
@@ -148,7 +148,6 @@ static int __devexit gpio_ir_recv_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
        rc_unregister_device(gpio_dev->rcdev);
        gpio_free(gpio_dev->gpio_nr);
-       rc_free_device(gpio_dev->rcdev);
        kfree(gpio_dev);
        return 0;
 }
index 5e5a7f2b8184cc992fab2bf0e3e90cb09c65c154..e810846fada472961b43ae169c7aa1319428f545 100644 (file)
@@ -1472,7 +1472,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        /* input device for IR remote (and tx) */
        rdev = rc_allocate_device();
        if (!rdev)
-               goto failure;
+               goto exit_free_dev_rdev;
        itdev->rdev = rdev;
 
        ret = -ENODEV;
@@ -1498,12 +1498,12 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        if (!pnp_port_valid(pdev, io_rsrc_no) ||
            pnp_port_len(pdev, io_rsrc_no) != dev_desc->io_region_size) {
                dev_err(&pdev->dev, "IR PNP Port not valid!\n");
-               goto failure;
+               goto exit_free_dev_rdev;
        }
 
        if (!pnp_irq_valid(pdev, 0)) {
                dev_err(&pdev->dev, "PNP IRQ not valid!\n");
-               goto failure;
+               goto exit_free_dev_rdev;
        }
 
        /* store resource values */
@@ -1591,29 +1591,29 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        rdev->driver_name = ITE_DRIVER_NAME;
        rdev->map_name = RC_MAP_RC6_MCE;
 
+       ret = rc_register_device(rdev);
+       if (ret)
+               goto exit_free_dev_rdev;
+
        ret = -EBUSY;
        /* now claim resources */
        if (!request_region(itdev->cir_addr,
                                dev_desc->io_region_size, ITE_DRIVER_NAME))
-               goto failure;
+               goto exit_unregister_device;
 
        if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
                        ITE_DRIVER_NAME, (void *)itdev))
-               goto failure2;
-
-       ret = rc_register_device(rdev);
-       if (ret)
-               goto failure3;
+               goto exit_release_cir_addr;
 
        ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
 
        return 0;
 
-failure3:
-       free_irq(itdev->cir_irq, itdev);
-failure2:
+exit_release_cir_addr:
        release_region(itdev->cir_addr, itdev->params.io_region_size);
-failure:
+exit_unregister_device:
+       rc_unregister_device(rdev);
+exit_free_dev_rdev:
        rc_free_device(rdev);
        kfree(itdev);
 
index ab84d66c67c1b0e37df35e4704d29aa3d7f73555..778661971aed52b6b5b4a6ef4e71a8bac851cbbf 100644 (file)
@@ -88,6 +88,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
                        rc-tevii-nec.o \
                        rc-tivo.o \
                        rc-total-media-in-hand.o \
+                       rc-total-media-in-hand-02.o \
                        rc-trekstor.o \
                        rc-tt-1500.o \
                        rc-twinhan1027.o \
diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand-02.c b/drivers/media/rc/keymaps/rc-total-media-in-hand-02.c
new file mode 100644 (file)
index 0000000..47270f7
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Total Media In Hand_02 remote controller keytable for Mygica X8507
+ *
+ * Copyright (C) 2012 Alfredo J. Delaiti <alfredodelaiti@netscape.net>
+ *
+ *    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.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+#include <linux/module.h>
+
+
+static struct rc_map_table total_media_in_hand_02[] = {
+       { 0x0000, KEY_0 },
+       { 0x0001, KEY_1 },
+       { 0x0002, KEY_2 },
+       { 0x0003, KEY_3 },
+       { 0x0004, KEY_4 },
+       { 0x0005, KEY_5 },
+       { 0x0006, KEY_6 },
+       { 0x0007, KEY_7 },
+       { 0x0008, KEY_8 },
+       { 0x0009, KEY_9 },
+       { 0x000a, KEY_MUTE },
+       { 0x000b, KEY_STOP },                   /* Stop */
+       { 0x000c, KEY_POWER2 },                 /* Turn on/off application */
+       { 0x000d, KEY_OK },                     /* OK */
+       { 0x000e, KEY_CAMERA },                 /* Snapshot */
+       { 0x000f, KEY_ZOOM },                   /* Full Screen/Restore */
+       { 0x0010, KEY_RIGHT },                  /* Right arrow */
+       { 0x0011, KEY_LEFT },                   /* Left arrow */
+       { 0x0012, KEY_CHANNELUP },
+       { 0x0013, KEY_CHANNELDOWN },
+       { 0x0014, KEY_SHUFFLE },
+       { 0x0016, KEY_PAUSE },
+       { 0x0017, KEY_PLAY },                   /* Play */
+       { 0x001e, KEY_TIME },                   /* Time Shift */
+       { 0x001f, KEY_RECORD },
+       { 0x0020, KEY_UP },
+       { 0x0021, KEY_DOWN },
+       { 0x0025, KEY_POWER },                  /* Turn off computer */
+       { 0x0026, KEY_REWIND },                 /* FR << */
+       { 0x0027, KEY_FASTFORWARD },            /* FF >> */
+       { 0x0029, KEY_ESC },
+       { 0x002b, KEY_VOLUMEUP },
+       { 0x002c, KEY_VOLUMEDOWN },
+       { 0x002d, KEY_CHANNEL },                /* CH Surfing */
+       { 0x0038, KEY_VIDEO },                  /* TV/AV/S-Video/YPbPr */
+};
+
+static struct rc_map_list total_media_in_hand_02_map = {
+       .map = {
+               .scan    = total_media_in_hand_02,
+               .size    = ARRAY_SIZE(total_media_in_hand_02),
+               .rc_type = RC_TYPE_RC5,
+               .name    = RC_MAP_TOTAL_MEDIA_IN_HAND_02,
+       }
+};
+
+static int __init init_rc_map_total_media_in_hand_02(void)
+{
+       return rc_map_register(&total_media_in_hand_02_map);
+}
+
+static void __exit exit_rc_map_total_media_in_hand_02(void)
+{
+       rc_map_unregister(&total_media_in_hand_02_map);
+}
+
+module_init(init_rc_map_total_media_in_hand_02)
+module_exit(exit_rc_map_total_media_in_hand_02)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(" Alfredo J. Delaiti <alfredodelaiti@netscape.net>");
index e4ea89a11eed451efd967b36a41a4fbbf5a7edf0..6cf43cc237eb20c45ee32c79cef7f75bde1d0839 100644 (file)
@@ -986,25 +986,25 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
        /* input device for IR remote (and tx) */
        rdev = rc_allocate_device();
        if (!rdev)
-               goto failure;
+               goto exit_free_dev_rdev;
 
        ret = -ENODEV;
        /* validate pnp resources */
        if (!pnp_port_valid(pdev, 0) ||
            pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
                dev_err(&pdev->dev, "IR PNP Port not valid!\n");
-               goto failure;
+               goto exit_free_dev_rdev;
        }
 
        if (!pnp_irq_valid(pdev, 0)) {
                dev_err(&pdev->dev, "PNP IRQ not valid!\n");
-               goto failure;
+               goto exit_free_dev_rdev;
        }
 
        if (!pnp_port_valid(pdev, 1) ||
            pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
                dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
-               goto failure;
+               goto exit_free_dev_rdev;
        }
 
        nvt->cir_addr = pnp_port_start(pdev, 0);
@@ -1027,7 +1027,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 
        ret = nvt_hw_detect(nvt);
        if (ret)
-               goto failure;
+               goto exit_free_dev_rdev;
 
        /* Initialize CIR & CIR Wake Logical Devices */
        nvt_efm_enable(nvt);
@@ -1065,31 +1065,32 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
        /* tx bits */
        rdev->tx_resolution = XYZ;
 #endif
+       nvt->rdev = rdev;
+
+       ret = rc_register_device(rdev);
+       if (ret)
+               goto exit_free_dev_rdev;
 
        ret = -EBUSY;
        /* now claim resources */
        if (!request_region(nvt->cir_addr,
                            CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
-               goto failure;
+               goto exit_unregister_device;
 
        if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
                        NVT_DRIVER_NAME, (void *)nvt))
-               goto failure2;
+               goto exit_release_cir_addr;
 
        if (!request_region(nvt->cir_wake_addr,
                            CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
-               goto failure3;
+               goto exit_free_irq;
 
        if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
                        NVT_DRIVER_NAME, (void *)nvt))
-               goto failure4;
-
-       ret = rc_register_device(rdev);
-       if (ret)
-               goto failure5;
+               goto exit_release_cir_wake_addr;
 
        device_init_wakeup(&pdev->dev, true);
-       nvt->rdev = rdev;
+
        nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n");
        if (debug) {
                cir_dump_regs(nvt);
@@ -1098,15 +1099,15 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 
        return 0;
 
-failure5:
-       free_irq(nvt->cir_wake_irq, nvt);
-failure4:
+exit_release_cir_wake_addr:
        release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
-failure3:
+exit_free_irq:
        free_irq(nvt->cir_irq, nvt);
-failure2:
+exit_release_cir_addr:
        release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
-failure:
+exit_unregister_device:
+       rc_unregister_device(rdev);
+exit_free_dev_rdev:
        rc_free_device(rdev);
        kfree(nvt);
 
index 601d1ac1c688b2608e8b96cbecae27f877c4b4b6..d593bc65b4ca402ef8d3dbc7be37acd67f32c138 100644 (file)
@@ -789,8 +789,10 @@ static ssize_t show_protocols(struct device *device,
        } else if (dev->raw) {
                enabled = dev->raw->enabled_protocols;
                allowed = ir_raw_get_allowed_protocols();
-       } else
+       } else {
+               mutex_unlock(&dev->lock);
                return -ENODEV;
+       }
 
        IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
                   (long long)allowed,
index 7f3c476dde05fb712cbb0fbbbc55c36e3150aba4..553d1cdc439f29e28c1a80875f49ff1718af2802 100644 (file)
@@ -1093,11 +1093,15 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
        data->dev->rx_resolution = US_TO_NS(2);
        data->dev->allowed_protos = RC_BIT_ALL;
 
+       err = rc_register_device(data->dev);
+       if (err)
+               goto exit_free_rc;
+
        if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
                dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
                        data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
                err = -EBUSY;
-               goto exit_free_rc;
+               goto exit_unregister_device;
        }
 
        if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
@@ -1122,24 +1126,20 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
                goto exit_release_sbase;
        }
 
-       err = rc_register_device(data->dev);
-       if (err)
-               goto exit_free_irq;
-
        device_init_wakeup(&device->dev, 1);
 
        wbcir_init_hw(data);
 
        return 0;
 
-exit_free_irq:
-       free_irq(data->irq, device);
 exit_release_sbase:
        release_region(data->sbase, SP_IOMEM_LEN);
 exit_release_ebase:
        release_region(data->ebase, EHFUNC_IOMEM_LEN);
 exit_release_wbase:
        release_region(data->wbase, WAKEUP_IOMEM_LEN);
+exit_unregister_device:
+       rc_unregister_device(data->dev);
 exit_free_rc:
        rc_free_device(data->dev);
 exit_unregister_led:
index 5d9f028425012e75ee7edefe97c149fb9f415df6..e4a84ee231cf458a4e5b84292f2e83115e023caf 100644 (file)
@@ -277,7 +277,7 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
 {
        struct tda18212_priv *priv = NULL;
        int ret;
-       u8 uninitialized_var(val);
+       u8 val;
 
        priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
        if (priv == NULL)
@@ -296,8 +296,8 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
-       dev_dbg(&priv->i2c->dev, "%s: ret=%d chip id=%02x\n", __func__, ret,
-                       val);
+       if (!ret)
+               dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, val);
        if (ret || val != 0xc7) {
                kfree(priv);
                return NULL;
index 18198537be9f45c9f224947643f9884ac22348db..2d31aeb6b088997fbed7678f631a47f175500d55 100644 (file)
@@ -277,7 +277,7 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
        struct i2c_adapter *i2c, struct tda18218_config *cfg)
 {
        struct tda18218_priv *priv = NULL;
-       u8 uninitialized_var(val);
+       u8 val;
        int ret;
        /* chip default registers values */
        static u8 def_regs[] = {
@@ -302,8 +302,8 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
 
        /* check if the tuner is there */
        ret = tda18218_rd_reg(priv, R00_ID, &val);
-       dev_dbg(&priv->i2c->dev, "%s: ret=%d chip id=%02x\n", __func__, ret,
-                       val);
+       if (!ret)
+               dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, val);
        if (ret || val != def_regs[R00_ID]) {
                kfree(priv);
                return NULL;
index 72c26fd77922883bf029a2b19d0af2ac52194c8b..e7786862dab2e4af7775bec7b8197d794ec094d8 100644 (file)
@@ -1122,6 +1122,7 @@ static int tda18271_dump_std_map(struct dvb_frontend *fe)
        tda18271_dump_std_item(dvbt_7, "dvbt 7");
        tda18271_dump_std_item(dvbt_8, "dvbt 8");
        tda18271_dump_std_item(qam_6,  "qam 6 ");
+       tda18271_dump_std_item(qam_7,  "qam 7 ");
        tda18271_dump_std_item(qam_8,  "qam 8 ");
 
        return 0;
@@ -1149,6 +1150,7 @@ static int tda18271_update_std_map(struct dvb_frontend *fe,
        tda18271_update_std(dvbt_7, "dvbt 7");
        tda18271_update_std(dvbt_8, "dvbt 8");
        tda18271_update_std(qam_6,  "qam 6");
+       tda18271_update_std(qam_7,  "qam 7");
        tda18271_update_std(qam_8,  "qam 8");
 
        return 0;
index 6746994d03fe2fce10cdb9c1b59429919d56c50c..0a7d520636a9a5a2ac2017ec5243c65b6b1c5841 100644 (file)
@@ -21,7 +21,6 @@ endif
 
 if MEDIA_ANALOG_TV_SUPPORT
        comment "Analog TV USB devices"
-source "drivers/media/usb/au0828/Kconfig"
 source "drivers/media/usb/pvrusb2/Kconfig"
 source "drivers/media/usb/hdpvr/Kconfig"
 source "drivers/media/usb/tlg2300/Kconfig"
@@ -31,6 +30,7 @@ endif
 
 if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
        comment "Analog/digital TV USB devices"
+source "drivers/media/usb/au0828/Kconfig"
 source "drivers/media/usb/cx231xx/Kconfig"
 source "drivers/media/usb/tm6000/Kconfig"
 endif
index 1766c0ce93be3736bd50c6b2991a622961cfa9d0..953a37c613b146883d70567c9f30d73c39e09700 100644 (file)
@@ -1,17 +1,28 @@
 
 config VIDEO_AU0828
        tristate "Auvitek AU0828 support"
-       depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
+       depends on I2C && INPUT && DVB_CORE && USB
        select I2C_ALGOBIT
        select VIDEO_TVEEPROM
        select VIDEOBUF_VMALLOC
        select DVB_AU8522_DTV if MEDIA_SUBDRV_AUTOSELECT
-       select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
-         This is a video4linux driver for Auvitek's USB device.
+         This is a hybrid analog/digital tv capture driver for
+         Auvitek's AU0828 USB device.
 
          To compile this driver as a module, choose M here: the
          module will be called au0828
+
+config VIDEO_AU0828_V4L2
+       bool "Auvitek AU0828 v4l2 analog video support"
+       depends on VIDEO_AU0828 && VIDEO_V4L2
+       select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT
+       default y
+       ---help---
+         This is a video4linux driver for Auvitek's USB device.
+
+         Choose Y here to include support for v4l2 analog video
+         capture within the au0828 driver.
index 98cc20cc0ffb2538cd025899e51931f9535715c2..be3bdf698022858eafa2121f2982f72e05dc1662 100644 (file)
@@ -1,4 +1,8 @@
-au0828-objs    := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o au0828-vbi.o
+au0828-objs    := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
+
+ifeq ($(CONFIG_VIDEO_AU0828_V4L2),y)
+  au0828-objs   += au0828-video.o au0828-vbi.o
+endif
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828.o
 
index 0cb7c28dcb1787e661fffe919ab6851e4a939c6a..88e35dfa33d47eeb989f76321a46c6722a8ca5f3 100644 (file)
@@ -169,7 +169,9 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
        case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
        case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
        case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
-       case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+       case 72261: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
+       case 72271: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
+       case 72281: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
        case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
        case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
                break;
@@ -183,12 +185,11 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
               __func__, tv.model);
 }
 
+void au0828_card_analog_fe_setup(struct au0828_dev *dev);
+
 void au0828_card_setup(struct au0828_dev *dev)
 {
        static u8 eeprom[256];
-       struct tuner_setup tun_setup;
-       struct v4l2_subdev *sd;
-       unsigned int mode_mask = T_ANALOG_TV;
 
        dprintk(1, "%s()\n", __func__);
 
@@ -209,6 +210,16 @@ void au0828_card_setup(struct au0828_dev *dev)
                break;
        }
 
+       au0828_card_analog_fe_setup(dev);
+}
+
+void au0828_card_analog_fe_setup(struct au0828_dev *dev)
+{
+#ifdef CONFIG_VIDEO_AU0828_V4L2
+       struct tuner_setup tun_setup;
+       struct v4l2_subdev *sd;
+       unsigned int mode_mask = T_ANALOG_TV;
+
        if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
                /* Load the analog demodulator driver (note this would need to
                   be abstracted out if we ever need to support a different
@@ -234,6 +245,7 @@ void au0828_card_setup(struct au0828_dev *dev)
                v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr,
                                     &tun_setup);
        }
+#endif
 }
 
 /*
@@ -333,6 +345,8 @@ struct usb_device_id au0828_usb_id_table[] = {
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
        { USB_DEVICE(0x2040, 0x7213),
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7270),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
        { },
 };
 
index 745a80a798c8b034f76401c43ce9935b71ce5569..1e6f40ef1c6b604e18e44e98fdca3f51284bb0c2 100644 (file)
@@ -134,13 +134,17 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
        /* Digital TV */
        au0828_dvb_unregister(dev);
 
+#ifdef CONFIG_VIDEO_AU0828_V4L2
        if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
                au0828_analog_unregister(dev);
+#endif
 
        /* I2C */
        au0828_i2c_unregister(dev);
 
+#ifdef CONFIG_VIDEO_AU0828_V4L2
        v4l2_device_unregister(&dev->v4l2_dev);
+#endif
 
        usb_set_intfdata(interface, NULL);
 
@@ -155,7 +159,10 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
 static int au0828_usb_probe(struct usb_interface *interface,
        const struct usb_device_id *id)
 {
-       int ifnum, retval;
+       int ifnum;
+#ifdef CONFIG_VIDEO_AU0828_V4L2
+       int retval;
+#endif
        struct au0828_dev *dev;
        struct usb_device *usbdev = interface_to_usbdev(interface);
 
@@ -194,6 +201,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
        dev->usbdev = usbdev;
        dev->boardnr = id->driver_info;
 
+#ifdef CONFIG_VIDEO_AU0828_V4L2
        /* Create the v4l2_device */
        retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
        if (retval) {
@@ -203,6 +211,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
                kfree(dev);
                return -EIO;
        }
+#endif
 
        /* Power Up the bridge */
        au0828_write(dev, REG_600, 1 << 4);
@@ -216,9 +225,11 @@ static int au0828_usb_probe(struct usb_interface *interface,
        /* Setup */
        au0828_card_setup(dev);
 
+#ifdef CONFIG_VIDEO_AU0828_V4L2
        /* Analog TV */
        if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
                au0828_analog_register(dev, interface);
+#endif
 
        /* Digital TV */
        au0828_dvb_register(dev);
index 4ded17fe195792d53158e7936048213376c40e6b..20d69b5652552fd6a0dab9ee1e2e3a81d5ab2f62 100644 (file)
@@ -378,7 +378,11 @@ int au0828_i2c_register(struct au0828_dev *dev)
 
        dev->i2c_adap.algo = &dev->i2c_algo;
        dev->i2c_adap.algo_data = dev;
+#ifdef CONFIG_VIDEO_AU0828_V4L2
        i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+#else
+       i2c_set_adapdata(&dev->i2c_adap, dev);
+#endif
        i2c_add_adapter(&dev->i2c_adap);
 
        dev->i2c_client.adapter = &dev->i2c_adap;
index 45387aab10c7ca5633c66c8616c4beb978039594..8b9e8268e911d2589f2758f8631f428518013019 100644 (file)
@@ -304,7 +304,7 @@ static inline void buffer_filled(struct au0828_dev *dev,
 
        buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
+       v4l2_get_timestamp(&buf->vb.ts);
 
        dev->isoc_ctl.buf = NULL;
 
@@ -321,7 +321,7 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev,
 
        buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
+       v4l2_get_timestamp(&buf->vb.ts);
 
        dev->isoc_ctl.vbi_buf = NULL;
 
index 66a56ef7bbe4f4921a9ebc1af6911a293693573f..e579ff69ca4a692121b27a5a43d34eaf9d9767d6 100644 (file)
@@ -199,8 +199,10 @@ struct au0828_dev {
        struct au0828_dvb               dvb;
        struct work_struct              restart_streaming;
 
+#ifdef CONFIG_VIDEO_AU0828_V4L2
        /* Analog */
        struct v4l2_device v4l2_dev;
+#endif
        int users;
        unsigned int resources; /* resources in use */
        struct video_device *vdev;
index 95b5d6e7cdc400d348dcb7462f7806c68e578a43..be17192836099c4e1759e2e7a9d41cf7e9cf3a33 100644 (file)
@@ -328,7 +328,7 @@ static void cpia2_usb_complete(struct urb *urb)
                                continue;
                        }
                        DBG("Start of frame pattern found\n");
-                       do_gettimeofday(&cam->workbuff->timestamp);
+                       v4l2_get_timestamp(&cam->workbuff->timestamp);
                        cam->workbuff->seq = cam->frame_count++;
                        cam->workbuff->data[0] = 0xFF;
                        cam->workbuff->data[1] = 0xD8;
index aeb9d227572583e077a134e6133d9766793cc215..d5d42b6e94be128d49ec8a4dd2a0d8c452c42f48 100644 (file)
@@ -825,6 +825,8 @@ static int cpia2_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
        else
                buf->flags = 0;
 
+       buf->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+
        switch (cam->buffers[buf->index].status) {
        case FRAME_EMPTY:
        case FRAME_ERROR:
@@ -943,7 +945,8 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 
        buf->index = frame;
        buf->bytesused = cam->buffers[buf->index].length;
-       buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
+       buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE
+               | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        buf->field = V4L2_FIELD_NONE;
        buf->timestamp = cam->buffers[buf->index].timestamp;
        buf->sequence = cam->buffers[buf->index].seq;
index b024e5197a755fa01cc36fff2be2c7be1a876740..28688dbcb6090cfab70386e7ac03b3526875598e 100644 (file)
@@ -1291,7 +1291,7 @@ static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *ur
 
                        buf->vb.state = VIDEOBUF_DONE;
                        buf->vb.field_count++;
-                       do_gettimeofday(&buf->vb.ts);
+                       v4l2_get_timestamp(&buf->vb.ts);
                        list_del(&buf->vb.queue);
                        wake_up(&buf->vb.done);
                        dma_q->mpeg_buffer_completed = 0;
@@ -1327,7 +1327,7 @@ static void buffer_filled(char *data, int len, struct urb *urb,
                memcpy(vbuf, data, len);
                buf->vb.state = VIDEOBUF_DONE;
                buf->vb.field_count++;
-               do_gettimeofday(&buf->vb.ts);
+               v4l2_get_timestamp(&buf->vb.ts);
                list_del(&buf->vb.queue);
                wake_up(&buf->vb.done);
 
index ac7db52f404ffbc9c95207f7a2bd5b1414aa4187..46e3892557c2127b3e022b85056d529ec2d02f4c 100644 (file)
@@ -530,7 +530,7 @@ static inline void vbi_buffer_filled(struct cx231xx *dev,
 
        buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
+       v4l2_get_timestamp(&buf->vb.ts);
 
        dev->vbi_mode.bulk_ctl.buf = NULL;
 
index fedf7852a355c8e2fff3575769b0237c3fa33105..239cb913be5ccaed49b9594825c23509183ae99c 100644 (file)
@@ -235,7 +235,7 @@ static inline void buffer_filled(struct cx231xx *dev,
        cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
        buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
+       v4l2_get_timestamp(&buf->vb.ts);
 
        if (dev->USE_ISO)
                dev->video_mode.isoc_ctl.buf = NULL;
index 47204280b8b3d1f5b557417a27d32430bccb2c21..fbc0a84465eb9f80f839c188b32020372b14e18d 100644 (file)
@@ -643,7 +643,8 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
        struct it913x_state *st = d->priv;
        int ret = 0;
        u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
-       u16 ep_size = adap->stream.buf_size / 4;
+       u16 ep_size = (adap->pid_filtering) ? TS_BUFFER_SIZE_PID / 4 :
+               TS_BUFFER_SIZE_MAX / 4;
        u8 pkt_size = 0x80;
 
        if (d->udev->speed != USB_SPEED_HIGH)
index 9382895b1b88ba664e7f552b9ceb846b34cdde90..937c744217c8c2470264692b758f02ec8c1c0e20 100644 (file)
 #define DW2102_RC_QUERY (0x1a00)
 #define DW2102_LED_CTRL (0x1b00)
 
+#define DW2101_FIRMWARE "dvb-usb-dw2101.fw"
+#define DW2102_FIRMWARE "dvb-usb-dw2102.fw"
+#define DW2104_FIRMWARE "dvb-usb-dw2104.fw"
+#define DW3101_FIRMWARE "dvb-usb-dw3101.fw"
+#define S630_FIRMWARE   "dvb-usb-s630.fw"
+#define S660_FIRMWARE   "dvb-usb-s660.fw"
+#define P1100_FIRMWARE  "dvb-usb-p1100.fw"
+#define P7500_FIRMWARE  "dvb-usb-p7500.fw"
+
 #define        err_str "did not find the firmware file. (%s) " \
                "Please see linux/Documentation/dvb/ for more details " \
                "on firmware-problems."
@@ -1478,13 +1487,12 @@ static int dw2102_load_firmware(struct usb_device *dev,
        u8 reset;
        u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
        const struct firmware *fw;
-       const char *fw_2101 = "dvb-usb-dw2101.fw";
 
        switch (dev->descriptor.idProduct) {
        case 0x2101:
-               ret = request_firmware(&fw, fw_2101, &dev->dev);
+               ret = request_firmware(&fw, DW2101_FIRMWARE, &dev->dev);
                if (ret != 0) {
-                       err(err_str, fw_2101);
+                       err(err_str, DW2101_FIRMWARE);
                        return ret;
                }
                break;
@@ -1586,7 +1594,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
 static struct dvb_usb_device_properties dw2102_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
-       .firmware = "dvb-usb-dw2102.fw",
+       .firmware = DW2102_FIRMWARE,
        .no_reconnect = 1,
 
        .i2c_algo = &dw2102_serit_i2c_algo,
@@ -1641,7 +1649,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
 static struct dvb_usb_device_properties dw2104_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
-       .firmware = "dvb-usb-dw2104.fw",
+       .firmware = DW2104_FIRMWARE,
        .no_reconnect = 1,
 
        .i2c_algo = &dw2104_i2c_algo,
@@ -1691,7 +1699,7 @@ static struct dvb_usb_device_properties dw2104_properties = {
 static struct dvb_usb_device_properties dw3101_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
-       .firmware = "dvb-usb-dw3101.fw",
+       .firmware = DW3101_FIRMWARE,
        .no_reconnect = 1,
 
        .i2c_algo = &dw3101_i2c_algo,
@@ -1739,7 +1747,7 @@ static struct dvb_usb_device_properties s6x0_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
        .size_of_priv = sizeof(struct s6x0_state),
-       .firmware = "dvb-usb-s630.fw",
+       .firmware = S630_FIRMWARE,
        .no_reconnect = 1,
 
        .i2c_algo = &s6x0_i2c_algo,
@@ -1879,7 +1887,7 @@ static int dw2102_probe(struct usb_interface *intf,
                return -ENOMEM;
        /* copy default structure */
        /* fill only different fields */
-       p1100->firmware = "dvb-usb-p1100.fw";
+       p1100->firmware = P1100_FIRMWARE;
        p1100->devices[0] = d1100;
        p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
        p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
@@ -1891,7 +1899,7 @@ static int dw2102_probe(struct usb_interface *intf,
                kfree(p1100);
                return -ENOMEM;
        }
-       s660->firmware = "dvb-usb-s660.fw";
+       s660->firmware = S660_FIRMWARE;
        s660->num_device_descs = 3;
        s660->devices[0] = d660;
        s660->devices[1] = d480_1;
@@ -1905,7 +1913,7 @@ static int dw2102_probe(struct usb_interface *intf,
                kfree(s660);
                return -ENOMEM;
        }
-       p7500->firmware = "dvb-usb-p7500.fw";
+       p7500->firmware = P7500_FIRMWARE;
        p7500->devices[0] = d7500;
        p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
        p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
@@ -1949,3 +1957,11 @@ MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
                                " Geniatech SU3000 devices");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(DW2101_FIRMWARE);
+MODULE_FIRMWARE(DW2102_FIRMWARE);
+MODULE_FIRMWARE(DW2104_FIRMWARE);
+MODULE_FIRMWARE(DW3101_FIRMWARE);
+MODULE_FIRMWARE(S630_FIRMWARE);
+MODULE_FIRMWARE(S660_FIRMWARE);
+MODULE_FIRMWARE(P1100_FIRMWARE);
+MODULE_FIRMWARE(P7500_FIRMWARE);
index 7a5bd61bd3bbb039fdb74bbb291bd1110d67ab02..094c4ecf086da6bbcc0f4ca421734f95a0f1555f 100644 (file)
@@ -34,6 +34,7 @@ config VIDEO_EM28XX_DVB
        tristate "DVB/ATSC Support for em28xx based TV cards"
        depends on VIDEO_EM28XX && DVB_CORE
        select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_S921 if MEDIA_SUBDRV_AUTOSELECT
@@ -43,6 +44,10 @@ config VIDEO_EM28XX_DVB
        select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
        select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
        select VIDEOBUF_DVB
        ---help---
          This adds support for DVB cards based on the
index 619bffbab3bc050f2cb2f1f1929bd5da1bdd91a8..ad6c800d9a406fdfcda3926a194f389463cc9f19 100644 (file)
@@ -6,6 +6,7 @@
                      Markus Rechberger <mrechberger@gmail.com>
                      Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
+   Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
 
    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
@@ -60,6 +61,11 @@ static unsigned int card[]     = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
 module_param_array(card,  int, NULL, 0444);
 MODULE_PARM_DESC(card,     "card type");
 
+static int prefer_bulk = -1;
+module_param(prefer_bulk, int, 0444);
+MODULE_PARM_DESC(prefer_bulk, "prefer USB bulk transfers (-1 = auto, 0 = isoc, 1 = bulk)");
+
+
 /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
 static unsigned long em28xx_devused;
 
@@ -2951,6 +2957,8 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
                           int minor)
 {
        int retval;
+       static const char *default_chip_name = "em28xx";
+       const char *chip_name = default_chip_name;
 
        dev->udev = udev;
        mutex_init(&dev->ctrl_urb_lock);
@@ -2978,51 +2986,62 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 
                switch (dev->chip_id) {
                case CHIP_ID_EM2800:
-                       em28xx_info("chip ID is em2800\n");
+                       chip_name = "em2800";
                        break;
                case CHIP_ID_EM2710:
-                       em28xx_info("chip ID is em2710\n");
+                       chip_name = "em2710";
                        break;
                case CHIP_ID_EM2750:
-                       em28xx_info("chip ID is em2750\n");
+                       chip_name = "em2750";
                        break;
                case CHIP_ID_EM2820:
-                       em28xx_info("chip ID is em2820 (or em2710)\n");
+                       chip_name = "em2710/2820";
                        break;
                case CHIP_ID_EM2840:
-                       em28xx_info("chip ID is em2840\n");
+                       chip_name = "em2840";
                        break;
                case CHIP_ID_EM2860:
-                       em28xx_info("chip ID is em2860\n");
+                       chip_name = "em2860";
                        break;
                case CHIP_ID_EM2870:
-                       em28xx_info("chip ID is em2870\n");
+                       chip_name = "em2870";
                        dev->wait_after_write = 0;
                        break;
                case CHIP_ID_EM2874:
-                       em28xx_info("chip ID is em2874\n");
+                       chip_name = "em2874";
                        dev->reg_gpio_num = EM2874_R80_GPIO;
                        dev->wait_after_write = 0;
                        break;
                case CHIP_ID_EM28174:
-                       em28xx_info("chip ID is em28174\n");
+                       chip_name = "em28174";
                        dev->reg_gpio_num = EM2874_R80_GPIO;
                        dev->wait_after_write = 0;
                        break;
                case CHIP_ID_EM2883:
-                       em28xx_info("chip ID is em2882/em2883\n");
+                       chip_name = "em2882/3";
                        dev->wait_after_write = 0;
                        break;
                case CHIP_ID_EM2884:
-                       em28xx_info("chip ID is em2884\n");
+                       chip_name = "em2884";
                        dev->reg_gpio_num = EM2874_R80_GPIO;
                        dev->wait_after_write = 0;
                        break;
                default:
-                       em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
+                       printk(KERN_INFO DRIVER_NAME
+                              ": unknown em28xx chip ID (%d)\n", dev->chip_id);
                }
        }
 
+       if (chip_name != default_chip_name)
+               printk(KERN_INFO DRIVER_NAME
+                      ": chip ID is %s\n", chip_name);
+
+       /*
+        * For em2820/em2710, the name may change latter, after checking
+        * if the device has a sensor (so, it is em2710) or not.
+        */
+       snprintf(dev->name, sizeof(dev->name), "%s #%d", chip_name, dev->devno);
+
        if (dev->is_audio_only) {
                retval = em28xx_audio_setup(dev);
                if (retval)
@@ -3039,6 +3058,14 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 
        em28xx_pre_card_setup(dev);
 
+       if (dev->chip_id == CHIP_ID_EM2820) {
+               if (dev->board.is_webcam)
+                       chip_name = "em2710";
+               else
+                       chip_name = "em2820";
+               snprintf(dev->name, sizeof(dev->name), "%s #%d", chip_name, dev->devno);
+       }
+
        if (!dev->board.is_em2800) {
                /* Resets I2C speed */
                retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
@@ -3143,7 +3170,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        struct em28xx *dev = NULL;
        int retval;
        bool has_audio = false, has_video = false, has_dvb = false;
-       int i, nr;
+       int i, nr, try_bulk;
        const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
        char *speed;
 
@@ -3183,9 +3210,10 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        }
 
        /* compute alternate max packet sizes */
-       dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) *
+       dev->alt_max_pkt_size_isoc =
+                               kmalloc(sizeof(dev->alt_max_pkt_size_isoc[0]) *
                                        interface->num_altsetting, GFP_KERNEL);
-       if (dev->alt_max_pkt_size == NULL) {
+       if (dev->alt_max_pkt_size_isoc == NULL) {
                em28xx_errdev("out of memory!\n");
                kfree(dev);
                retval = -ENOMEM;
@@ -3208,25 +3236,67 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                        if (udev->speed == USB_SPEED_HIGH)
                                size = size * hb_mult(sizedescr);
 
-                       if (usb_endpoint_xfer_isoc(e) &&
-                           usb_endpoint_dir_in(e)) {
+                       if (usb_endpoint_dir_in(e)) {
                                switch (e->bEndpointAddress) {
-                               case EM28XX_EP_AUDIO:
-                                       has_audio = true;
-                                       break;
-                               case EM28XX_EP_ANALOG:
+                               case 0x82:
                                        has_video = true;
-                                       dev->alt_max_pkt_size[i] = size;
+                                       if (usb_endpoint_xfer_isoc(e)) {
+                                               dev->analog_ep_isoc =
+                                                           e->bEndpointAddress;
+                                               dev->alt_max_pkt_size_isoc[i] = size;
+                                       } else if (usb_endpoint_xfer_bulk(e)) {
+                                               dev->analog_ep_bulk =
+                                                           e->bEndpointAddress;
+                                       }
+                                       break;
+                               case 0x83:
+                                       if (usb_endpoint_xfer_isoc(e)) {
+                                               has_audio = true;
+                                       } else {
+                                               printk(KERN_INFO DRIVER_NAME
+                                               ": error: skipping audio endpoint 0x83, because it uses bulk transfers !\n");
+                                       }
                                        break;
-                               case EM28XX_EP_DIGITAL:
-                                       has_dvb = true;
-                                       if (size > dev->dvb_max_pkt_size) {
-                                               dev->dvb_max_pkt_size = size;
-                                               dev->dvb_alt = i;
+                               case 0x84:
+                                       if (has_video &&
+                                           (usb_endpoint_xfer_bulk(e))) {
+                                               dev->analog_ep_bulk =
+                                                           e->bEndpointAddress;
+                                       } else {
+                                               has_dvb = true;
+                                               if (usb_endpoint_xfer_isoc(e)) {
+                                                       dev->dvb_ep_isoc = e->bEndpointAddress;
+                                                       if (size > dev->dvb_max_pkt_size_isoc) {
+                                                               dev->dvb_max_pkt_size_isoc = size;
+                                                               dev->dvb_alt_isoc = i;
+                                                       }
+                                               } else {
+                                                       dev->dvb_ep_bulk = e->bEndpointAddress;
+                                               }
                                        }
                                        break;
                                }
                        }
+                       /* NOTE:
+                        * Old logic with support for isoc transfers only was:
+                        *  0x82        isoc            => analog
+                        *  0x83        isoc            => audio
+                        *  0x84        isoc            => digital
+                        *
+                        * New logic with support for bulk transfers
+                        *  0x82        isoc            => analog
+                        *  0x82        bulk            => analog
+                        *  0x83        isoc*           => audio
+                        *  0x84        isoc            => digital
+                        *  0x84        bulk            => analog or digital**
+                        * (*: audio should always be isoc)
+                        * (**: analog, if ep 0x82 is isoc, otherwise digital)
+                        *
+                        * The new logic preserves backwards compatibility and
+                        * reflects the endpoint configurations we have seen
+                        * so far. But there might be devices for which this
+                        * logic is not sufficient...
+                        */
                }
        }
 
@@ -3261,19 +3331,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                ifnum,
                interface->altsetting->desc.bInterfaceNumber);
 
-       if (has_audio)
-               printk(KERN_INFO DRIVER_NAME
-                      ": Audio Vendor Class interface %i found\n",
-                      ifnum);
-       if (has_video)
-               printk(KERN_INFO DRIVER_NAME
-                      ": Video interface %i found\n",
-                      ifnum);
-       if (has_dvb)
-               printk(KERN_INFO DRIVER_NAME
-                      ": DVB interface %i found\n",
-                      ifnum);
-
        /*
         * Make sure we have 480 Mbps of bandwidth, otherwise things like
         * video stream wouldn't likely work, since 12 Mbps is generally
@@ -3287,7 +3344,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                goto err_free;
        }
 
-       snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
        dev->devno = nr;
        dev->model = id->driver_info;
        dev->alt   = -1;
@@ -3304,6 +3360,24 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                }
        }
 
+       if (has_audio)
+               printk(KERN_INFO DRIVER_NAME
+                      ": Audio interface %i found %s\n",
+                      ifnum,
+                      dev->has_audio_class ? "(USB Audio Class)" : "(Vendor Class)");
+       if (has_video)
+               printk(KERN_INFO DRIVER_NAME
+                      ": Video interface %i found:%s%s\n",
+                      ifnum,
+                      dev->analog_ep_bulk ? " bulk" : "",
+                      dev->analog_ep_isoc ? " isoc" : "");
+       if (has_dvb)
+               printk(KERN_INFO DRIVER_NAME
+                      ": DVB interface %i found:%s%s\n",
+                      ifnum,
+                      dev->dvb_ep_bulk ? " bulk" : "",
+                      dev->dvb_ep_isoc ? " isoc" : "");
+
        dev->num_alt = interface->num_altsetting;
 
        if ((unsigned)card[nr] < em28xx_bcount)
@@ -3320,13 +3394,46 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                goto unlock_and_free;
        }
 
+       if (prefer_bulk < 0) {
+               if (dev->board.is_webcam)
+                       try_bulk = 1;
+               else
+                       try_bulk = 0;
+       } else {
+               try_bulk = prefer_bulk > 0;
+       }
+
+       /* Select USB transfer types to use */
+       if (has_video) {
+           if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk))
+               dev->analog_xfer_bulk = 1;
+               em28xx_info("analog set to %s mode.\n",
+                           dev->analog_xfer_bulk ? "bulk" : "isoc");
+       }
        if (has_dvb) {
-               /* pre-allocate DVB isoc transfer buffers */
-               retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE,
-                                          EM28XX_DVB_MAX_PACKETS,
-                                          EM28XX_DVB_NUM_BUFS,
-                                          dev->dvb_max_pkt_size);
+           if (!dev->dvb_ep_isoc || (try_bulk && dev->dvb_ep_bulk))
+               dev->dvb_xfer_bulk = 1;
+
+               em28xx_info("dvb set to %s mode.\n",
+                           dev->dvb_xfer_bulk ? "bulk" : "isoc");
+
+               /* pre-allocate DVB usb transfer buffers */
+               if (dev->dvb_xfer_bulk) {
+                       retval = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE,
+                                           dev->dvb_xfer_bulk,
+                                           EM28XX_DVB_NUM_BUFS,
+                                           512,
+                                           EM28XX_DVB_BULK_PACKET_MULTIPLIER);
+               } else {
+                       retval = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE,
+                                           dev->dvb_xfer_bulk,
+                                           EM28XX_DVB_NUM_BUFS,
+                                           dev->dvb_max_pkt_size_isoc,
+                                           EM28XX_DVB_NUM_ISOC_PACKETS);
+               }
                if (retval) {
+                       printk(DRIVER_NAME
+                              ": Failed to pre-allocate USB transfer buffers for DVB.\n");
                        goto unlock_and_free;
                }
        }
@@ -3344,7 +3451,7 @@ unlock_and_free:
        mutex_unlock(&dev->lock);
 
 err_free:
-       kfree(dev->alt_max_pkt_size);
+       kfree(dev->alt_max_pkt_size_isoc);
        kfree(dev);
 
 err:
@@ -3394,7 +3501,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
                     video_device_node_name(dev->vdev));
 
                dev->state |= DEV_MISCONFIGURED;
-               em28xx_uninit_isoc(dev, dev->mode);
+               em28xx_uninit_usb_xfer(dev, dev->mode);
                dev->state |= DEV_DISCONNECTED;
        } else {
                dev->state |= DEV_DISCONNECTED;
@@ -3402,14 +3509,14 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
        }
 
        /* free DVB isoc buffers */
-       em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE);
+       em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE);
 
        mutex_unlock(&dev->lock);
 
        em28xx_close_extension(dev);
 
        if (!dev->users) {
-               kfree(dev->alt_max_pkt_size);
+               kfree(dev->alt_max_pkt_size_isoc);
                kfree(dev);
        }
 }
index bed07a6c33f8156df80919725c05857cd0fd9b37..b10d959fefe5a11cffc396b1f4623e0a924fa377 100644 (file)
@@ -5,6 +5,7 @@
                      Markus Rechberger <mrechberger@gmail.com>
                      Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
+   Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
 
    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
@@ -804,21 +805,23 @@ int em28xx_resolution_set(struct em28xx *dev)
        return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
 }
 
+/* Set USB alternate setting for analog video */
 int em28xx_set_alternate(struct em28xx *dev)
 {
        int errCode, prev_alt = dev->alt;
        int i;
        unsigned int min_pkt_size = dev->width * 2 + 4;
 
-       /*
-        * alt = 0 is used only for control messages, so, only values
-        * greater than 0 can be used for streaming.
-        */
-       if (alt && alt < dev->num_alt) {
+       /* NOTE: for isoc transfers, only alt settings > 0 are allowed
+                for bulk transfers, use alt=0 as default value */
+       dev->alt = 0;
+       if ((alt > 0) && (alt < dev->num_alt)) {
                em28xx_coredbg("alternate forced to %d\n", dev->alt);
                dev->alt = alt;
                goto set_alt;
        }
+       if (dev->analog_xfer_bulk)
+               goto set_alt;
 
        /* When image size is bigger than a certain value,
           the frame size should be increased, otherwise, only
@@ -829,22 +832,29 @@ int em28xx_set_alternate(struct em28xx *dev)
 
        for (i = 0; i < dev->num_alt; i++) {
                /* stop when the selected alt setting offers enough bandwidth */
-               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
+               if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
                        dev->alt = i;
                        break;
                /* otherwise make sure that we end up with the maximum bandwidth
                   because the min_pkt_size equation might be wrong...
                */
-               } else if (dev->alt_max_pkt_size[i] >
-                          dev->alt_max_pkt_size[dev->alt])
+               } else if (dev->alt_max_pkt_size_isoc[i] >
+                          dev->alt_max_pkt_size_isoc[dev->alt])
                        dev->alt = i;
        }
 
 set_alt:
        if (dev->alt != prev_alt) {
-               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
-                               min_pkt_size, dev->alt);
-               dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+               if (dev->analog_xfer_bulk) {
+                       dev->max_pkt_size = 512; /* USB 2.0 spec */
+                       dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
+               } else { /* isoc */
+                       em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+                                      min_pkt_size, dev->alt);
+                       dev->max_pkt_size =
+                                         dev->alt_max_pkt_size_isoc[dev->alt];
+                       dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
+               }
                em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
                               dev->alt, dev->max_pkt_size);
                errCode = usb_set_interface(dev->udev, 0, dev->alt);
@@ -919,7 +929,7 @@ EXPORT_SYMBOL_GPL(em28xx_set_mode);
    ------------------------------------------------------------------*/
 
 /*
- * IRQ callback, called by URB callback
+ * URB completion handler for isoc/bulk transfers
  */
 static void em28xx_irq_callback(struct urb *urb)
 {
@@ -941,11 +951,12 @@ static void em28xx_irq_callback(struct urb *urb)
 
        /* Copy data from URB */
        spin_lock(&dev->slock);
-       dev->isoc_ctl.isoc_copy(dev, urb);
+       dev->usb_ctl.urb_data_copy(dev, urb);
        spin_unlock(&dev->slock);
 
        /* Reset urb buffers */
        for (i = 0; i < urb->number_of_packets; i++) {
+               /* isoc only (bulk: number_of_packets = 0) */
                urb->iso_frame_desc[i].status = 0;
                urb->iso_frame_desc[i].actual_length = 0;
        }
@@ -961,49 +972,50 @@ static void em28xx_irq_callback(struct urb *urb)
 /*
  * Stop and Deallocate URBs
  */
-void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode)
+void em28xx_uninit_usb_xfer(struct em28xx *dev, enum em28xx_mode mode)
 {
        struct urb *urb;
-       struct em28xx_usb_isoc_bufs *isoc_bufs;
+       struct em28xx_usb_bufs *usb_bufs;
        int i;
 
-       em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode);
+       em28xx_isocdbg("em28xx: called em28xx_uninit_usb_xfer in mode %d\n",
+                      mode);
 
        if (mode == EM28XX_DIGITAL_MODE)
-               isoc_bufs = &dev->isoc_ctl.digital_bufs;
+               usb_bufs = &dev->usb_ctl.digital_bufs;
        else
-               isoc_bufs = &dev->isoc_ctl.analog_bufs;
+               usb_bufs = &dev->usb_ctl.analog_bufs;
 
-       for (i = 0; i < isoc_bufs->num_bufs; i++) {
-               urb = isoc_bufs->urb[i];
+       for (i = 0; i < usb_bufs->num_bufs; i++) {
+               urb = usb_bufs->urb[i];
                if (urb) {
                        if (!irqs_disabled())
                                usb_kill_urb(urb);
                        else
                                usb_unlink_urb(urb);
 
-                       if (isoc_bufs->transfer_buffer[i]) {
+                       if (usb_bufs->transfer_buffer[i]) {
                                usb_free_coherent(dev->udev,
                                        urb->transfer_buffer_length,
-                                       isoc_bufs->transfer_buffer[i],
+                                       usb_bufs->transfer_buffer[i],
                                        urb->transfer_dma);
                        }
                        usb_free_urb(urb);
-                       isoc_bufs->urb[i] = NULL;
+                       usb_bufs->urb[i] = NULL;
                }
-               isoc_bufs->transfer_buffer[i] = NULL;
+               usb_bufs->transfer_buffer[i] = NULL;
        }
 
-       kfree(isoc_bufs->urb);
-       kfree(isoc_bufs->transfer_buffer);
+       kfree(usb_bufs->urb);
+       kfree(usb_bufs->transfer_buffer);
 
-       isoc_bufs->urb = NULL;
-       isoc_bufs->transfer_buffer = NULL;
-       isoc_bufs->num_bufs = 0;
+       usb_bufs->urb = NULL;
+       usb_bufs->transfer_buffer = NULL;
+       usb_bufs->num_bufs = 0;
 
        em28xx_capture_start(dev, 0);
 }
-EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
+EXPORT_SYMBOL_GPL(em28xx_uninit_usb_xfer);
 
 /*
  * Stop URBs
@@ -1012,7 +1024,7 @@ void em28xx_stop_urbs(struct em28xx *dev)
 {
        int i;
        struct urb *urb;
-       struct em28xx_usb_isoc_bufs *isoc_bufs = &dev->isoc_ctl.digital_bufs;
+       struct em28xx_usb_bufs *isoc_bufs = &dev->usb_ctl.digital_bufs;
 
        em28xx_isocdbg("em28xx: called em28xx_stop_urbs\n");
 
@@ -1033,10 +1045,10 @@ EXPORT_SYMBOL_GPL(em28xx_stop_urbs);
 /*
  * Allocate URBs
  */
-int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                     int max_packets, int num_bufs, int max_pkt_size)
+int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
+                     int num_bufs, int max_pkt_size, int packet_multiplier)
 {
-       struct em28xx_usb_isoc_bufs *isoc_bufs;
+       struct em28xx_usb_bufs *usb_bufs;
        int i;
        int sb_size, pipe;
        struct urb *urb;
@@ -1044,140 +1056,180 @@ int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
 
        em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode);
 
-       if (mode == EM28XX_DIGITAL_MODE)
-               isoc_bufs = &dev->isoc_ctl.digital_bufs;
-       else
-               isoc_bufs = &dev->isoc_ctl.analog_bufs;
+       /* Check mode and if we have an endpoint for the selected
+          transfer type, select buffer                          */
+       if (mode == EM28XX_DIGITAL_MODE) {
+               if ((xfer_bulk && !dev->dvb_ep_bulk) ||
+                   (!xfer_bulk && !dev->dvb_ep_isoc)) {
+                       em28xx_errdev("no endpoint for DVB mode and transfer type %d\n",
+                                     xfer_bulk > 0);
+                       return -EINVAL;
+               }
+               usb_bufs = &dev->usb_ctl.digital_bufs;
+       } else if (mode == EM28XX_ANALOG_MODE) {
+               if ((xfer_bulk && !dev->analog_ep_bulk) ||
+                   (!xfer_bulk && !dev->analog_ep_isoc)) {
+                       em28xx_errdev("no endpoint for analog mode and transfer type %d\n",
+                                      xfer_bulk > 0);
+                       return -EINVAL;
+               }
+               usb_bufs = &dev->usb_ctl.analog_bufs;
+       } else {
+               em28xx_errdev("invalid mode selected\n");
+               return -EINVAL;
+       }
 
        /* De-allocates all pending stuff */
-       em28xx_uninit_isoc(dev, mode);
+       em28xx_uninit_usb_xfer(dev, mode);
 
-       isoc_bufs->num_bufs = num_bufs;
+       usb_bufs->num_bufs = num_bufs;
 
-       isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
-       if (!isoc_bufs->urb) {
+       usb_bufs->urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
+       if (!usb_bufs->urb) {
                em28xx_errdev("cannot alloc memory for usb buffers\n");
                return -ENOMEM;
        }
 
-       isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+       usb_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
                                             GFP_KERNEL);
-       if (!isoc_bufs->transfer_buffer) {
+       if (!usb_bufs->transfer_buffer) {
                em28xx_errdev("cannot allocate memory for usb transfer\n");
-               kfree(isoc_bufs->urb);
+               kfree(usb_bufs->urb);
                return -ENOMEM;
        }
 
-       isoc_bufs->max_pkt_size = max_pkt_size;
-       isoc_bufs->num_packets = max_packets;
-       dev->isoc_ctl.vid_buf = NULL;
-       dev->isoc_ctl.vbi_buf = NULL;
+       usb_bufs->max_pkt_size = max_pkt_size;
+       if (xfer_bulk)
+               usb_bufs->num_packets = 0;
+       else
+               usb_bufs->num_packets = packet_multiplier;
+       dev->usb_ctl.vid_buf = NULL;
+       dev->usb_ctl.vbi_buf = NULL;
 
-       sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size;
+       sb_size = packet_multiplier * usb_bufs->max_pkt_size;
 
        /* allocate urbs and transfer buffers */
-       for (i = 0; i < isoc_bufs->num_bufs; i++) {
-               urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL);
+       for (i = 0; i < usb_bufs->num_bufs; i++) {
+               urb = usb_alloc_urb(usb_bufs->num_packets, GFP_KERNEL);
                if (!urb) {
-                       em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
-                       em28xx_uninit_isoc(dev, mode);
+                       em28xx_err("cannot alloc usb_ctl.urb %i\n", i);
+                       em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }
-               isoc_bufs->urb[i] = urb;
+               usb_bufs->urb[i] = urb;
 
-               isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+               usb_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev,
                        sb_size, GFP_KERNEL, &urb->transfer_dma);
-               if (!isoc_bufs->transfer_buffer[i]) {
+               if (!usb_bufs->transfer_buffer[i]) {
                        em28xx_err("unable to allocate %i bytes for transfer"
                                        " buffer %i%s\n",
                                        sb_size, i,
                                        in_interrupt() ? " while in int" : "");
-                       em28xx_uninit_isoc(dev, mode);
+                       em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }
-               memset(isoc_bufs->transfer_buffer[i], 0, sb_size);
-
-               /* FIXME: this is a hack - should be
-                       'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
-                       should also be using 'desc.bInterval'
-                */
-               pipe = usb_rcvisocpipe(dev->udev,
-                                      mode == EM28XX_ANALOG_MODE ?
-                                      EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL);
-
-               usb_fill_int_urb(urb, dev->udev, pipe,
-                                isoc_bufs->transfer_buffer[i], sb_size,
-                                em28xx_irq_callback, dev, 1);
-
-               urb->number_of_packets = isoc_bufs->num_packets;
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-
-               k = 0;
-               for (j = 0; j < isoc_bufs->num_packets; j++) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                                               isoc_bufs->max_pkt_size;
-                       k += isoc_bufs->max_pkt_size;
+               memset(usb_bufs->transfer_buffer[i], 0, sb_size);
+
+               if (xfer_bulk) { /* bulk */
+                       pipe = usb_rcvbulkpipe(dev->udev,
+                                              mode == EM28XX_ANALOG_MODE ?
+                                              dev->analog_ep_bulk :
+                                              dev->dvb_ep_bulk);
+                       usb_fill_bulk_urb(urb, dev->udev, pipe,
+                                         usb_bufs->transfer_buffer[i], sb_size,
+                                         em28xx_irq_callback, dev);
+                       urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+               } else { /* isoc */
+                       pipe = usb_rcvisocpipe(dev->udev,
+                                              mode == EM28XX_ANALOG_MODE ?
+                                              dev->analog_ep_isoc :
+                                              dev->dvb_ep_isoc);
+                       usb_fill_int_urb(urb, dev->udev, pipe,
+                                        usb_bufs->transfer_buffer[i], sb_size,
+                                        em28xx_irq_callback, dev, 1);
+                       urb->transfer_flags = URB_ISO_ASAP |
+                                             URB_NO_TRANSFER_DMA_MAP;
+                       k = 0;
+                       for (j = 0; j < usb_bufs->num_packets; j++) {
+                               urb->iso_frame_desc[j].offset = k;
+                               urb->iso_frame_desc[j].length =
+                                                       usb_bufs->max_pkt_size;
+                               k += usb_bufs->max_pkt_size;
+                       }
                }
+
+               urb->number_of_packets = usb_bufs->num_packets;
        }
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(em28xx_alloc_isoc);
+EXPORT_SYMBOL_GPL(em28xx_alloc_urbs);
 
 /*
  * Allocate URBs and start IRQ
  */
-int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                    int max_packets, int num_bufs, int max_pkt_size,
-                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
+int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
+                   int xfer_bulk, int num_bufs, int max_pkt_size,
+                   int packet_multiplier,
+                   int (*urb_data_copy) (struct em28xx *dev, struct urb *urb))
 {
        struct em28xx_dmaqueue *dma_q = &dev->vidq;
        struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
-       struct em28xx_usb_isoc_bufs *isoc_bufs;
+       struct em28xx_usb_bufs *usb_bufs;
        int i;
        int rc;
        int alloc;
 
-       em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode);
+       em28xx_isocdbg("em28xx: called em28xx_init_usb_xfer in mode %d\n",
+                      mode);
 
-       dev->isoc_ctl.isoc_copy = isoc_copy;
+       dev->usb_ctl.urb_data_copy = urb_data_copy;
 
        if (mode == EM28XX_DIGITAL_MODE) {
-               isoc_bufs = &dev->isoc_ctl.digital_bufs;
-               /* no need to free/alloc isoc buffers in digital mode */
+               usb_bufs = &dev->usb_ctl.digital_bufs;
+               /* no need to free/alloc usb buffers in digital mode */
                alloc = 0;
        } else {
-               isoc_bufs = &dev->isoc_ctl.analog_bufs;
+               usb_bufs = &dev->usb_ctl.analog_bufs;
                alloc = 1;
        }
 
        if (alloc) {
-               rc = em28xx_alloc_isoc(dev, mode, max_packets,
-                                      num_bufs, max_pkt_size);
+               rc = em28xx_alloc_urbs(dev, mode, xfer_bulk, num_bufs,
+                                      max_pkt_size, packet_multiplier);
                if (rc)
                        return rc;
        }
 
+       if (xfer_bulk) {
+               rc = usb_clear_halt(dev->udev, usb_bufs->urb[0]->pipe);
+               if (rc < 0) {
+                       em28xx_err("failed to clear USB bulk endpoint stall/halt condition (error=%i)\n",
+                                  rc);
+                       em28xx_uninit_usb_xfer(dev, mode);
+                       return rc;
+               }
+       }
+
        init_waitqueue_head(&dma_q->wq);
        init_waitqueue_head(&vbi_dma_q->wq);
 
        em28xx_capture_start(dev, 1);
 
        /* submit urbs and enables IRQ */
-       for (i = 0; i < isoc_bufs->num_bufs; i++) {
-               rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC);
+       for (i = 0; i < usb_bufs->num_bufs; i++) {
+               rc = usb_submit_urb(usb_bufs->urb[i], GFP_ATOMIC);
                if (rc) {
                        em28xx_err("submit of urb %i failed (error=%i)\n", i,
                                   rc);
-                       em28xx_uninit_isoc(dev, mode);
+                       em28xx_uninit_usb_xfer(dev, mode);
                        return rc;
                }
        }
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(em28xx_init_isoc);
+EXPORT_SYMBOL_GPL(em28xx_init_usb_xfer);
 
 /*
  * em28xx_wake_i2c()
index 63f2e7070c005d8ed05af171bd1d80c6006295f4..a70b19e07e370ab4f84dc61277bf9cc9f674fb48 100644 (file)
@@ -10,6 +10,8 @@
 
  (c) 2008 Aidan Thornton <makosoft@googlemail.com>
 
+ (c) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
+
  Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
        (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
        (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
@@ -124,9 +126,9 @@ static inline void print_err_status(struct em28xx *dev,
        }
 }
 
-static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+static inline int em28xx_dvb_urb_data_copy(struct em28xx *dev, struct urb *urb)
 {
-       int i;
+       int xfer_bulk, num_packets, i;
 
        if (!dev)
                return 0;
@@ -134,24 +136,37 @@ static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
        if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
                return 0;
 
-       if (urb->status < 0) {
+       if (urb->status < 0)
                print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
 
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
+       xfer_bulk = usb_pipebulk(urb->pipe);
 
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
+       if (xfer_bulk) /* bulk */
+               num_packets = 1;
+       else /* isoc */
+               num_packets = urb->number_of_packets;
 
-               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
-                                urb->iso_frame_desc[i].offset,
-                                urb->iso_frame_desc[i].actual_length);
+       for (i = 0; i < num_packets; i++) {
+               if (xfer_bulk) {
+                       if (urb->status < 0) {
+                               print_err_status(dev, i, urb->status);
+                               if (urb->status != -EPROTO)
+                                       continue;
+                       }
+                       dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
+                                       urb->actual_length);
+               } else {
+                       if (urb->iso_frame_desc[i].status < 0) {
+                               print_err_status(dev, i,
+                                                urb->iso_frame_desc[i].status);
+                               if (urb->iso_frame_desc[i].status != -EPROTO)
+                                       continue;
+                       }
+                       dvb_dmx_swfilter(&dev->dvb->demux,
+                                        urb->transfer_buffer +
+                                        urb->iso_frame_desc[i].offset,
+                                        urb->iso_frame_desc[i].actual_length);
+               }
        }
 
        return 0;
@@ -161,24 +176,40 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb)
 {
        int rc;
        struct em28xx *dev = dvb->adapter.priv;
-       int max_dvb_packet_size;
+       int dvb_max_packet_size, packet_multiplier, dvb_alt;
+
+       if (dev->dvb_xfer_bulk) {
+               if (!dev->dvb_ep_bulk)
+                       return -ENODEV;
+               dvb_max_packet_size = 512; /* USB 2.0 spec */
+               packet_multiplier = EM28XX_DVB_BULK_PACKET_MULTIPLIER;
+               dvb_alt = 0;
+       } else { /* isoc */
+               if (!dev->dvb_ep_isoc)
+                       return -ENODEV;
+               dvb_max_packet_size = dev->dvb_max_pkt_size_isoc;
+               if (dvb_max_packet_size < 0)
+                       return dvb_max_packet_size;
+               packet_multiplier = EM28XX_DVB_NUM_ISOC_PACKETS;
+               dvb_alt = dev->dvb_alt_isoc;
+       }
 
-       usb_set_interface(dev->udev, 0, dev->dvb_alt);
+       usb_set_interface(dev->udev, 0, dvb_alt);
        rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
        if (rc < 0)
                return rc;
 
-       max_dvb_packet_size = dev->dvb_max_pkt_size;
-       if (max_dvb_packet_size < 0)
-               return max_dvb_packet_size;
        dprintk(1, "Using %d buffers each with %d x %d bytes\n",
                EM28XX_DVB_NUM_BUFS,
-               EM28XX_DVB_MAX_PACKETS,
-               max_dvb_packet_size);
-
-       return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE,
-                               EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS,
-                               max_dvb_packet_size, em28xx_dvb_isoc_copy);
+               packet_multiplier,
+               dvb_max_packet_size);
+
+       return em28xx_init_usb_xfer(dev, EM28XX_DIGITAL_MODE,
+                                   dev->dvb_xfer_bulk,
+                                   EM28XX_DVB_NUM_BUFS,
+                                   dvb_max_packet_size,
+                                   packet_multiplier,
+                                   em28xx_dvb_urb_data_copy);
 }
 
 static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
@@ -714,7 +745,8 @@ static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
 };
 
 static const struct tda10071_config em28xx_tda10071_config = {
-       .i2c_address = 0x55, /* (0xaa >> 1) */
+       .demod_i2c_addr = 0x55, /* (0xaa >> 1) */
+       .tuner_i2c_addr = 0x14,
        .i2c_wr_max = 64,
        .ts_mode = TDA10071_TS_SERIAL,
        .spec_inv = 0,
index 1683bd9d51eed67ecaef8832832bd1eafeaa1ca5..44533e4574ffe6fd2cc746aab0d249b48a0510b1 100644 (file)
@@ -53,12 +53,11 @@ do {                                                        \
  * em2800_i2c_send_max4()
  * send up to 4 bytes to the i2c device
  */
-static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
-                               char *buf, int len)
+static int em2800_i2c_send_max4(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 {
        int ret;
        int write_timeout;
-       unsigned char b2[6];
+       u8 b2[6];
        BUG_ON(len < 1 || len > 4);
        b2[5] = 0x80 + len - 1;
        b2[4] = addr;
@@ -89,15 +88,13 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
 /*
  * em2800_i2c_send_bytes()
  */
-static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf,
-                                short len)
+static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 {
-       char *bufPtr = buf;
+       u8 *bufPtr = buf;
        int ret;
        int wrcount = 0;
        int count;
        int maxLen = 4;
-       struct em28xx *dev = (struct em28xx *)data;
        while (len > 0) {
                count = (len > maxLen) ? maxLen : len;
                ret = em2800_i2c_send_max4(dev, addr, bufPtr, count);
@@ -115,9 +112,9 @@ static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf,
  * em2800_i2c_check_for_device()
  * check if there is a i2c_device at the supplied address
  */
-static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
+static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
 {
-       char msg;
+       u8 msg;
        int ret;
        int write_timeout;
        msg = addr;
@@ -150,8 +147,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
  * em2800_i2c_recv_bytes()
  * read from the i2c device
  */
-static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
-                                char *buf, int len)
+static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 {
        int ret;
        /* check for the device and set i2c read address */
@@ -174,11 +170,10 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
 /*
  * em28xx_i2c_send_bytes()
  */
-static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
-                                short len, int stop)
+static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
+                                u16 len, int stop)
 {
        int wrcount = 0;
-       struct em28xx *dev = (struct em28xx *)data;
        int write_timeout, ret;
 
        wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
@@ -199,8 +194,7 @@ static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
  * em28xx_i2c_recv_bytes()
  * read a byte from the i2c device
  */
-static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
-                                char *buf, int len)
+static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
 {
        int ret;
        ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
@@ -217,7 +211,7 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
  * em28xx_i2c_check_for_device()
  * check if there is a i2c_device at the supplied address
  */
-static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
+static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
 {
        int ret;
 
index 660bf803c9e4b8df04defd0c0a0758280e30a69b..3598221378acaa88134dcd488144a826eb00b452 100644 (file)
@@ -57,8 +57,8 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 struct em28xx_ir_poll_result {
        unsigned int toggle_bit:1;
        unsigned int read_count:7;
-       u8 rc_address;
-       u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */
+
+       u32 scancode;
 };
 
 struct em28xx_IR {
@@ -72,6 +72,7 @@ struct em28xx_IR {
        struct delayed_work work;
        unsigned int full_code:1;
        unsigned int last_readcount;
+       u64 rc_type;
 
        int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
 };
@@ -236,11 +237,8 @@ static int default_polling_getkey(struct em28xx_IR *ir,
        /* Infrared read count (Reg 0x45[6:0] */
        poll_result->read_count = (msg[0] & 0x7f);
 
-       /* Remote Control Address (Reg 0x46) */
-       poll_result->rc_address = msg[1];
-
-       /* Remote Control Data (Reg 0x47) */
-       poll_result->rc_data[0] = msg[2];
+       /* Remote Control Address/Data (Regs 0x46/0x47) */
+       poll_result->scancode = msg[1] << 8 | msg[2];
 
        return 0;
 }
@@ -266,13 +264,35 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
        /* Infrared read count (Reg 0x51[6:0] */
        poll_result->read_count = (msg[0] & 0x7f);
 
-       /* Remote Control Address (Reg 0x52) */
-       poll_result->rc_address = msg[1];
-
-       /* Remote Control Data (Reg 0x53-55) */
-       poll_result->rc_data[0] = msg[2];
-       poll_result->rc_data[1] = msg[3];
-       poll_result->rc_data[2] = msg[4];
+       /*
+        * Remote Control Address (Reg 0x52)
+        * Remote Control Data (Reg 0x53-0x55)
+        */
+       switch (ir->rc_type) {
+       case RC_BIT_RC5:
+               poll_result->scancode = msg[1] << 8 | msg[2];
+               break;
+       case RC_BIT_NEC:
+               if ((msg[3] ^ msg[4]) != 0xff)          /* 32 bits NEC */
+                       poll_result->scancode = (msg[1] << 24) |
+                                               (msg[2] << 16) |
+                                               (msg[3] << 8)  |
+                                                msg[4];
+               else if ((msg[1] ^ msg[2]) != 0xff)     /* 24 bits NEC */
+                       poll_result->scancode = (msg[1] << 16) |
+                                               (msg[2] << 8)  |
+                                                msg[3];
+               else                                    /* Normal NEC */
+                       poll_result->scancode = msg[1] << 8 | msg[3];
+               break;
+       case RC_BIT_RC6_0:
+               poll_result->scancode = msg[1] << 8 | msg[2];
+               break;
+       default:
+               poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) |
+                                       (msg[3] << 8)  | msg[4];
+               break;
+       }
 
        return 0;
 }
@@ -294,17 +314,16 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
        }
 
        if (unlikely(poll_result.read_count != ir->last_readcount)) {
-               dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__,
+               dprintk("%s: toggle: %d, count: %d, key 0x%04x\n", __func__,
                        poll_result.toggle_bit, poll_result.read_count,
-                       poll_result.rc_address, poll_result.rc_data[0]);
+                       poll_result.scancode);
                if (ir->full_code)
                        rc_keydown(ir->rc,
-                                  poll_result.rc_address << 8 |
-                                  poll_result.rc_data[0],
+                                  poll_result.scancode,
                                   poll_result.toggle_bit);
                else
                        rc_keydown(ir->rc,
-                                  poll_result.rc_data[0],
+                                  poll_result.scancode & 0xff,
                                   poll_result.toggle_bit);
 
                if (ir->dev->chip_id == CHIP_ID_EM2874 ||
@@ -345,49 +364,92 @@ static void em28xx_ir_stop(struct rc_dev *rc)
        cancel_delayed_work_sync(&ir->work);
 }
 
-static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
+static int em2860_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
 {
-       int rc = 0;
        struct em28xx_IR *ir = rc_dev->priv;
        struct em28xx *dev = ir->dev;
-       u8 ir_config = EM2874_IR_RC5;
 
-       /* Adjust xclk based o IR table for RC5/NEC tables */
+       /* Adjust xclk based on IR table for RC5/NEC tables */
+       if (*rc_type & RC_BIT_RC5) {
+               dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
+               ir->full_code = 1;
+               *rc_type = RC_BIT_RC5;
+       } else if (*rc_type & RC_BIT_NEC) {
+               dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
+               ir->full_code = 1;
+               *rc_type = RC_BIT_NEC;
+       } else if (*rc_type & RC_BIT_UNKNOWN) {
+               *rc_type = RC_BIT_UNKNOWN;
+       } else {
+               *rc_type = ir->rc_type;
+               return -EINVAL;
+       }
+       ir->get_key = default_polling_getkey;
+       em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
+                             EM28XX_XCLK_IR_RC5_MODE);
+
+       ir->rc_type = *rc_type;
+
+       return 0;
+}
+
+static int em2874_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
+{
+       struct em28xx_IR *ir = rc_dev->priv;
+       struct em28xx *dev = ir->dev;
+       u8 ir_config = EM2874_IR_RC5;
 
+       /* Adjust xclk and set type based on IR table for RC5/NEC/RC6 tables */
        if (*rc_type & RC_BIT_RC5) {
                dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
                ir->full_code = 1;
                *rc_type = RC_BIT_RC5;
        } else if (*rc_type & RC_BIT_NEC) {
                dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
-               ir_config = EM2874_IR_NEC;
+               ir_config = EM2874_IR_NEC | EM2874_IR_NEC_NO_PARITY;
                ir->full_code = 1;
                *rc_type = RC_BIT_NEC;
-       } else if (*rc_type != RC_BIT_UNKNOWN)
-               rc = -EINVAL;
+       } else if (*rc_type & RC_BIT_RC6_0) {
+               dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
+               ir_config = EM2874_IR_RC6_MODE_0;
+               ir->full_code = 1;
+               *rc_type = RC_BIT_RC6_0;
+       } else if (*rc_type & RC_BIT_UNKNOWN) {
+               *rc_type = RC_BIT_UNKNOWN;
+       } else {
+               *rc_type = ir->rc_type;
+               return -EINVAL;
+       }
+
+       ir->get_key = em2874_polling_getkey;
+       em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
 
        em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
                              EM28XX_XCLK_IR_RC5_MODE);
 
+       ir->rc_type = *rc_type;
+
+       return 0;
+}
+static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
+{
+       struct em28xx_IR *ir = rc_dev->priv;
+       struct em28xx *dev = ir->dev;
+
        /* Setup the proper handler based on the chip */
        switch (dev->chip_id) {
        case CHIP_ID_EM2860:
        case CHIP_ID_EM2883:
-               ir->get_key = default_polling_getkey;
-               break;
+               return em2860_ir_change_protocol(rc_dev, rc_type);
        case CHIP_ID_EM2884:
        case CHIP_ID_EM2874:
        case CHIP_ID_EM28174:
-               ir->get_key = em2874_polling_getkey;
-               em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
-               break;
+               return em2874_ir_change_protocol(rc_dev, rc_type);
        default:
                printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
                        dev->chip_id);
-               rc = -EINVAL;
+               return -EINVAL;
        }
-
-       return rc;
 }
 
 static void em28xx_register_i2c_ir(struct em28xx *dev)
@@ -538,7 +600,7 @@ static int em28xx_ir_init(struct em28xx *dev)
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
        rc = rc_allocate_device();
        if (!ir || !rc)
-               goto err_out_free;
+               goto error;
 
        /* record handles to ourself */
        ir->dev = dev;
@@ -555,11 +617,26 @@ static int em28xx_ir_init(struct em28xx *dev)
        rc->open = em28xx_ir_start;
        rc->close = em28xx_ir_stop;
 
+       switch (dev->chip_id) {
+       case CHIP_ID_EM2860:
+       case CHIP_ID_EM2883:
+               rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
+               break;
+       case CHIP_ID_EM2884:
+       case CHIP_ID_EM2874:
+       case CHIP_ID_EM28174:
+               rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | RC_BIT_RC6_0;
+               break;
+       default:
+               err = -ENODEV;
+               goto error;
+       }
+
        /* By default, keep protocol field untouched */
        rc_type = RC_BIT_UNKNOWN;
        err = em28xx_ir_change_protocol(rc, &rc_type);
        if (err)
-               goto err_out_free;
+               goto error;
 
        /* This is how often we ask the chip for IR information */
        ir->polling = 100; /* ms */
@@ -584,7 +661,7 @@ static int em28xx_ir_init(struct em28xx *dev)
        /* all done */
        err = rc_register_device(rc);
        if (err)
-               goto err_out_stop;
+               goto error;
 
        em28xx_register_i2c_ir(dev);
 
@@ -597,9 +674,8 @@ static int em28xx_ir_init(struct em28xx *dev)
 
        return 0;
 
- err_out_stop:
+error:
        dev->ir = NULL;
- err_out_free:
        rc_free_device(rc);
        kfree(ir);
        return err;
index 6ff368297f6eaef94f93b26528f59bacc6010a53..885089e22bcd74965a156f4a73878077c0493335 100644 (file)
@@ -13,9 +13,9 @@
 #define EM_GPO_3   (1 << 3)
 
 /* em28xx endpoints */
-#define EM28XX_EP_ANALOG       0x82
+/* 0x82:   (always ?) analog */
 #define EM28XX_EP_AUDIO                0x83
-#define EM28XX_EP_DIGITAL      0x84
+/* 0x84:   digital or analog */
 
 /* em2800 registers */
 #define EM2800_R08_AUDIOSRC 0x08
 
 /* em2874 IR config register (0x50) */
 #define EM2874_IR_NEC           0x00
+#define EM2874_IR_NEC_NO_PARITY 0x01
 #define EM2874_IR_RC5           0x04
 #define EM2874_IR_RC6_MODE_0    0x08
 #define EM2874_IR_RC6_MODE_6A   0x0b
index 2b4c9cba2d67312bb8561c3410cdb8cc59b5debc..d74713bd1d18362f148e00a7e5c02fc779659af5 100644 (file)
@@ -60,8 +60,8 @@ free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
           VIDEOBUF_ACTIVE, it won't be, though.
        */
        spin_lock_irqsave(&dev->slock, flags);
-       if (dev->isoc_ctl.vbi_buf == buf)
-               dev->isoc_ctl.vbi_buf = NULL;
+       if (dev->usb_ctl.vbi_buf == buf)
+               dev->usb_ctl.vbi_buf = NULL;
        spin_unlock_irqrestore(&dev->slock, flags);
 
        videobuf_vmalloc_free(&buf->vb);
index 1e553d3573805795dc8cb1debdbd50f82d6a42c4..4c1726d433741d881629bd4221cd991412396656 100644 (file)
@@ -6,6 +6,7 @@
                      Markus Rechberger <mrechberger@gmail.com>
                      Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
+   Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
 
        Some parts based on SN9C10x PC Camera Controllers GPL driver made
                by Luca Risolia <luca.risolia@studio.unibo.it>
@@ -153,72 +154,44 @@ static struct v4l2_queryctrl ac97_qctrl[] = {
    ------------------------------------------------------------------*/
 
 /*
- * Announces that a buffer were filled and request the next
+ * Finish the current buffer
  */
-static inline void buffer_filled(struct em28xx *dev,
-                                 struct em28xx_dmaqueue *dma_q,
-                                 struct em28xx_buffer *buf)
+static inline void finish_buffer(struct em28xx *dev,
+                                struct em28xx_buffer *buf)
 {
-       /* Advice that buffer was filled */
        em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
        buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       dev->isoc_ctl.vid_buf = NULL;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-static inline void vbi_buffer_filled(struct em28xx *dev,
-                                    struct em28xx_dmaqueue *dma_q,
-                                    struct em28xx_buffer *buf)
-{
-       /* Advice that buffer was filled */
-       em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
-
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       dev->isoc_ctl.vbi_buf = NULL;
-
+       v4l2_get_timestamp(&buf->vb.ts);
        list_del(&buf->vb.queue);
        wake_up(&buf->vb.done);
 }
 
 /*
- * Identify the buffer header type and properly handles
+ * Copy picture data from USB buffer to videobuf buffer
  */
 static void em28xx_copy_video(struct em28xx *dev,
-                             struct em28xx_dmaqueue  *dma_q,
                              struct em28xx_buffer *buf,
-                             unsigned char *p,
-                             unsigned char *outp, unsigned long len)
+                             unsigned char *usb_buf,
+                             unsigned long len)
 {
        void *fieldstart, *startwrite, *startread;
        int  linesdone, currlinedone, offset, lencopy, remain;
        int bytesperline = dev->width << 1;
 
-       if (dma_q->pos + len > buf->vb.size)
-               len = buf->vb.size - dma_q->pos;
+       if (buf->pos + len > buf->vb.size)
+               len = buf->vb.size - buf->pos;
 
-       startread = p;
+       startread = usb_buf;
        remain = len;
 
-       if (dev->progressive)
-               fieldstart = outp;
-       else {
-               /* Interlaces two half frames */
-               if (buf->top_field)
-                       fieldstart = outp;
-               else
-                       fieldstart = outp + bytesperline;
-       }
+       if (dev->progressive || buf->top_field)
+               fieldstart = buf->vb_buf;
+       else /* interlaced mode, even nr. of lines */
+               fieldstart = buf->vb_buf + bytesperline;
 
-       linesdone = dma_q->pos / bytesperline;
-       currlinedone = dma_q->pos % bytesperline;
+       linesdone = buf->pos / bytesperline;
+       currlinedone = buf->pos % bytesperline;
 
        if (dev->progressive)
                offset = linesdone * bytesperline + currlinedone;
@@ -229,11 +202,12 @@ static void em28xx_copy_video(struct em28xx *dev,
        lencopy = bytesperline - currlinedone;
        lencopy = lencopy > remain ? remain : lencopy;
 
-       if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+       if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->vb.size) {
                em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
-                              ((char *)startwrite + lencopy) -
-                              ((char *)outp + buf->vb.size));
-               remain = (char *)outp + buf->vb.size - (char *)startwrite;
+                             ((char *)startwrite + lencopy) -
+                             ((char *)buf->vb_buf + buf->vb.size));
+               remain = (char *)buf->vb_buf + buf->vb.size -
+                        (char *)startwrite;
                lencopy = remain;
        }
        if (lencopy <= 0)
@@ -243,20 +217,23 @@ static void em28xx_copy_video(struct em28xx *dev,
        remain -= lencopy;
 
        while (remain > 0) {
-               startwrite += lencopy + bytesperline;
+               if (dev->progressive)
+                       startwrite += lencopy;
+               else
+                       startwrite += lencopy + bytesperline;
                startread += lencopy;
                if (bytesperline > remain)
                        lencopy = remain;
                else
                        lencopy = bytesperline;
 
-               if ((char *)startwrite + lencopy > (char *)outp +
+               if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
                    buf->vb.size) {
                        em28xx_isocdbg("Overflow of %zi bytes past buffer end"
                                       "(2)\n",
                                       ((char *)startwrite + lencopy) -
-                                      ((char *)outp + buf->vb.size));
-                       lencopy = remain = (char *)outp + buf->vb.size -
+                                      ((char *)buf->vb_buf + buf->vb.size));
+                       lencopy = remain = (char *)buf->vb_buf + buf->vb.size -
                                           (char *)startwrite;
                }
                if (lencopy <= 0)
@@ -267,57 +244,29 @@ static void em28xx_copy_video(struct em28xx *dev,
                remain -= lencopy;
        }
 
-       dma_q->pos += len;
+       buf->pos += len;
 }
 
+/*
+ * Copy VBI data from USB buffer to videobuf buffer
+ */
 static void em28xx_copy_vbi(struct em28xx *dev,
-                             struct em28xx_dmaqueue  *dma_q,
-                             struct em28xx_buffer *buf,
-                             unsigned char *p,
-                             unsigned char *outp, unsigned long len)
+                           struct em28xx_buffer *buf,
+                           unsigned char *usb_buf,
+                           unsigned long len)
 {
-       void *startwrite, *startread;
-       int  offset;
-       int bytesperline;
-
-       if (dev == NULL) {
-               em28xx_isocdbg("dev is null\n");
-               return;
-       }
-       bytesperline = dev->vbi_width;
-
-       if (dma_q == NULL) {
-               em28xx_isocdbg("dma_q is null\n");
-               return;
-       }
-       if (buf == NULL) {
-               return;
-       }
-       if (p == NULL) {
-               em28xx_isocdbg("p is null\n");
-               return;
-       }
-       if (outp == NULL) {
-               em28xx_isocdbg("outp is null\n");
-               return;
-       }
+       unsigned int offset;
 
-       if (dma_q->pos + len > buf->vb.size)
-               len = buf->vb.size - dma_q->pos;
-
-       startread = p;
-
-       startwrite = outp + dma_q->pos;
-       offset = dma_q->pos;
+       if (buf->pos + len > buf->vb.size)
+               len = buf->vb.size - buf->pos;
 
+       offset = buf->pos;
        /* Make sure the bottom field populates the second half of the frame */
-       if (buf->top_field == 0) {
-               startwrite += bytesperline * dev->vbi_height;
-               offset += bytesperline * dev->vbi_height;
-       }
+       if (buf->top_field == 0)
+               offset += dev->vbi_width * dev->vbi_height;
 
-       memcpy(startwrite, startread, len);
-       dma_q->pos += len;
+       memcpy(buf->vb_buf + offset, usb_buf, len);
+       buf->pos += len;
 }
 
 static inline void print_err_status(struct em28xx *dev,
@@ -360,166 +309,135 @@ static inline void print_err_status(struct em28xx *dev,
 }
 
 /*
- * video-buf generic routine to get the next available buffer
+ * get the next available buffer from dma queue
  */
-static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
-                                         struct em28xx_buffer **buf)
+static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
+                                                struct em28xx_dmaqueue *dma_q)
 {
-       struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+       struct em28xx_buffer *buf;
        char *outp;
 
        if (list_empty(&dma_q->active)) {
                em28xx_isocdbg("No active queue to serve\n");
-               dev->isoc_ctl.vid_buf = NULL;
-               *buf = NULL;
-               return;
+               return NULL;
        }
 
        /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
-
+       buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
        /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0, (*buf)->vb.size);
+       outp = videobuf_to_vmalloc(&buf->vb);
+       memset(outp, 0, buf->vb.size);
+       buf->pos = 0;
+       buf->vb_buf = outp;
 
-       dev->isoc_ctl.vid_buf = *buf;
-
-       return;
+       return buf;
 }
 
 /*
- * video-buf generic routine to get the next available VBI buffer
+ * Finish the current buffer if completed and prepare for the next field
  */
-static inline void vbi_get_next_buf(struct em28xx_dmaqueue *dma_q,
-                                   struct em28xx_buffer **buf)
-{
-       struct em28xx *dev = container_of(dma_q, struct em28xx, vbiq);
-       char *outp;
-
-       if (list_empty(&dma_q->active)) {
-               em28xx_isocdbg("No active queue to serve\n");
-               dev->isoc_ctl.vbi_buf = NULL;
-               *buf = NULL;
-               return;
+static struct em28xx_buffer *
+finish_field_prepare_next(struct em28xx *dev,
+                         struct em28xx_buffer *buf,
+                         struct em28xx_dmaqueue *dma_q)
+{
+       if (dev->progressive || dev->top_field) { /* Brand new frame */
+               if (buf != NULL)
+                       finish_buffer(dev, buf);
+               buf = get_next_buf(dev, dma_q);
+       }
+       if (buf != NULL) {
+               buf->top_field = dev->top_field;
+               buf->pos = 0;
        }
 
-       /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
-       /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0x00, (*buf)->vb.size);
-
-       dev->isoc_ctl.vbi_buf = *buf;
-
-       return;
+       return buf;
 }
 
 /*
- * Controls the isoc copy of each urb packet
+ * Process data packet according to the em2710/em2750/em28xx frame data format
  */
-static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
+static inline void process_frame_data_em28xx(struct em28xx *dev,
+                                            unsigned char *data_pkt,
+                                            unsigned int  data_len)
 {
-       struct em28xx_buffer    *buf;
+       struct em28xx_buffer    *buf = dev->usb_ctl.vid_buf;
+       struct em28xx_buffer    *vbi_buf = dev->usb_ctl.vbi_buf;
        struct em28xx_dmaqueue  *dma_q = &dev->vidq;
-       unsigned char *outp = NULL;
-       int i, len = 0, rc = 1;
-       unsigned char *p;
-
-       if (!dev)
-               return 0;
-
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       buf = dev->isoc_ctl.vid_buf;
-       if (buf != NULL)
-               outp = videobuf_to_vmalloc(&buf->vb);
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
+       struct em28xx_dmaqueue  *vbi_dma_q = &dev->vbiq;
 
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
+       /* capture type 0 = vbi start
+          capture type 1 = vbi in progress
+          capture type 2 = video start
+          capture type 3 = video in progress */
+       if (data_len >= 4) {
+               /* NOTE: Headers are always 4 bytes and
+                * never split across packets */
+               if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
+                   data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
+                       /* Continuation */
+                       data_pkt += 4;
+                       data_len -= 4;
+               } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
+                       /* Field start (VBI mode) */
+                       dev->capture_type = 0;
+                       dev->vbi_read = 0;
+                       em28xx_isocdbg("VBI START HEADER !!!\n");
+                       dev->top_field = !(data_pkt[2] & 1);
+                       data_pkt += 4;
+                       data_len -= 4;
+               } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
+                       /* Field start (VBI disabled) */
+                       dev->capture_type = 2;
+                       em28xx_isocdbg("VIDEO START HEADER !!!\n");
+                       dev->top_field = !(data_pkt[2] & 1);
+                       data_pkt += 4;
+                       data_len -= 4;
                }
+       }
+       /* NOTE: With bulk transfers, intermediate data packets
+        * have no continuation header */
 
-               len = urb->iso_frame_desc[i].actual_length - 4;
+       if (dev->capture_type == 0) {
+               vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
+               dev->usb_ctl.vbi_buf = vbi_buf;
+               dev->capture_type = 1;
+       }
 
-               if (urb->iso_frame_desc[i].actual_length <= 0) {
-                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
-                       continue;
-               }
-               if (urb->iso_frame_desc[i].actual_length >
-                                               dev->max_pkt_size) {
-                       em28xx_isocdbg("packet bigger than packet size");
-                       continue;
-               }
+       if (dev->capture_type == 1) {
+               int vbi_size = dev->vbi_width * dev->vbi_height;
+               int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
+                                  (vbi_size - dev->vbi_read) : data_len;
 
-               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               /* Copy VBI data */
+               if (vbi_buf != NULL)
+                       em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
+               dev->vbi_read += vbi_data_len;
 
-               /* FIXME: incomplete buffer checks where removed to make
-                  logic simpler. Impacts of those changes should be evaluated
-                */
-               if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
-                       em28xx_isocdbg("VBI HEADER!!!\n");
-                       /* FIXME: Should add vbi copy */
-                       continue;
+               if (vbi_data_len < data_len) {
+                       /* Continue with copying video data */
+                       dev->capture_type = 2;
+                       data_pkt += vbi_data_len;
+                       data_len -= vbi_data_len;
                }
-               if (p[0] == 0x22 && p[1] == 0x5a) {
-                       em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
-                                      len, (p[2] & 1) ? "odd" : "even");
-
-                       if (dev->progressive || !(p[2] & 1)) {
-                               if (buf != NULL)
-                                       buffer_filled(dev, dma_q, buf);
-                               get_next_buf(dma_q, &buf);
-                               if (buf == NULL)
-                                       outp = NULL;
-                               else
-                                       outp = videobuf_to_vmalloc(&buf->vb);
-                       }
-
-                       if (buf != NULL) {
-                               if (p[2] & 1)
-                                       buf->top_field = 0;
-                               else
-                                       buf->top_field = 1;
-                       }
+       }
 
-                       dma_q->pos = 0;
-               }
-               if (buf != NULL) {
-                       if (p[0] != 0x88 && p[0] != 0x22) {
-                               em28xx_isocdbg("frame is not complete\n");
-                               len += 4;
-                       } else {
-                               p += 4;
-                       }
-                       em28xx_copy_video(dev, dma_q, buf, p, outp, len);
-               }
+       if (dev->capture_type == 2) {
+               buf = finish_field_prepare_next(dev, buf, dma_q);
+               dev->usb_ctl.vid_buf = buf;
+               dev->capture_type = 3;
        }
-       return rc;
+
+       if (dev->capture_type == 3 && buf != NULL && data_len > 0)
+               em28xx_copy_video(dev, buf, data_pkt, data_len);
 }
 
-/* Version of isoc handler that takes into account a mixture of video and
-   VBI data */
-static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
+/* Processes and copies the URB data content (video and VBI data) */
+static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
 {
-       struct em28xx_buffer    *buf, *vbi_buf;
-       struct em28xx_dmaqueue  *dma_q = &dev->vidq;
-       struct em28xx_dmaqueue  *vbi_dma_q = &dev->vbiq;
-       unsigned char *outp = NULL;
-       unsigned char *vbioutp = NULL;
-       int i, len = 0, rc = 1;
-       unsigned char *p;
-       int vbi_size;
+       int xfer_bulk, num_packets, i;
+       unsigned char *usb_data_pkt;
+       unsigned int usb_data_len;
 
        if (!dev)
                return 0;
@@ -527,154 +445,48 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
        if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
                return 0;
 
-       if (urb->status < 0) {
+       if (urb->status < 0)
                print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       buf = dev->isoc_ctl.vid_buf;
-       if (buf != NULL)
-               outp = videobuf_to_vmalloc(&buf->vb);
-
-       vbi_buf = dev->isoc_ctl.vbi_buf;
-       if (vbi_buf != NULL)
-               vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
 
-               len = urb->iso_frame_desc[i].actual_length;
-               if (urb->iso_frame_desc[i].actual_length <= 0) {
-                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
-                       continue;
-               }
-               if (urb->iso_frame_desc[i].actual_length >
-                                               dev->max_pkt_size) {
-                       em28xx_isocdbg("packet bigger than packet size");
-                       continue;
-               }
+       xfer_bulk = usb_pipebulk(urb->pipe);
 
-               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+       if (xfer_bulk) /* bulk */
+               num_packets = 1;
+       else /* isoc */
+               num_packets = urb->number_of_packets;
 
-               /* capture type 0 = vbi start
-                  capture type 1 = video start
-                  capture type 2 = video in progress */
-               if (p[0] == 0x33 && p[1] == 0x95) {
-                       dev->capture_type = 0;
-                       dev->vbi_read = 0;
-                       em28xx_isocdbg("VBI START HEADER!!!\n");
-                       dev->cur_field = p[2];
-                       p += 4;
-                       len -= 4;
-               } else if (p[0] == 0x88 && p[1] == 0x88 &&
-                          p[2] == 0x88 && p[3] == 0x88) {
-                       /* continuation */
-                       p += 4;
-                       len -= 4;
-               } else if (p[0] == 0x22 && p[1] == 0x5a) {
-                       /* start video */
-                       p += 4;
-                       len -= 4;
-               }
+       for (i = 0; i < num_packets; i++) {
+               if (xfer_bulk) { /* bulk */
+                       usb_data_len = urb->actual_length;
 
-               vbi_size = dev->vbi_width * dev->vbi_height;
-
-               if (dev->capture_type == 0) {
-                       if (dev->vbi_read >= vbi_size) {
-                               /* We've already read all the VBI data, so
-                                  treat the rest as video */
-                               em28xx_isocdbg("dev->vbi_read > vbi_size\n");
-                       } else if ((dev->vbi_read + len) < vbi_size) {
-                               /* This entire frame is VBI data */
-                               if (dev->vbi_read == 0 &&
-                                   (!(dev->cur_field & 1))) {
-                                       /* Brand new frame */
-                                       if (vbi_buf != NULL)
-                                               vbi_buffer_filled(dev,
-                                                                 vbi_dma_q,
-                                                                 vbi_buf);
-                                       vbi_get_next_buf(vbi_dma_q, &vbi_buf);
-                                       if (vbi_buf == NULL)
-                                               vbioutp = NULL;
-                                       else
-                                               vbioutp = videobuf_to_vmalloc(
-                                                       &vbi_buf->vb);
-                               }
-
-                               if (dev->vbi_read == 0) {
-                                       vbi_dma_q->pos = 0;
-                                       if (vbi_buf != NULL) {
-                                               if (dev->cur_field & 1)
-                                                       vbi_buf->top_field = 0;
-                                               else
-                                                       vbi_buf->top_field = 1;
-                                       }
-                               }
-
-                               dev->vbi_read += len;
-                               em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
-                                               vbioutp, len);
-                       } else {
-                               /* Some of this frame is VBI data and some is
-                                  video data */
-                               int vbi_data_len = vbi_size - dev->vbi_read;
-                               dev->vbi_read += vbi_data_len;
-                               em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
-                                               vbioutp, vbi_data_len);
-                               dev->capture_type = 1;
-                               p += vbi_data_len;
-                               len -= vbi_data_len;
+                       usb_data_pkt = urb->transfer_buffer;
+               } else { /* isoc */
+                       if (urb->iso_frame_desc[i].status < 0) {
+                               print_err_status(dev, i,
+                                                urb->iso_frame_desc[i].status);
+                               if (urb->iso_frame_desc[i].status != -EPROTO)
+                                       continue;
                        }
-               }
 
-               if (dev->capture_type == 1) {
-                       dev->capture_type = 2;
-                       if (dev->progressive || !(dev->cur_field & 1)) {
-                               if (buf != NULL)
-                                       buffer_filled(dev, dma_q, buf);
-                               get_next_buf(dma_q, &buf);
-                               if (buf == NULL)
-                                       outp = NULL;
-                               else
-                                       outp = videobuf_to_vmalloc(&buf->vb);
-                       }
-                       if (buf != NULL) {
-                               if (dev->cur_field & 1)
-                                       buf->top_field = 0;
-                               else
-                                       buf->top_field = 1;
+                       usb_data_len = urb->iso_frame_desc[i].actual_length;
+                       if (usb_data_len > dev->max_pkt_size) {
+                               em28xx_isocdbg("packet bigger than packet size");
+                               continue;
                        }
 
-                       dma_q->pos = 0;
+                       usb_data_pkt = urb->transfer_buffer +
+                                      urb->iso_frame_desc[i].offset;
                }
 
-               if (buf != NULL && dev->capture_type == 2) {
-                       if (len >= 4 && p[0] == 0x88 && p[1] == 0x88 &&
-                           p[2] == 0x88 && p[3] == 0x88) {
-                               p += 4;
-                               len -= 4;
-                       }
-                       if (len >= 4 && p[0] == 0x22 && p[1] == 0x5a) {
-                               em28xx_isocdbg("Video frame %d, len=%i, %s\n",
-                                              p[2], len, (p[2] & 1) ?
-                                              "odd" : "even");
-                               p += 4;
-                               len -= 4;
-                       }
-
-                       if (len > 0)
-                               em28xx_copy_video(dev, dma_q, buf, p, outp,
-                                                 len);
+               if (usb_data_len == 0) {
+                       /* NOTE: happens very often with isoc transfers */
+                       /* em28xx_usbdbg("packet %d is empty",i); - spammy */
+                       continue;
                }
+
+               process_frame_data_em28xx(dev, usb_data_pkt, usb_data_len);
        }
-       return rc;
+       return 1;
 }
 
 
@@ -727,8 +539,8 @@ static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
           VIDEOBUF_ACTIVE, it won't be, though.
        */
        spin_lock_irqsave(&dev->slock, flags);
-       if (dev->isoc_ctl.vid_buf == buf)
-               dev->isoc_ctl.vid_buf = NULL;
+       if (dev->usb_ctl.vid_buf == buf)
+               dev->usb_ctl.vid_buf = NULL;
        spin_unlock_irqrestore(&dev->slock, flags);
 
        videobuf_vmalloc_free(&buf->vb);
@@ -760,22 +572,17 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
                        goto fail;
        }
 
-       if (!dev->isoc_ctl.analog_bufs.num_bufs)
+       if (!dev->usb_ctl.analog_bufs.num_bufs)
                urb_init = 1;
 
        if (urb_init) {
-               if (em28xx_vbi_supported(dev) == 1)
-                       rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE,
-                                             EM28XX_NUM_PACKETS,
-                                             EM28XX_NUM_BUFS,
-                                             dev->max_pkt_size,
-                                             em28xx_isoc_copy_vbi);
-               else
-                       rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE,
-                                             EM28XX_NUM_PACKETS,
-                                             EM28XX_NUM_BUFS,
-                                             dev->max_pkt_size,
-                                             em28xx_isoc_copy);
+               dev->capture_type = -1;
+               rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
+                                         dev->analog_xfer_bulk,
+                                         EM28XX_NUM_BUFS,
+                                         dev->max_pkt_size,
+                                         dev->packet_multiplier,
+                                         em28xx_urb_data_copy);
                if (rc < 0)
                        goto fail;
        }
@@ -2263,7 +2070,7 @@ static int em28xx_v4l2_close(struct file *filp)
                   free the remaining resources */
                if (dev->state & DEV_DISCONNECTED) {
                        em28xx_release_resources(dev);
-                       kfree(dev->alt_max_pkt_size);
+                       kfree(dev->alt_max_pkt_size_isoc);
                        mutex_unlock(&dev->lock);
                        kfree(dev);
                        kfree(fh);
@@ -2274,7 +2081,7 @@ static int em28xx_v4l2_close(struct file *filp)
                v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
 
                /* do this before setting alternate! */
-               em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE);
+               em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
                em28xx_set_mode(dev, EM28XX_SUSPEND);
 
                /* set alternate 0 */
index 86e90d86da6d51547ae73b5f5a4d3197e488ccbb..062841e5072222ef8bba229a4bfd8d6116ebc9dd 100644 (file)
@@ -4,6 +4,7 @@
    Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
                      Ludovico Cavedon <cavedon@sssup.it>
                      Mauro Carvalho Chehab <mchehab@infradead.org>
+   Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
 
    Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
 
 #define EM28XX_NUM_BUFS 5
 #define EM28XX_DVB_NUM_BUFS 5
 
-/* number of packets for each buffer
+/* isoc transfers: number of packets for each buffer
    windows requests only 64 packets .. so we better do the same
    this is what I found out for all alternate numbers there!
  */
-#define EM28XX_NUM_PACKETS 64
-#define EM28XX_DVB_MAX_PACKETS 64
+#define EM28XX_NUM_ISOC_PACKETS 64
+#define EM28XX_DVB_NUM_ISOC_PACKETS 64
+
+/* bulk transfers: transfer buffer size = packet size * packet multiplier
+   USB 2.0 spec says bulk packet size is always 512 bytes
+ */
+#define EM28XX_BULK_PACKET_MULTIPLIER 384
+#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 384
 
 #define EM28XX_INTERLACED_DEFAULT 1
 
                        Interval: 125us
 */
 
-/* time to wait when stopping the isoc transfer */
-#define EM28XX_URB_TIMEOUT \
-                       msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS)
-
 /* time in msecs to wait for i2c writes to finish */
 #define EM2800_I2C_WRITE_TIMEOUT 20
 
@@ -203,7 +206,7 @@ enum em28xx_mode {
 
 struct em28xx;
 
-struct em28xx_usb_isoc_bufs {
+struct em28xx_usb_bufs {
                /* max packet size of isoc transaction */
        int                             max_pkt_size;
 
@@ -213,26 +216,26 @@ struct em28xx_usb_isoc_bufs {
                /* number of allocated urbs */
        int                             num_bufs;
 
-               /* urb for isoc transfers */
+               /* urb for isoc/bulk transfers */
        struct urb                      **urb;
 
-               /* transfer buffers for isoc transfer */
+               /* transfer buffers for isoc/bulk transfer */
        char                            **transfer_buffer;
 };
 
-struct em28xx_usb_isoc_ctl {
-               /* isoc transfer buffers for analog mode */
-       struct em28xx_usb_isoc_bufs     analog_bufs;
+struct em28xx_usb_ctl {
+               /* isoc/bulk transfer buffers for analog mode */
+       struct em28xx_usb_bufs          analog_bufs;
 
-               /* isoc transfer buffers for digital mode */
-       struct em28xx_usb_isoc_bufs     digital_bufs;
+               /* isoc/bulk transfer buffers for digital mode */
+       struct em28xx_usb_bufs          digital_bufs;
 
                /* Stores already requested buffers */
        struct em28xx_buffer            *vid_buf;
        struct em28xx_buffer            *vbi_buf;
 
-               /* isoc urb callback */
-       int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
+               /* copy data from URB */
+       int (*urb_data_copy) (struct em28xx *dev, struct urb *urb);
 
 };
 
@@ -249,17 +252,21 @@ struct em28xx_buffer {
        /* common v4l buffer stuff -- must be first */
        struct videobuf_buffer vb;
 
-       struct list_head frame;
        int top_field;
+
+       /* counter to control buffer fill */
+       unsigned int pos;
+       /* NOTE; in interlaced mode, this value is reset to zero at
+        * the start of each new field (not frame !)               */
+
+       /* pointer to vmalloc memory address in vb */
+       char *vb_buf;
 };
 
 struct em28xx_dmaqueue {
        struct list_head       active;
 
        wait_queue_head_t          wq;
-
-       /* Counters to control buffer fill */
-       int                        pos;
 };
 
 /* inputs */
@@ -497,7 +504,7 @@ struct em28xx {
        int sensor_xres, sensor_yres;
        int sensor_xtal;
 
-       /* Allows progressive (e. g. non-interlaced) mode */
+       /* Progressive (non-interlaced) mode */
        int progressive;
 
        /* Vinmode/Vinctl used at the driver */
@@ -557,10 +564,10 @@ struct em28xx {
        /* states */
        enum em28xx_dev_state state;
 
-       /* vbi related state tracking */
+       /* capture state tracking */
        int capture_type;
+       unsigned char top_field:1;
        int vbi_read;
-       unsigned char cur_field;
        unsigned int vbi_width;
        unsigned int vbi_height; /* lines per field */
 
@@ -582,17 +589,28 @@ struct em28xx {
        /* Isoc control struct */
        struct em28xx_dmaqueue vidq;
        struct em28xx_dmaqueue vbiq;
-       struct em28xx_usb_isoc_ctl isoc_ctl;
+       struct em28xx_usb_ctl usb_ctl;
        spinlock_t slock;
 
        /* usb transfer */
        struct usb_device *udev;        /* the usb device */
-       int alt;                /* alternate */
-       int max_pkt_size;       /* max packet size of isoc transaction */
-       int num_alt;            /* Number of alternative settings */
-       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
-       int dvb_alt;                            /* alternate for DVB */
-       unsigned int dvb_max_pkt_size;          /* wMaxPacketSize for DVB */
+       u8 analog_ep_isoc;      /* address of isoc endpoint for analog */
+       u8 analog_ep_bulk;      /* address of bulk endpoint for analog */
+       u8 dvb_ep_isoc;         /* address of isoc endpoint for DVB */
+       u8 dvb_ep_bulk;         /* address of bulk endpoint for DVC */
+       int alt;                /* alternate setting */
+       int max_pkt_size;       /* max packet size of the selected ep at alt */
+       int packet_multiplier;  /* multiplier for wMaxPacketSize, used for
+                                  URB buffer size definition */
+       int num_alt;            /* number of alternative settings */
+       unsigned int *alt_max_pkt_size_isoc; /* array of isoc wMaxPacketSize */
+       unsigned int analog_xfer_bulk:1;        /* use bulk instead of isoc
+                                                  transfers for analog      */
+       int dvb_alt_isoc;       /* alternate setting for DVB isoc transfers */
+       unsigned int dvb_max_pkt_size_isoc;     /* isoc max packet size of the
+                                                  selected DVB ep at dvb_alt */
+       unsigned int dvb_xfer_bulk:1;           /* use bulk instead of isoc
+                                                  transfers for DVB          */
        char urb_buf[URB_MAX_CTRL_SIZE];        /* urb control msg buffer */
 
        /* helper funcs that call usb_control_msg */
@@ -666,12 +684,14 @@ int em28xx_vbi_supported(struct em28xx *dev);
 int em28xx_set_outfmt(struct em28xx *dev);
 int em28xx_resolution_set(struct em28xx *dev);
 int em28xx_set_alternate(struct em28xx *dev);
-int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                     int max_packets, int num_bufs, int max_pkt_size);
-int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                    int max_packets, int num_bufs, int max_pkt_size,
-                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
-void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode);
+int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
+                     int num_bufs, int max_pkt_size, int packet_multiplier);
+int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
+                        int xfer_bulk,
+                        int num_bufs, int max_pkt_size, int packet_multiplier,
+                        int (*urb_data_copy)
+                                       (struct em28xx *dev, struct urb *urb));
+void em28xx_uninit_usb_xfer(struct em28xx *dev, enum em28xx_mode mode);
 void em28xx_stop_urbs(struct em28xx *dev);
 int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
 int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
index 62ba80d9b9988478dbc9727eb1b6a50d210b583c..fdaeeb14453fbb42d82d9d31c0d64e088333bed2 100644 (file)
@@ -536,20 +536,4 @@ static struct usb_driver sd_driver = {
 #endif
 };
 
-/* -- module insert / remove -- */
-static int __init sd_mod_init(void)
-{
-       int ret;
-
-       ret = usb_register(&sd_driver);
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-static void __exit sd_mod_exit(void)
-{
-       usb_deregister(&sd_driver);
-}
-
-module_init(sd_mod_init);
-module_exit(sd_mod_exit);
+module_usb_driver(sd_driver);
index 40ad6687ee5dee1e53cad6489a386438f5d2a483..3773a8a745df9323719d4aaeb6dd949fa0e61cad 100644 (file)
@@ -381,6 +381,7 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x045e, 0x02ae)},
+       {USB_DEVICE(0x045e, 0x02bf)},
        {}
 };
 
index d236d1791f78da1ff0bdf965b8dde6389d169155..1f253dfebe4709da0de86fe6517eca5191e5eee2 100644 (file)
@@ -55,6 +55,11 @@ MODULE_LICENSE("GPL");
 
 #define PAC207_AUTOGAIN_DEADZONE       30
 
+/* global parameters */
+static int led_invert;
+module_param(led_invert, int, 0644);
+MODULE_PARM_DESC(led_invert, "Invert led");
+
 /* specific webcam descriptor */
 struct sd {
        struct gspca_dev gspca_dev;             /* !! must be the first item */
@@ -187,10 +192,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-       pac207_write_reg(gspca_dev, 0x41, 0x00);
-                               /* Bit_0=Image Format,
-                                * Bit_1=LED,
-                                * Bit_2=Compression test mode enable */
+       u8 mode;
+
+       /* mode: Image Format (Bit 0), LED (1), Compr. test mode (2) */
+       if (led_invert)
+               mode = 0x02;
+       else
+               mode = 0x00;
+       pac207_write_reg(gspca_dev, 0x41, mode);
        pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
 
        return gspca_dev->usb_err;
@@ -303,7 +312,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
        pac207_write_reg(gspca_dev, 0x02,
                v4l2_ctrl_g_ctrl(gspca_dev->exposure)); /* PXCK = 12MHz /n */
 
-       mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
+       /* mode: Image Format (Bit 0), LED (1), Compr. test mode (2) */
+       if (led_invert)
+               mode = 0x00;
+       else
+               mode = 0x02;
        if (gspca_dev->width == 176) {  /* 176x144 */
                mode |= 0x01;
                PDEBUG(D_STREAM, "pac207_start mode 176x144");
@@ -325,8 +338,15 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
+       u8 mode;
+
+       /* mode: Image Format (Bit 0), LED (1), Compr. test mode (2) */
+       if (led_invert)
+               mode = 0x02;
+       else
+               mode = 0x00;
        pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
-       pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
+       pac207_write_reg(gspca_dev, 0x41, mode); /* Turn off LED */
        pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
 }
 
index 70511d5f953857492aca04655cdf079836a998dc..1220340e76028654385ec448c7a98a310d3d89f6 100644 (file)
@@ -496,7 +496,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
        }
 }
 
-static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
+static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf)
 {
        int retry = 60;
 
@@ -504,16 +504,19 @@ static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
                return;
 
        /* is i2c ready */
-       reg_w(gspca_dev, 0x08, buffer, 8);
+       reg_w(gspca_dev, 0x08, buf, 8);
        while (retry--) {
                if (gspca_dev->usb_err < 0)
                        return;
-               msleep(10);
+               msleep(1);
                reg_r(gspca_dev, 0x08);
                if (gspca_dev->usb_buf[0] & 0x04) {
                        if (gspca_dev->usb_buf[0] & 0x08) {
                                dev_err(gspca_dev->v4l2_dev.dev,
-                                       "i2c write error\n");
+                                       "i2c error writing %02x %02x %02x %02x"
+                                       " %02x %02x %02x %02x\n",
+                                       buf[0], buf[1], buf[2], buf[3],
+                                       buf[4], buf[5], buf[6], buf[7]);
                                gspca_dev->usb_err = -EIO;
                        }
                        return;
@@ -530,7 +533,7 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev,
        for (;;) {
                if (gspca_dev->usb_err < 0)
                        return;
-               reg_w(gspca_dev, 0x08, *buffer, 8);
+               i2c_w(gspca_dev, *buffer);
                len -= 8;
                if (len <= 0)
                        break;
index 5a86047b846f484c2d1c22d88023878d2249b646..36307a9028a932b6414523e0a189c613479daa90 100644 (file)
@@ -1550,6 +1550,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
                        0,
                        gspca_dev->usb_buf, 8,
                        500);
+       msleep(2);
        if (ret < 0) {
                pr_err("i2c_w1 err %d\n", ret);
                gspca_dev->usb_err = ret;
index 748e1421d6d8c93bdb993c1aaf32d09d8297fca2..e95fa8997d22c33e2318b5946ffbe72723346f1a 100644 (file)
@@ -52,9 +52,13 @@ static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case V4L2_CID_HFLIP:
+               if (!gspca_dev->streaming)
+                       return 0;
                err = vv6410_set_hflip(gspca_dev, ctrl->val);
                break;
        case V4L2_CID_VFLIP:
+               if (!gspca_dev->streaming)
+                       return 0;
                err = vv6410_set_vflip(gspca_dev, ctrl->val);
                break;
        case V4L2_CID_GAIN:
@@ -94,11 +98,14 @@ static int vv6410_init_controls(struct sd *sd)
 {
        struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
 
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_handler_init(hdl, 2);
+       /* Disable the hardware VFLIP and HFLIP as we currently lack a
+          mechanism to adjust the image offset in such a way that
+          we don't need to renegotiate the announced format */
+       /* v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, */
+       /*              V4L2_CID_HFLIP, 0, 1, 1, 0); */
+       /* v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, */
+       /*              V4L2_CID_VFLIP, 0, 1, 1, 0); */
        v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
                        V4L2_CID_EXPOSURE, 0, 32768, 1, 20000);
        v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
index 8bc6c3ceec2cf7c70df161990101f423d8952daf..b92d4ef2de6e399801832622d94c2ce1cb8ca297 100644 (file)
@@ -494,7 +494,7 @@ static void setcolors(struct gspca_dev *gspca_dev, s32 val)
 
 static void setgamma(struct gspca_dev *gspca_dev, s32 val)
 {
-       PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
+       PDEBUG(D_CONF, "Gamma: %d", val);
        reg_w_ixbuf(gspca_dev, 0x90,
                gamma_table[val], sizeof gamma_table[0]);
 }
index 5210239cbaeefcc9b92cd548bfbe1c010fd6b89d..21c15233c6ae1556384add1f5a994b98e4bf9c56 100644 (file)
@@ -316,7 +316,8 @@ static void pwc_isoc_handler(struct urb *urb)
                        struct pwc_frame_buf *fbuf = pdev->fill_buf;
 
                        if (pdev->vsync == 1) {
-                               do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
+                               v4l2_get_timestamp(
+                                       &fbuf->vb.v4l2_buf.timestamp);
                                pdev->vsync = 2;
                        }
 
index 8ebec0d7bf59509bd19ea1756528e1e9407fbe45..498c57ea5d32c2c0176aea4ca0f429a2eded85b6 100644 (file)
@@ -593,7 +593,7 @@ static int s2255_got_frame(struct s2255_channel *channel, int jpgsize)
        buf = list_entry(dma_q->active.next,
                         struct s2255_buffer, vb.queue);
        list_del(&buf->vb.queue);
-       do_gettimeofday(&buf->vb.ts);
+       v4l2_get_timestamp(&buf->vb.ts);
        s2255_fillbuff(channel, buf, jpgsize);
        wake_up(&buf->vb.done);
        dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i);
@@ -629,7 +629,6 @@ static void s2255_fillbuff(struct s2255_channel *channel,
                           struct s2255_buffer *buf, int jpgsize)
 {
        int pos = 0;
-       struct timeval ts;
        const char *tmpbuf;
        char *vbuf = videobuf_to_vmalloc(&buf->vb);
        unsigned long last_frame;
@@ -674,8 +673,7 @@ static void s2255_fillbuff(struct s2255_channel *channel,
        /* tell v4l buffer was filled */
 
        buf->vb.field_count = channel->frame_count * 2;
-       do_gettimeofday(&ts);
-       buf->vb.ts = ts;
+       v4l2_get_timestamp(&buf->vb.ts);
        buf->vb.state = VIDEOBUF_DONE;
 }
 
index 73605864fffadb98ce9e780cf8499bee83a1704c..6bda81aebf87fca620abb1ae16bdad7af2fe83ed 100644 (file)
@@ -173,7 +173,7 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
                cam->frame[i].buf.sequence = 0;
                cam->frame[i].buf.field = V4L2_FIELD_NONE;
                cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
-               cam->frame[i].buf.flags = 0;
+               cam->frame[i].buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        }
 
        return cam->nbuffers;
@@ -773,7 +773,8 @@ end_of_frame:
                                       img);
 
                                if ((*f)->buf.bytesused == 0)
-                                       do_gettimeofday(&(*f)->buf.timestamp);
+                                       v4l2_get_timestamp(
+                                               &(*f)->buf.timestamp);
 
                                (*f)->buf.bytesused += img;
 
index fa3671de02aa66081019f9d102339a0c6873f972..0a4ee85f43999e2d9374453ecf86339e2006ea7d 100644 (file)
@@ -101,7 +101,7 @@ void stk1160_buffer_done(struct stk1160 *dev)
        buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
        buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
        buf->vb.v4l2_buf.bytesused = buf->bytesused;
-       do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
+       v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 
        vb2_set_plane_payload(&buf->vb, 0, buf->bytesused);
        vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
index 5d3c032d733cf6e92ca7b345de95862204cd3d91..4cbab085e3483f9bf03fe21c73b72d139bcd7d1a 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
+#include <linux/dmi.h>
 #include <linux/usb.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include "stk-webcam.h"
 
 
-static bool hflip;
-module_param(hflip, bool, 0444);
+static int hflip = -1;
+module_param(hflip, int, 0444);
 MODULE_PARM_DESC(hflip, "Horizontal image flip (mirror). Defaults to 0");
 
-static bool vflip;
-module_param(vflip, bool, 0444);
+static int vflip = -1;
+module_param(vflip, int, 0444);
 MODULE_PARM_DESC(vflip, "Vertical image flip. Defaults to 0");
 
 static int debug;
@@ -62,6 +63,19 @@ static struct usb_device_id stkwebcam_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, stkwebcam_table);
 
+/* The stk webcam laptop module is mounted upside down in some laptops :( */
+static const struct dmi_system_id stk_upside_down_dmi_table[] = {
+       {
+               .ident = "ASUS G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "G1")
+               }
+       },
+       {}
+};
+
+
 /*
  * Basic stuff
  */
@@ -466,6 +480,7 @@ static int stk_setup_siobuf(struct stk_camera *dev, int index)
        buf->dev = dev;
        buf->v4lbuf.index = index;
        buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf->v4lbuf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        buf->v4lbuf.field = V4L2_FIELD_NONE;
        buf->v4lbuf.memory = V4L2_MEMORY_MMAP;
        buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length;
@@ -816,10 +831,16 @@ static int stk_vidioc_g_ctrl(struct file *filp,
                c->value = dev->vsettings.brightness;
                break;
        case V4L2_CID_HFLIP:
-               c->value = dev->vsettings.hflip;
+               if (dmi_check_system(stk_upside_down_dmi_table))
+                       c->value = !dev->vsettings.hflip;
+               else
+                       c->value = dev->vsettings.hflip;
                break;
        case V4L2_CID_VFLIP:
-               c->value = dev->vsettings.vflip;
+               if (dmi_check_system(stk_upside_down_dmi_table))
+                       c->value = !dev->vsettings.vflip;
+               else
+                       c->value = dev->vsettings.vflip;
                break;
        default:
                return -EINVAL;
@@ -836,10 +857,16 @@ static int stk_vidioc_s_ctrl(struct file *filp,
                dev->vsettings.brightness = c->value;
                return stk_sensor_set_brightness(dev, c->value >> 8);
        case V4L2_CID_HFLIP:
-               dev->vsettings.hflip = c->value;
+               if (dmi_check_system(stk_upside_down_dmi_table))
+                       dev->vsettings.hflip = !c->value;
+               else
+                       dev->vsettings.hflip = c->value;
                return 0;
        case V4L2_CID_VFLIP:
-               dev->vsettings.vflip = c->value;
+               if (dmi_check_system(stk_upside_down_dmi_table))
+                       dev->vsettings.vflip = !c->value;
+               else
+                       dev->vsettings.vflip = c->value;
                return 0;
        default:
                return -EINVAL;
@@ -1113,7 +1140,7 @@ static int stk_vidioc_dqbuf(struct file *filp,
        sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
        sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;
        sbuf->v4lbuf.sequence = ++dev->sequence;
-       do_gettimeofday(&sbuf->v4lbuf.timestamp);
+       v4l2_get_timestamp(&sbuf->v4lbuf.timestamp);
 
        *buf = sbuf->v4lbuf;
        return 0;
@@ -1275,8 +1302,18 @@ static int stk_camera_probe(struct usb_interface *interface,
        dev->interface = interface;
        usb_get_intf(interface);
 
-       dev->vsettings.vflip = vflip;
-       dev->vsettings.hflip = hflip;
+       if (hflip != -1)
+               dev->vsettings.hflip = hflip;
+       else if (dmi_check_system(stk_upside_down_dmi_table))
+               dev->vsettings.hflip = 1;
+       else
+               dev->vsettings.hflip = 0;
+       if (vflip != -1)
+               dev->vsettings.vflip = vflip;
+       else if (dmi_check_system(stk_upside_down_dmi_table))
+               dev->vsettings.vflip = 1;
+       else
+               dev->vsettings.vflip = 0;
        dev->n_sbufs = 0;
        set_present(dev);
 
index 3082bfa9b2c5d60fdc38a383344f915564b86e2f..21723378bb8f7d7ae84ab647958b9066ab1e3c34 100644 (file)
@@ -212,7 +212,7 @@ static void submit_frame(struct front_face *front)
        front->curr_frame       = NULL;
        vb->state               = VIDEOBUF_DONE;
        vb->field_count++;
-       do_gettimeofday(&vb->ts);
+       v4l2_get_timestamp(&vb->ts);
 
        wake_up(&vb->done);
 }
index e1f3f66e1e63018f3db3074bfb276f765808dc96..9fc1e940a82b6684e3a16192b0f5ffbcc7b89b00 100644 (file)
@@ -360,8 +360,8 @@ dvb_dmx_err:
        dvb_dmx_release(&dvb->demux);
 frontend_err:
        if (dvb->frontend) {
-               dvb_frontend_detach(dvb->frontend);
                dvb_unregister_frontend(dvb->frontend);
+               dvb_frontend_detach(dvb->frontend);
        }
 adapter_err:
        dvb_unregister_adapter(&dvb->adapter);
@@ -384,8 +384,8 @@ static void unregister_dvb(struct tm6000_core *dev)
 
 /*     mutex_lock(&tm6000_driver.open_close_mutex); */
        if (dvb->frontend) {
-               dvb_frontend_detach(dvb->frontend);
                dvb_unregister_frontend(dvb->frontend);
+               dvb_frontend_detach(dvb->frontend);
        }
 
        dvb_dmxdev_release(&dvb->dmxdev);
index f656fd7a39a27de037923320ea605c0fe14c1e83..e3c567c27918bd7321e168550df3df0e5941f8bf 100644 (file)
 #define TM6000_MIN_BUF 4
 #define TM6000_DEF_BUF 8
 
+#define TM6000_NUM_URB_BUF 8
+
 #define TM6000_MAX_ISO_PACKETS 46      /* Max number of ISO packets */
 
 /* Declare static vars that will be used as parameters */
 static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
 static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
 static int radio_nr = -1;              /* /dev/radioN, -1 for autodetect */
+static bool keep_urb;                  /* keep urb buffers allocated */
 
 /* Debug level */
 int tm6000_debug;
@@ -191,7 +194,7 @@ static inline void buffer_filled(struct tm6000_core *dev,
        dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
        buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
+       v4l2_get_timestamp(&buf->vb.ts);
 
        list_del(&buf->vb.queue);
        wake_up(&buf->vb.done);
@@ -537,6 +540,71 @@ static void tm6000_irq_callback(struct urb *urb)
                        urb->status);
 }
 
+/*
+ * Allocate URB buffers
+ */
+static int tm6000_alloc_urb_buffers(struct tm6000_core *dev)
+{
+       int num_bufs = TM6000_NUM_URB_BUF;
+       int i;
+
+       if (dev->urb_buffer != NULL)
+               return 0;
+
+       dev->urb_buffer = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+       if (!dev->urb_buffer) {
+               tm6000_err("cannot allocate memory for urb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->urb_dma = kmalloc(sizeof(dma_addr_t *)*num_bufs, GFP_KERNEL);
+       if (!dev->urb_dma) {
+               tm6000_err("cannot allocate memory for urb dma pointers\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < num_bufs; i++) {
+               dev->urb_buffer[i] = usb_alloc_coherent(
+                                       dev->udev, dev->urb_size,
+                                       GFP_KERNEL, &dev->urb_dma[i]);
+               if (!dev->urb_buffer[i]) {
+                       tm6000_err("unable to allocate %i bytes for transfer buffer %i\n",
+                                   dev->urb_size, i);
+                       return -ENOMEM;
+               }
+               memset(dev->urb_buffer[i], 0, dev->urb_size);
+       }
+
+       return 0;
+}
+
+/*
+ * Free URB buffers
+ */
+static int tm6000_free_urb_buffers(struct tm6000_core *dev)
+{
+       int i;
+
+       if (dev->urb_buffer == NULL)
+               return 0;
+
+       for (i = 0; i < TM6000_NUM_URB_BUF; i++) {
+               if (dev->urb_buffer[i]) {
+                       usb_free_coherent(dev->udev,
+                                       dev->urb_size,
+                                       dev->urb_buffer[i],
+                                       dev->urb_dma[i]);
+                       dev->urb_buffer[i] = NULL;
+               }
+       }
+       kfree(dev->urb_buffer);
+       kfree(dev->urb_dma);
+       dev->urb_buffer = NULL;
+       dev->urb_dma = NULL;
+
+       return 0;
+}
+
 /*
  * Stop and Deallocate URBs
  */
@@ -551,18 +619,15 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
                if (urb) {
                        usb_kill_urb(urb);
                        usb_unlink_urb(urb);
-                       if (dev->isoc_ctl.transfer_buffer[i]) {
-                               usb_free_coherent(dev->udev,
-                                               urb->transfer_buffer_length,
-                                               dev->isoc_ctl.transfer_buffer[i],
-                                               urb->transfer_dma);
-                       }
                        usb_free_urb(urb);
                        dev->isoc_ctl.urb[i] = NULL;
                }
                dev->isoc_ctl.transfer_buffer[i] = NULL;
        }
 
+       if (!keep_urb)
+               tm6000_free_urb_buffers(dev);
+
        kfree(dev->isoc_ctl.urb);
        kfree(dev->isoc_ctl.transfer_buffer);
 
@@ -572,12 +637,13 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
 }
 
 /*
- * Allocate URBs and start IRQ
+ * Assign URBs and start IRQ
  */
 static int tm6000_prepare_isoc(struct tm6000_core *dev)
 {
        struct tm6000_dmaqueue *dma_q = &dev->vidq;
-       int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
+       int i, j, sb_size, pipe, size, max_packets;
+       int num_bufs = TM6000_NUM_URB_BUF;
        struct urb *urb;
 
        /* De-allocates all pending stuff */
@@ -605,6 +671,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
 
        max_packets = TM6000_MAX_ISO_PACKETS;
        sb_size = max_packets * size;
+       dev->urb_size = sb_size;
 
        dev->isoc_ctl.num_bufs = num_bufs;
 
@@ -627,6 +694,17 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
                    max_packets, num_bufs, sb_size,
                    dev->isoc_in.maxsize, size);
 
+
+       if (!dev->urb_buffer && tm6000_alloc_urb_buffers(dev) < 0) {
+               tm6000_err("cannot allocate memory for urb buffers\n");
+
+               /* call free, as some buffers might have been allocated */
+               tm6000_free_urb_buffers(dev);
+               kfree(dev->isoc_ctl.urb);
+               kfree(dev->isoc_ctl.transfer_buffer);
+               return -ENOMEM;
+       }
+
        /* allocate urbs and transfer buffers */
        for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
                urb = usb_alloc_urb(max_packets, GFP_KERNEL);
@@ -638,17 +716,8 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
                }
                dev->isoc_ctl.urb[i] = urb;
 
-               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
-                       sb_size, GFP_KERNEL, &urb->transfer_dma);
-               if (!dev->isoc_ctl.transfer_buffer[i]) {
-                       tm6000_err("unable to allocate %i bytes for transfer"
-                                       " buffer %i%s\n",
-                                       sb_size, i,
-                                       in_interrupt() ? " while in int" : "");
-                       tm6000_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+               urb->transfer_dma = dev->urb_dma[i];
+               dev->isoc_ctl.transfer_buffer[i] = dev->urb_buffer[i];
 
                usb_fill_bulk_urb(urb, dev->udev, pipe,
                                  dev->isoc_ctl.transfer_buffer[i], sb_size,
@@ -1826,6 +1895,9 @@ int tm6000_v4l2_unregister(struct tm6000_core *dev)
 {
        video_unregister_device(dev->vfd);
 
+       /* if URB buffers are still allocated free them now */
+       tm6000_free_urb_buffers(dev);
+
        if (dev->radio_dev) {
                if (video_is_registered(dev->radio_dev))
                        video_unregister_device(dev->radio_dev);
@@ -1851,3 +1923,5 @@ MODULE_PARM_DESC(debug, "activates debug info");
 module_param(vid_limit, int, 0644);
 MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
 
+module_param(keep_urb, bool, 0);
+MODULE_PARM_DESC(keep_urb, "Keep urb buffers allocated even when the device is closed by the user");
index 6df418658c9cac977348cd19f60665e632b1c3d2..173dcd7a7284085d134ed168cb8c1a0775698529 100644 (file)
@@ -264,6 +264,11 @@ struct tm6000_core {
 
        spinlock_t                   slock;
 
+       /* urb dma buffers */
+       char                            **urb_buffer;
+       dma_addr_t                      *urb_dma;
+       unsigned int                    urb_size;
+
        unsigned long quirks;
 };
 
index c9b2042f8bdfa9310b7d3c53eb50181a0647a31d..816b1cffab7de245e49fb69fc1ea00876ff78cce 100644 (file)
@@ -1169,7 +1169,7 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision)
 
        if (newstate == parse_state_next_frame) {
                frame->grabstate = frame_state_done;
-               do_gettimeofday(&(frame->timestamp));
+               v4l2_get_timestamp(&(frame->timestamp));
                frame->sequence = usbvision->frame_num;
 
                spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
index 5c36a57e6590d6c731341663296faad17607a7ef..c6bc8ce673759a719dedce2e98fc546aa8629e76 100644 (file)
@@ -761,7 +761,7 @@ static int vidioc_querybuf(struct file *file,
        if (vb->index >= usbvision->num_frames)
                return -EINVAL;
        /* Updating the corresponding frame state */
-       vb->flags = 0;
+       vb->flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        frame = &usbvision->frame[vb->index];
        if (frame->grabstate >= frame_state_ready)
                vb->flags |= V4L2_BUF_FLAG_QUEUED;
@@ -843,7 +843,8 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *vb)
        vb->memory = V4L2_MEMORY_MMAP;
        vb->flags = V4L2_BUF_FLAG_MAPPED |
                V4L2_BUF_FLAG_QUEUED |
-               V4L2_BUF_FLAG_DONE;
+               V4L2_BUF_FLAG_DONE |
+               V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        vb->index = f->index;
        vb->sequence = f->sequence;
        vb->timestamp = f->timestamp;
index 39edd444293226406a4faed135930dcf09ff059c..74d56df3347f59329ec6c4538023592c863bc1ac 100644 (file)
@@ -501,7 +501,6 @@ static void zr364xx_fillbuff(struct zr364xx_camera *cam,
                             int jpgsize)
 {
        int pos = 0;
-       struct timeval ts;
        const char *tmpbuf;
        char *vbuf = videobuf_to_vmalloc(&buf->vb);
        unsigned long last_frame;
@@ -530,8 +529,7 @@ static void zr364xx_fillbuff(struct zr364xx_camera *cam,
        /* tell v4l buffer was filled */
 
        buf->vb.field_count = cam->frame_count * 2;
-       do_gettimeofday(&ts);
-       buf->vb.ts = ts;
+       v4l2_get_timestamp(&buf->vb.ts);
        buf->vb.state = VIDEOBUF_DONE;
 }
 
@@ -559,7 +557,7 @@ static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
                goto unlock;
        }
        list_del(&buf->vb.queue);
-       do_gettimeofday(&buf->vb.ts);
+       v4l2_get_timestamp(&buf->vb.ts);
        DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
        zr364xx_fillbuff(cam, buf, jpgsize);
        wake_up(&buf->vb.done);
index 380ddd89fa4c6f8d6c1bb1b612eeb97fa8420a9f..614316f9b7a47d2dd2111932ee109ef7fd1bb17e 100644 (file)
@@ -978,3 +978,13 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
        return best;
 }
 EXPORT_SYMBOL_GPL(v4l2_find_nearest_format);
+
+void v4l2_get_timestamp(struct timeval *tv)
+{
+       struct timespec ts;
+
+       ktime_get_ts(&ts);
+       tv->tv_sec = ts.tv_sec;
+       tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+}
+EXPORT_SYMBOL_GPL(v4l2_get_timestamp);
index 438ea45d10749750a2941474265b0e72ea75f239..da99cf7271622bcde65495426686fc00e7beec02 100644 (file)
@@ -62,7 +62,7 @@ struct v4l2_m2m_dev {
        struct list_head        job_queue;
        spinlock_t              job_spinlock;
 
-       struct v4l2_m2m_ops     *m2m_ops;
+       const struct v4l2_m2m_ops *m2m_ops;
 };
 
 static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
@@ -519,7 +519,7 @@ EXPORT_SYMBOL(v4l2_m2m_mmap);
  *
  * Usually called from driver's probe() function.
  */
-struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops)
+struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops)
 {
        struct v4l2_m2m_dev *m2m_dev;
 
index 5449e8aa984a7b9ba18d1f02679a68d976411f9c..fb5ee5dd8fe933cbdd371aeecf41a3047d2e0e39 100644 (file)
@@ -340,7 +340,7 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
                break;
        }
 
-       b->flags    = 0;
+       b->flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        if (vb->map)
                b->flags |= V4L2_BUF_FLAG_MAPPED;
 
index 9f81be23a81f06a1d527ac792071e1b7a6154979..85e3c221dadc2783175e34f0d34a06ad81ddbbbd 100644 (file)
@@ -40,9 +40,10 @@ module_param(debug, int, 0644);
 #define call_qop(q, op, args...)                                       \
        (((q)->ops->op) ? ((q)->ops->op(args)) : 0)
 
-#define V4L2_BUFFER_STATE_FLAGS        (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
+#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
                                 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
-                                V4L2_BUF_FLAG_PREPARED)
+                                V4L2_BUF_FLAG_PREPARED | \
+                                V4L2_BUF_FLAG_TIMESTAMP_MASK)
 
 /**
  * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
@@ -401,7 +402,8 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        /*
         * Clear any buffer state related flags.
         */
-       b->flags &= ~V4L2_BUFFER_STATE_FLAGS;
+       b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
+       b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
        switch (vb->state) {
        case VB2_BUF_STATE_QUEUED:
@@ -939,7 +941,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 
        vb->v4l2_buf.field = b->field;
        vb->v4l2_buf.timestamp = b->timestamp;
-       vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
+       vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
 }
 
 /**
index 427218b8b10f435e5f9dcd7dbc3751a572b0566f..ae0abc350e340221af485aa9634d712124534430 100644 (file)
@@ -23,6 +23,8 @@ source "drivers/staging/media/as102/Kconfig"
 
 source "drivers/staging/media/cxd2099/Kconfig"
 
+source "drivers/staging/media/davinci_vpfe/Kconfig"
+
 source "drivers/staging/media/dt3155v4l/Kconfig"
 
 source "drivers/staging/media/go7007/Kconfig"
index aec6eb96394033c156a9731a5503f813c9193393..2b97cae9949942f0bfc96269ca49d5e11ec2013f 100644 (file)
@@ -4,3 +4,4 @@ obj-$(CONFIG_LIRC_STAGING)      += lirc/
 obj-$(CONFIG_SOLO6X10)         += solo6x10/
 obj-$(CONFIG_VIDEO_DT3155)     += dt3155v4l/
 obj-$(CONFIG_VIDEO_GO7007)     += go7007/
+obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
index d2a4bce896231f13985fcde28e8b1e8fcec26eca..4a2bbd76665541990d69009b133686ae7b947fd6 100644 (file)
@@ -197,7 +197,7 @@ out:
  * @prsp:       pointer to AS10x command response buffer
  * @proc_id:    id of the command
  *
- * Since the contex command reponse does not follow the common
+ * Since the contex command response does not follow the common
  * response, a specific parse function is required.
  * Return 0 on success or negative value in case of error.
  */
index 0ff19724992fbe5de688620d22a4396ea0f381ef..822c487592a4df1d51efb40bb98b70680e87e4b2 100644 (file)
@@ -66,8 +66,9 @@ static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr,
        struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2};
 
        if (i2c_transfer(adapter, &msg, 1) != 1) {
-               printk(KERN_ERR "Failed to write to I2C register %02x@%02x!\n",
-                      reg, adr);
+               dev_err(&adapter->dev,
+                       "Failed to write to I2C register %02x@%02x!\n",
+                       reg, adr);
                return -1;
        }
        return 0;
@@ -79,7 +80,7 @@ static int i2c_write(struct i2c_adapter *adapter, u8 adr,
        struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len};
 
        if (i2c_transfer(adapter, &msg, 1) != 1) {
-               printk(KERN_ERR "Failed to write to I2C!\n");
+               dev_err(&adapter->dev, "Failed to write to I2C!\n");
                return -1;
        }
        return 0;
@@ -94,7 +95,7 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
                                   .buf = val, .len = 1} };
 
        if (i2c_transfer(adapter, msgs, 2) != 2) {
-               printk(KERN_ERR "error in i2c_read_reg\n");
+               dev_err(&adapter->dev, "error in i2c_read_reg\n");
                return -1;
        }
        return 0;
@@ -109,7 +110,7 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr,
                                 .buf = data, .len = n} };
 
        if (i2c_transfer(adapter, msgs, 2) != 2) {
-               printk(KERN_ERR "error in i2c_read\n");
+               dev_err(&adapter->dev, "error in i2c_read\n");
                return -1;
        }
        return 0;
@@ -277,7 +278,7 @@ static void cam_mode(struct cxd *ci, int mode)
 #ifdef BUFFER_MODE
                if (!ci->en.read_data)
                        return;
-               printk(KERN_INFO "enable cam buffer mode\n");
+               dev_info(&ci->i2c->dev, "enable cam buffer mode\n");
                /* write_reg(ci, 0x0d, 0x00); */
                /* write_reg(ci, 0x0e, 0x01); */
                write_regm(ci, 0x08, 0x40, 0x40);
@@ -524,7 +525,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
                        msleep(10);
 #if 0
                        read_reg(ci, 0x06, &val);
-                       printk(KERN_INFO "%d:%02x\n", i, val);
+                       dev_info(&ci->i2c->dev, "%d:%02x\n", i, val);
                        if (!(val&0x10))
                                break;
 #else
@@ -542,7 +543,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 {
        struct cxd *ci = ca->data;
 
-       printk(KERN_INFO "slot_shutdown\n");
+       dev_info(&ci->i2c->dev, "slot_shutdown\n");
        mutex_lock(&ci->lock);
        write_regm(ci, 0x09, 0x08, 0x08);
        write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */
@@ -578,10 +579,10 @@ static int campoll(struct cxd *ci)
 
        if (istat&0x40) {
                ci->dr = 1;
-               printk(KERN_INFO "DR\n");
+               dev_info(&ci->i2c->dev, "DR\n");
        }
        if (istat&0x20)
-               printk(KERN_INFO "WC\n");
+               dev_info(&ci->i2c->dev, "WC\n");
 
        if (istat&2) {
                u8 slotstat;
@@ -597,7 +598,7 @@ static int campoll(struct cxd *ci)
                        if (ci->slot_stat) {
                                ci->slot_stat = 0;
                                write_regm(ci, 0x03, 0x00, 0x08);
-                               printk(KERN_INFO "NO CAM\n");
+                               dev_info(&ci->i2c->dev, "NO CAM\n");
                                ci->ready = 0;
                        }
                }
@@ -634,7 +635,7 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
        campoll(ci);
        mutex_unlock(&ci->lock);
 
-       printk(KERN_INFO "read_data\n");
+       dev_info(&ci->i2c->dev, "read_data\n");
        if (!ci->dr)
                return 0;
 
@@ -687,7 +688,7 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
        u8 val;
 
        if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) {
-               printk(KERN_INFO "No CXD2099 detected at %02x\n", cfg->adr);
+               dev_info(&i2c->dev, "No CXD2099 detected at %02x\n", cfg->adr);
                return NULL;
        }
 
@@ -705,7 +706,7 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
        ci->en = en_templ;
        ci->en.data = ci;
        init(ci);
-       printk(KERN_INFO "Attached CXD2099AR at %02x\n", ci->cfg.adr);
+       dev_info(&i2c->dev, "Attached CXD2099AR at %02x\n", ci->cfg.adr);
        return &ci->en;
 }
 EXPORT_SYMBOL(cxd2099_attach);
index 19c588a595883be93f0cef4102e647fdbaa21e71..0eb607c5b4237db755684c5dbec7b6beb20d5bcb 100644 (file)
@@ -43,7 +43,7 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
 static inline struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
                                        void *priv, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
diff --git a/drivers/staging/media/davinci_vpfe/Kconfig b/drivers/staging/media/davinci_vpfe/Kconfig
new file mode 100644 (file)
index 0000000..2e4a28b
--- /dev/null
@@ -0,0 +1,9 @@
+config VIDEO_DM365_VPFE
+       tristate "DM365 VPFE Media Controller Capture Driver"
+       depends on VIDEO_V4L2 && ARCH_DAVINCI_DM365 && !VIDEO_VPFE_CAPTURE
+       select VIDEOBUF2_DMA_CONTIG
+       help
+         Support for DM365 VPFE based Media Controller Capture driver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vpfe-mc-capture.
diff --git a/drivers/staging/media/davinci_vpfe/Makefile b/drivers/staging/media/davinci_vpfe/Makefile
new file mode 100644 (file)
index 0000000..c64515c
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_VIDEO_DM365_VPFE) += \
+       dm365_isif.o dm365_ipipe_hw.o dm365_ipipe.o \
+       dm365_resizer.o dm365_ipipeif.o vpfe_mc_capture.o vpfe_video.o
diff --git a/drivers/staging/media/davinci_vpfe/TODO b/drivers/staging/media/davinci_vpfe/TODO
new file mode 100644 (file)
index 0000000..7015ab3
--- /dev/null
@@ -0,0 +1,37 @@
+TODO (general):
+==================================
+
+- User space interface refinement
+        - Controls should be used when possible rather than private ioctl
+        - No enums should be used
+        - Use of MC and V4L2 subdev APIs when applicable
+        - Single interface header might suffice
+        - Current interface forces to configure everything at once
+- Get rid of the dm365_ipipe_hw.[ch] layer
+- Active external sub-devices defined by link configuration; no strcmp
+  needed
+- More generic platform data (i2c adapters)
+- The driver should have no knowledge of possible external subdevs; see
+  struct vpfe_subdev_id
+- Some of the hardware control should be refactorede
+- Check proper serialisation (through mutexes and spinlocks)
+- Names that are visible in kernel global namespace should have a common
+  prefix (or a few)
+- While replacing the older driver in media folder, provide a compatibility
+  layer and compatibility tests that warrants (using the libv4l's LD_PRELOAD
+  approach) there is no regression for the users using the older driver.
+
+Building of uImage and Applications:
+==================================
+
+As of now since the interface will undergo few changes all the include
+files are present in staging itself, to build for dm365 follow below steps,
+
+- copy vpfe.h from drivers/staging/media/davinci_vpfe/ to
+  include/media/davinci/ folder for building the uImage.
+- copy davinci_vpfe_user.h from drivers/staging/media/davinci_vpfe/ to
+  include/uapi/linux/davinci_vpfe.h, and add a entry in Kbuild (required
+  for building application).
+- copy dm365_ipipeif_user.h from drivers/staging/media/davinci_vpfe/ to
+  include/uapi/linux/dm365_ipipeif.h and a entry in Kbuild (required
+  for building application).
diff --git a/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt b/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt
new file mode 100644 (file)
index 0000000..1dbd564
--- /dev/null
@@ -0,0 +1,154 @@
+Davinci Video processing Front End (VPFE) driver
+
+Copyright (C) 2012 Texas Instruments Inc
+
+Contacts: Manjunath Hadli <manjunath.hadli@ti.com>
+         Prabhakar Lad <prabhakar.lad@ti.com>
+
+
+Introduction
+============
+
+This file documents the Texas Instruments Davinci Video processing Front End
+(VPFE) driver located under drivers/media/platform/davinci. The original driver
+exists for Davinci VPFE, which is now being changed to Media Controller
+Framework.
+
+Currently the driver has been successfully used on the following
+version of Davinci:
+
+       DM365/DM368
+
+The driver implements V4L2, Media controller and v4l2_subdev interfaces. Sensor,
+lens and flash drivers using the v4l2_subdev interface in the kernel are
+supported.
+
+
+Split to subdevs
+================
+
+The Davinci VPFE is split into V4L2 subdevs, each of the blocks inside the VPFE
+having one subdev to represent it. Each of the subdevs provide a V4L2 subdev
+interface to userspace.
+
+       DAVINCI ISIF
+       DAVINCI IPIPEIF
+       DAVINCI IPIPE
+       DAVINCI CROP RESIZER
+       DAVINCI RESIZER A
+       DAVINCI RESIZER B
+
+Each possible link in the VPFE is modeled by a link in the Media controller
+interface. For an example program see [1].
+
+
+ISIF, IPIPE, and RESIZER block IOCTLs
+======================================
+
+The Davinci Video processing Front End (VPFE) driver supports standard V4L2
+IOCTLs and controls where possible and practical. Much of the functions provided
+by the VPFE, however, does not fall under the standard IOCTL's.
+
+In general, there is a private ioctl for configuring each of the blocks
+containing hardware-dependent functions.
+
+The following private IOCTLs are supported:
+
+       VIDIOC_VPFE_ISIF_[S/G]_RAW_PARAMS
+       VIDIOC_VPFE_IPIPE_[S/G]_CONFIG
+       VIDIOC_VPFE_RSZ_[S/G]_CONFIG
+
+The parameter structures used by these ioctl's are described in
+include/uapi/linux/davinci_vpfe.h.
+
+The VIDIOC_VPFE_ISIF_S_RAW_PARAMS, VIDIOC_VPFE_IPIPE_S_CONFIG and
+VIDIOC_VPFE_RSZ_S_CONFIG are used to configure, enable and disable functions in
+the isif, ipipe and resizer blocks respectively. These IOCTL's control several
+functions in the blocks they control. VIDIOC_VPFE_ISIF_S_RAW_PARAMS IOCTL
+accepts a pointer to struct vpfe_isif_raw_config as its argument. Similarly
+VIDIOC_VPFE_IPIPE_S_CONFIG accepts a pointer to struct vpfe_ipipe_config. And
+VIDIOC_VPFE_RSZ_S_CONFIG accepts a pointer to struct vpfe_rsz_config as its
+argument. Similarly VIDIOC_VPFE_ISIF_G_RAW_PARAMS, VIDIOC_VPFE_IPIPE_G_CONFIG
+and VIDIOC_VPFE_RSZ_G_CONFIG are used to get the current configuration set in
+the isif, ipipe and resizer blocks respectively.
+
+The detailed functions of the VPFE itself related to a given VPFE block is
+described in the Technical Reference Manuals (TRMs) --- see the end of the
+document for those.
+
+
+IPIPEIF block IOCTLs
+======================================
+
+The following private IOCTLs are supported:
+
+       VIDIOC_VPFE_IPIPEIF_[S/G]_CONFIG
+
+The parameter structures used by these ioctl's are described in
+include/uapi/linux/dm365_ipipeif.h
+
+The VIDIOC_VPFE_IPIPEIF_S_CONFIG is used to configure the ipipeif
+hardware block. The VIDIOC_VPFE_IPIPEIF_S_CONFIG and
+VIDIOC_VPFE_IPIPEIF_G_CONFIG accepts a pointer to struct ipipeif_params
+as its argument.
+
+
+VPFE Operating Modes
+==========================================
+
+a: Continuous Modes
+------------------------
+
+1: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> SDRAM
+
+2: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> DAVINCI IPIPEIF--->|
+                                                                   |
+   <--------------------<----------------<---------------------<---|
+   |
+   V
+ DAVINCI CROP RESIZER--->DAVINCI RESIZER [A/B]---> SDRAM
+
+3: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> DAVINCI IPIPEIF--->|
+                                                                   |
+   <--------------------<----------------<---------------------<---|
+   |
+   V
+ DAVINCI IPIPE---> DAVINCI CROP RESIZER--->DAVINCI RESIZER [A/B]---> SDRAM
+
+a: Single Shot Modes
+------------------------
+
+1: SDRAM---> DAVINCI IPIPEIF---> DAVINCI IPIPE---> DAVINCI CROP RESIZER--->|
+                                                                           |
+   <----------------<----------------<------------------<---------------<--|
+   |
+   V
+DAVINCI RESIZER [A/B]---> SDRAM
+
+2: SDRAM---> DAVINCI IPIPEIF---> DAVINCI CROP RESIZER--->|
+                                                         |
+   <----------------<----------------<---------------<---|
+   |
+   V
+DAVINCI RESIZER [A/B]---> SDRAM
+
+
+Technical reference manuals (TRMs) and other documentation
+==========================================================
+
+Davinci DM365 TRM:
+<URL:http://www.ti.com/lit/ds/sprs457e/sprs457e.pdf>
+Referenced MARCH 2009-REVISED JUNE 2011
+
+Davinci DM368 TRM:
+<URL:http://www.ti.com/lit/ds/sprs668c/sprs668c.pdf>
+Referenced APRIL 2010-REVISED JUNE 2011
+
+Davinci Video Processing Front End (VPFE) DM36x
+<URL:http://www.ti.com/lit/ug/sprufg8c/sprufg8c.pdf>
+
+
+References
+==========
+
+[1] http://git.ideasonboard.org/?p=media-ctl.git;a=summary
diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h
new file mode 100644 (file)
index 0000000..7b7e7b2
--- /dev/null
@@ -0,0 +1,1290 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_USER_H
+#define _DAVINCI_VPFE_USER_H
+
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+/*
+ * Private IOCTL
+ *
+ * VIDIOC_VPFE_ISIF_S_RAW_PARAMS: Set raw params in isif
+ * VIDIOC_VPFE_ISIF_G_RAW_PARAMS: Get raw params from isif
+ * VIDIOC_VPFE_PRV_S_CONFIG: Set ipipe engine configuration
+ * VIDIOC_VPFE_PRV_G_CONFIG: Get ipipe engine configuration
+ * VIDIOC_VPFE_RSZ_S_CONFIG: Set resizer engine configuration
+ * VIDIOC_VPFE_RSZ_G_CONFIG: Get resizer engine configuration
+ */
+
+#define VIDIOC_VPFE_ISIF_S_RAW_PARAMS \
+       _IOW('V', BASE_VIDIOC_PRIVATE + 1,  struct vpfe_isif_raw_config)
+#define VIDIOC_VPFE_ISIF_G_RAW_PARAMS \
+       _IOR('V', BASE_VIDIOC_PRIVATE + 2, struct vpfe_isif_raw_config)
+#define VIDIOC_VPFE_IPIPE_S_CONFIG \
+       _IOWR('P', BASE_VIDIOC_PRIVATE + 3, struct vpfe_ipipe_config)
+#define VIDIOC_VPFE_IPIPE_G_CONFIG \
+       _IOWR('P', BASE_VIDIOC_PRIVATE + 4, struct vpfe_ipipe_config)
+#define VIDIOC_VPFE_RSZ_S_CONFIG \
+       _IOWR('R', BASE_VIDIOC_PRIVATE + 5, struct vpfe_rsz_config)
+#define VIDIOC_VPFE_RSZ_G_CONFIG \
+       _IOWR('R', BASE_VIDIOC_PRIVATE + 6, struct vpfe_rsz_config)
+
+/*
+ * Private Control's for ISIF
+ */
+#define VPFE_ISIF_CID_CRGAIN           (V4L2_CID_USER_BASE | 0xa001)
+#define VPFE_ISIF_CID_CGRGAIN          (V4L2_CID_USER_BASE | 0xa002)
+#define VPFE_ISIF_CID_CGBGAIN          (V4L2_CID_USER_BASE | 0xa003)
+#define VPFE_ISIF_CID_CBGAIN           (V4L2_CID_USER_BASE | 0xa004)
+#define VPFE_ISIF_CID_GAIN_OFFSET      (V4L2_CID_USER_BASE | 0xa005)
+
+/*
+ * Private Control's for ISIF and IPIPEIF
+ */
+#define VPFE_CID_DPCM_PREDICTOR                (V4L2_CID_USER_BASE | 0xa006)
+
+/************************************************************************
+ *   Vertical Defect Correction parameters
+ ***********************************************************************/
+
+/**
+ * vertical defect correction methods
+ */
+enum vpfe_isif_vdfc_corr_mode {
+       /* Defect level subtraction. Just fed through if saturating */
+       VPFE_ISIF_VDFC_NORMAL,
+       /**
+        * Defect level subtraction. Horizontal interpolation ((i-2)+(i+2))/2
+        * if data saturating
+        */
+       VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT,
+       /* Horizontal interpolation (((i-2)+(i+2))/2) */
+       VPFE_ISIF_VDFC_HORZ_INTERPOL
+};
+
+/**
+ * Max Size of the Vertical Defect Correction table
+ */
+#define VPFE_ISIF_VDFC_TABLE_SIZE      8
+
+/**
+ * Values used for shifting up the vdfc defect level
+ */
+enum vpfe_isif_vdfc_shift {
+       /* No Shift */
+       VPFE_ISIF_VDFC_NO_SHIFT,
+       /* Shift by 1 bit */
+       VPFE_ISIF_VDFC_SHIFT_1,
+       /* Shift by 2 bit */
+       VPFE_ISIF_VDFC_SHIFT_2,
+       /* Shift by 3 bit */
+       VPFE_ISIF_VDFC_SHIFT_3,
+       /* Shift by 4 bit */
+       VPFE_ISIF_VDFC_SHIFT_4
+};
+
+/**
+ * Defect Correction (DFC) table entry
+ */
+struct vpfe_isif_vdfc_entry {
+       /* vertical position of defect */
+       unsigned short pos_vert;
+       /* horizontal position of defect */
+       unsigned short pos_horz;
+       /**
+        * Defect level of Vertical line defect position. This is subtracted
+        * from the data at the defect position
+        */
+       unsigned char level_at_pos;
+       /**
+        * Defect level of the pixels upper than the vertical line defect.
+        * This is subtracted from the data
+        */
+       unsigned char level_up_pixels;
+       /**
+        * Defect level of the pixels lower than the vertical line defect.
+        * This is subtracted from the data
+        */
+       unsigned char level_low_pixels;
+};
+
+/**
+ * Structure for Defect Correction (DFC) parameter
+ */
+struct vpfe_isif_dfc {
+       /* enable vertical defect correction */
+       unsigned char en;
+       /* Correction methods */
+       enum vpfe_isif_vdfc_corr_mode corr_mode;
+       /**
+        * 0 - whole line corrected, 1 - not
+        * pixels upper than the defect
+        */
+       unsigned char corr_whole_line;
+       /**
+        * defect level shift value. level_at_pos, level_upper_pos,
+        * and level_lower_pos can be shifted up by this value
+        */
+       enum vpfe_isif_vdfc_shift def_level_shift;
+       /* defect saturation level */
+       unsigned short def_sat_level;
+       /* number of vertical defects. Max is VPFE_ISIF_VDFC_TABLE_SIZE */
+       short num_vdefects;
+       /* VDFC table ptr */
+       struct vpfe_isif_vdfc_entry table[VPFE_ISIF_VDFC_TABLE_SIZE];
+};
+
+/************************************************************************
+*   Digital/Black clamp or DC Subtract parameters
+************************************************************************/
+/**
+ * Horizontal Black Clamp modes
+ */
+enum vpfe_isif_horz_bc_mode {
+       /**
+        * Horizontal clamp disabled. Only vertical clamp
+        * value is subtracted
+        */
+       VPFE_ISIF_HORZ_BC_DISABLE,
+       /**
+        * Horizontal clamp value is calculated and subtracted
+        * from image data along with vertical clamp value
+        */
+       VPFE_ISIF_HORZ_BC_CLAMP_CALC_ENABLED,
+       /**
+        * Horizontal clamp value calculated from previous image
+        * is subtracted from image data along with vertical clamp
+        * value. How the horizontal clamp value for the first image
+        * is calculated in this case ???
+        */
+       VPFE_ISIF_HORZ_BC_CLAMP_NOT_UPDATED
+};
+
+/**
+ * Base window selection for Horizontal Black Clamp calculations
+ */
+enum vpfe_isif_horz_bc_base_win_sel {
+       /* Select Most left window for bc calculation */
+       VPFE_ISIF_SEL_MOST_LEFT_WIN,
+
+       /* Select Most right window for bc calculation */
+       VPFE_ISIF_SEL_MOST_RIGHT_WIN,
+};
+
+/* Size of window in horizontal direction for horizontal bc */
+enum vpfe_isif_horz_bc_sz_h {
+       VPFE_ISIF_HORZ_BC_SZ_H_2PIXELS,
+       VPFE_ISIF_HORZ_BC_SZ_H_4PIXELS,
+       VPFE_ISIF_HORZ_BC_SZ_H_8PIXELS,
+       VPFE_ISIF_HORZ_BC_SZ_H_16PIXELS
+};
+
+/* Size of window in vertcal direction for vertical bc */
+enum vpfe_isif_horz_bc_sz_v {
+       VPFE_ISIF_HORZ_BC_SZ_H_32PIXELS,
+       VPFE_ISIF_HORZ_BC_SZ_H_64PIXELS,
+       VPFE_ISIF_HORZ_BC_SZ_H_128PIXELS,
+       VPFE_ISIF_HORZ_BC_SZ_H_256PIXELS
+};
+
+/**
+ * Structure for Horizontal Black Clamp config params
+ */
+struct vpfe_isif_horz_bclamp {
+       /* horizontal clamp mode */
+       enum vpfe_isif_horz_bc_mode mode;
+       /**
+        * pixel value limit enable.
+        *  0 - limit disabled
+        *  1 - pixel value limited to 1023
+        */
+       unsigned char clamp_pix_limit;
+       /**
+        * Select most left or right window for clamp val
+        * calculation
+        */
+       enum vpfe_isif_horz_bc_base_win_sel base_win_sel_calc;
+       /* Window count per color for calculation. range 1-32 */
+       unsigned char win_count_calc;
+       /* Window start position - horizontal for calculation. 0 - 8191 */
+       unsigned short win_start_h_calc;
+       /* Window start position - vertical for calculation 0 - 8191 */
+       unsigned short win_start_v_calc;
+       /* Width of the sample window in pixels for calculation */
+       enum vpfe_isif_horz_bc_sz_h win_h_sz_calc;
+       /* Height of the sample window in pixels for calculation */
+       enum vpfe_isif_horz_bc_sz_v win_v_sz_calc;
+};
+
+/**
+ * Black Clamp vertical reset values
+ */
+enum vpfe_isif_vert_bc_reset_val_sel {
+       /* Reset value used is the clamp value calculated */
+       VPFE_ISIF_VERT_BC_USE_HORZ_CLAMP_VAL,
+       /* Reset value used is reset_clamp_val configured */
+       VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL,
+       /* No update, previous image value is used */
+       VPFE_ISIF_VERT_BC_NO_UPDATE
+};
+
+enum vpfe_isif_vert_bc_sz_h {
+       VPFE_ISIF_VERT_BC_SZ_H_2PIXELS,
+       VPFE_ISIF_VERT_BC_SZ_H_4PIXELS,
+       VPFE_ISIF_VERT_BC_SZ_H_8PIXELS,
+       VPFE_ISIF_VERT_BC_SZ_H_16PIXELS,
+       VPFE_ISIF_VERT_BC_SZ_H_32PIXELS,
+       VPFE_ISIF_VERT_BC_SZ_H_64PIXELS
+};
+
+/**
+ * Structure for Vertical Black Clamp configuration params
+ */
+struct vpfe_isif_vert_bclamp {
+       /* Reset value selection for vertical clamp calculation */
+       enum vpfe_isif_vert_bc_reset_val_sel reset_val_sel;
+       /* U12 value if reset_sel = ISIF_BC_VERT_USE_CONFIG_CLAMP_VAL */
+       unsigned short reset_clamp_val;
+       /**
+        * U8Q8. Line average coefficient used in vertical clamp
+        * calculation
+        */
+       unsigned char line_ave_coef;
+       /* Width in pixels of the optical black region used for calculation. */
+       enum vpfe_isif_vert_bc_sz_h ob_h_sz_calc;
+       /* Height of the optical black region for calculation */
+       unsigned short ob_v_sz_calc;
+       /* Optical black region start position - horizontal. 0 - 8191 */
+       unsigned short ob_start_h;
+       /* Optical black region start position - vertical 0 - 8191 */
+       unsigned short ob_start_v;
+};
+
+/**
+ * Structure for Black Clamp configuration params
+ */
+struct vpfe_isif_black_clamp {
+       /**
+        * this offset value is added irrespective of the clamp
+        * enable status. S13
+        */
+       unsigned short dc_offset;
+       /**
+        * Enable black/digital clamp value to be subtracted
+        * from the image data
+        */
+       unsigned char en;
+       /**
+        * black clamp mode. same/separate clamp for 4 colors
+        * 0 - disable - same clamp value for all colors
+        * 1 - clamp value calculated separately for all colors
+        */
+       unsigned char bc_mode_color;
+       /* Vertical start position for bc subtraction */
+       unsigned short vert_start_sub;
+       /* Black clamp for horizontal direction */
+       struct vpfe_isif_horz_bclamp horz;
+       /* Black clamp for vertical direction */
+       struct vpfe_isif_vert_bclamp vert;
+};
+
+/*************************************************************************
+** Color Space Conversion (CSC)
+*************************************************************************/
+/**
+ * Number of Coefficient values used for CSC
+ */
+#define VPFE_ISIF_CSC_NUM_COEFF 16
+
+struct float_8_bit {
+       /* 8 bit integer part */
+       __u8 integer;
+       /* 8 bit decimal part */
+       __u8 decimal;
+};
+
+struct float_16_bit {
+       /* 16 bit integer part */
+       __u16 integer;
+       /* 16 bit decimal part */
+       __u16 decimal;
+};
+
+/*************************************************************************
+**  Color Space Conversion parameters
+*************************************************************************/
+/**
+ * Structure used for CSC config params
+ */
+struct vpfe_isif_color_space_conv {
+       /* Enable color space conversion */
+       unsigned char en;
+       /**
+        * csc coefficient table. S8Q5, M00 at index 0, M01 at index 1, and
+        * so forth
+        */
+       struct float_8_bit coeff[VPFE_ISIF_CSC_NUM_COEFF];
+};
+
+enum vpfe_isif_datasft {
+       /* No Shift */
+       VPFE_ISIF_NO_SHIFT,
+       /* 1 bit Shift */
+       VPFE_ISIF_1BIT_SHIFT,
+       /* 2 bit Shift */
+       VPFE_ISIF_2BIT_SHIFT,
+       /* 3 bit Shift */
+       VPFE_ISIF_3BIT_SHIFT,
+       /* 4 bit Shift */
+       VPFE_ISIF_4BIT_SHIFT,
+       /* 5 bit Shift */
+       VPFE_ISIF_5BIT_SHIFT,
+       /* 6 bit Shift */
+       VPFE_ISIF_6BIT_SHIFT
+};
+
+#define VPFE_ISIF_LINEAR_TAB_SIZE              192
+/*************************************************************************
+**  Linearization parameters
+*************************************************************************/
+/**
+ * Structure for Sensor data linearization
+ */
+struct vpfe_isif_linearize {
+       /* Enable or Disable linearization of data */
+       unsigned char en;
+       /* Shift value applied */
+       enum vpfe_isif_datasft corr_shft;
+       /* scale factor applied U11Q10 */
+       struct float_16_bit scale_fact;
+       /* Size of the linear table */
+       unsigned short table[VPFE_ISIF_LINEAR_TAB_SIZE];
+};
+
+/*************************************************************************
+**  ISIF Raw configuration parameters
+*************************************************************************/
+enum vpfe_isif_fmt_mode {
+       VPFE_ISIF_SPLIT,
+       VPFE_ISIF_COMBINE
+};
+
+enum vpfe_isif_lnum {
+       VPFE_ISIF_1LINE,
+       VPFE_ISIF_2LINES,
+       VPFE_ISIF_3LINES,
+       VPFE_ISIF_4LINES
+};
+
+enum vpfe_isif_line {
+       VPFE_ISIF_1STLINE,
+       VPFE_ISIF_2NDLINE,
+       VPFE_ISIF_3RDLINE,
+       VPFE_ISIF_4THLINE
+};
+
+struct vpfe_isif_fmtplen {
+       /**
+        * number of program entries for SET0, range 1 - 16
+        * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is
+        * ISIF_COMBINE
+        */
+       unsigned short plen0;
+       /**
+        * number of program entries for SET1, range 1 - 16
+        * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is
+        * ISIF_COMBINE
+        */
+       unsigned short plen1;
+       /**
+        * number of program entries for SET2, range 1 - 16
+        * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is
+        * ISIF_COMBINE
+        */
+       unsigned short plen2;
+       /**
+        * number of program entries for SET3, range 1 - 16
+        * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is
+        * ISIF_COMBINE
+        */
+       unsigned short plen3;
+};
+
+struct vpfe_isif_fmt_cfg {
+       /* Split or combine or line alternate */
+       enum vpfe_isif_fmt_mode fmtmode;
+       /* enable or disable line alternating mode */
+       unsigned char ln_alter_en;
+       /* Split/combine line number */
+       enum vpfe_isif_lnum lnum;
+       /* Address increment Range 1 - 16 */
+       unsigned int addrinc;
+};
+
+struct vpfe_isif_fmt_addr_ptr {
+       /* Initial address */
+       unsigned int init_addr;
+       /* output line number */
+       enum vpfe_isif_line out_line;
+};
+
+struct vpfe_isif_fmtpgm_ap {
+       /* program address pointer */
+       unsigned char pgm_aptr;
+       /* program address increment or decrement */
+       unsigned char pgmupdt;
+};
+
+struct vpfe_isif_data_formatter {
+       /* Enable/Disable data formatter */
+       unsigned char en;
+       /* data formatter configuration */
+       struct vpfe_isif_fmt_cfg cfg;
+       /* Formatter program entries length */
+       struct vpfe_isif_fmtplen plen;
+       /* first pixel in a line fed to formatter */
+       unsigned short fmtrlen;
+       /* HD interval for output line. Only valid when split line */
+       unsigned short fmthcnt;
+       /* formatter address pointers */
+       struct vpfe_isif_fmt_addr_ptr fmtaddr_ptr[16];
+       /* program enable/disable */
+       unsigned char pgm_en[32];
+       /* program address pointers */
+       struct vpfe_isif_fmtpgm_ap fmtpgm_ap[32];
+};
+
+struct vpfe_isif_df_csc {
+       /* Color Space Conversion configuration, 0 - csc, 1 - df */
+       unsigned int df_or_csc;
+       /* csc configuration valid if df_or_csc is 0 */
+       struct vpfe_isif_color_space_conv csc;
+       /* data formatter configuration valid if df_or_csc is 1 */
+       struct vpfe_isif_data_formatter df;
+       /* start pixel in a line at the input */
+       unsigned int start_pix;
+       /* number of pixels in input line */
+       unsigned int num_pixels;
+       /* start line at the input */
+       unsigned int start_line;
+       /* number of lines at the input */
+       unsigned int num_lines;
+};
+
+struct vpfe_isif_gain_offsets_adj {
+       /* Enable or Disable Gain adjustment for SDRAM data */
+       unsigned char gain_sdram_en;
+       /* Enable or Disable Gain adjustment for IPIPE data */
+       unsigned char gain_ipipe_en;
+       /* Enable or Disable Gain adjustment for H3A data */
+       unsigned char gain_h3a_en;
+       /* Enable or Disable Gain adjustment for SDRAM data */
+       unsigned char offset_sdram_en;
+       /* Enable or Disable Gain adjustment for IPIPE data */
+       unsigned char offset_ipipe_en;
+       /* Enable or Disable Gain adjustment for H3A data */
+       unsigned char offset_h3a_en;
+};
+
+struct vpfe_isif_cul {
+       /* Horizontal Cull pattern for odd lines */
+       unsigned char hcpat_odd;
+       /* Horizontal Cull pattern for even lines */
+       unsigned char hcpat_even;
+       /* Vertical Cull pattern */
+       unsigned char vcpat;
+       /* Enable or disable lpf. Apply when cull is enabled */
+       unsigned char en_lpf;
+};
+
+/* all the stuff in this struct will be provided by userland */
+struct vpfe_isif_raw_config {
+       /* Linearization parameters for image sensor data input */
+       struct vpfe_isif_linearize linearize;
+       /* Data formatter or CSC */
+       struct vpfe_isif_df_csc df_csc;
+       /* Defect Pixel Correction (DFC) confguration */
+       struct vpfe_isif_dfc dfc;
+       /* Black/Digital Clamp configuration */
+       struct vpfe_isif_black_clamp bclamp;
+       /* Gain, offset adjustments */
+       struct vpfe_isif_gain_offsets_adj gain_offset;
+       /* Culling */
+       struct vpfe_isif_cul culling;
+       /* horizontal offset for Gain/LSC/DFC */
+       unsigned short horz_offset;
+       /* vertical offset for Gain/LSC/DFC */
+       unsigned short vert_offset;
+};
+
+/**********************************************************************
+      IPIPE API Structures
+**********************************************************************/
+
+/* IPIPE module configurations */
+
+/* IPIPE input configuration */
+#define VPFE_IPIPE_INPUT_CONFIG                (1 << 0)
+/* LUT based Defect Pixel Correction */
+#define VPFE_IPIPE_LUTDPC              (1 << 1)
+/* On the fly (OTF) Defect Pixel Correction */
+#define VPFE_IPIPE_OTFDPC              (1 << 2)
+/* Noise Filter - 1 */
+#define VPFE_IPIPE_NF1                 (1 << 3)
+/* Noise Filter - 2 */
+#define VPFE_IPIPE_NF2                 (1 << 4)
+/* White Balance.  Also a control ID */
+#define VPFE_IPIPE_WB                  (1 << 5)
+/* 1st RGB to RBG Blend module */
+#define VPFE_IPIPE_RGB2RGB_1           (1 << 6)
+/* 2nd RGB to RBG Blend module */
+#define VPFE_IPIPE_RGB2RGB_2           (1 << 7)
+/* Gamma Correction */
+#define VPFE_IPIPE_GAMMA               (1 << 8)
+/* 3D LUT color conversion */
+#define VPFE_IPIPE_3D_LUT              (1 << 9)
+/* RGB to YCbCr module */
+#define VPFE_IPIPE_RGB2YUV             (1 << 10)
+/* YUV 422 conversion module */
+#define VPFE_IPIPE_YUV422_CONV         (1 << 11)
+/* Edge Enhancement */
+#define VPFE_IPIPE_YEE                 (1 << 12)
+/* Green Imbalance Correction */
+#define VPFE_IPIPE_GIC                 (1 << 13)
+/* CFA Interpolation */
+#define VPFE_IPIPE_CFA                 (1 << 14)
+/* Chroma Artifact Reduction */
+#define VPFE_IPIPE_CAR                 (1 << 15)
+/* Chroma Gain Suppression */
+#define VPFE_IPIPE_CGS                 (1 << 16)
+/* Global brightness and contrast control */
+#define VPFE_IPIPE_GBCE                        (1 << 17)
+
+#define VPFE_IPIPE_MAX_MODULES         18
+
+struct ipipe_float_u16 {
+       unsigned short integer;
+       unsigned short decimal;
+};
+
+struct ipipe_float_s16 {
+       short integer;
+       unsigned short decimal;
+};
+
+struct ipipe_float_u8 {
+       unsigned char integer;
+       unsigned char decimal;
+};
+
+/* Copy method selection for vertical correction
+ *  Used when ipipe_dfc_corr_meth is IPIPE_DPC_CTORB_AFTER_HINT
+ */
+enum vpfe_ipipe_dpc_corr_meth {
+       /* replace by black or white dot specified by repl_white */
+       VPFE_IPIPE_DPC_REPL_BY_DOT = 0,
+       /* Copy from left */
+       VPFE_IPIPE_DPC_CL = 1,
+       /* Copy from right */
+       VPFE_IPIPE_DPC_CR = 2,
+       /* Horizontal interpolation */
+       VPFE_IPIPE_DPC_H_INTP = 3,
+       /* Vertical interpolation */
+       VPFE_IPIPE_DPC_V_INTP = 4,
+       /* Copy from top  */
+       VPFE_IPIPE_DPC_CT = 5,
+       /* Copy from bottom */
+       VPFE_IPIPE_DPC_CB = 6,
+       /* 2D interpolation */
+       VPFE_IPIPE_DPC_2D_INTP = 7,
+};
+
+struct vpfe_ipipe_lutdpc_entry {
+       /* Horizontal position */
+       unsigned short horz_pos;
+       /* vertical position */
+       unsigned short vert_pos;
+       enum vpfe_ipipe_dpc_corr_meth method;
+};
+
+#define VPFE_IPIPE_MAX_SIZE_DPC 256
+
+/* Structure for configuring DPC module */
+struct vpfe_ipipe_lutdpc {
+       /* 0 - disable, 1 - enable */
+       unsigned char en;
+       /* 0 - replace with black dot, 1 - white dot when correction
+        * method is  IPIPE_DFC_REPL_BY_DOT=0,
+        */
+       unsigned char repl_white;
+       /* number of entries in the correction table. Currently only
+        * support up-to 256 entries. infinite mode is not supported
+        */
+       unsigned short dpc_size;
+       struct vpfe_ipipe_lutdpc_entry table[VPFE_IPIPE_MAX_SIZE_DPC];
+};
+
+enum vpfe_ipipe_otfdpc_det_meth {
+       VPFE_IPIPE_DPC_OTF_MIN_MAX,
+       VPFE_IPIPE_DPC_OTF_MIN_MAX2
+};
+
+struct vpfe_ipipe_otfdpc_thr {
+       unsigned short r;
+       unsigned short gr;
+       unsigned short gb;
+       unsigned short b;
+};
+
+enum vpfe_ipipe_otfdpc_alg {
+       VPFE_IPIPE_OTFDPC_2_0,
+       VPFE_IPIPE_OTFDPC_3_0
+};
+
+struct vpfe_ipipe_otfdpc_2_0_cfg {
+       /* defect detection threshold for MIN_MAX2 method  (DPC 2.0 alg) */
+       struct vpfe_ipipe_otfdpc_thr det_thr;
+       /* defect correction threshold for MIN_MAX2 method (DPC 2.0 alg) or
+        * maximum value for MIN_MAX method
+        */
+       struct vpfe_ipipe_otfdpc_thr corr_thr;
+};
+
+struct vpfe_ipipe_otfdpc_3_0_cfg {
+       /* DPC3.0 activity adj shf. activity = (max2-min2) >> (6 -shf)
+        */
+       unsigned char act_adj_shf;
+       /* DPC3.0 detection threshold, THR */
+       unsigned short det_thr;
+       /* DPC3.0 detection threshold slope, SLP */
+       unsigned short det_slp;
+       /* DPC3.0 detection threshold min, MIN */
+       unsigned short det_thr_min;
+       /* DPC3.0 detection threshold max, MAX */
+       unsigned short det_thr_max;
+       /* DPC3.0 correction threshold, THR */
+       unsigned short corr_thr;
+       /* DPC3.0 correction threshold slope, SLP */
+       unsigned short corr_slp;
+       /* DPC3.0 correction threshold min, MIN */
+       unsigned short corr_thr_min;
+       /* DPC3.0 correction threshold max, MAX */
+       unsigned short corr_thr_max;
+};
+
+struct vpfe_ipipe_otfdpc {
+       /* 0 - disable, 1 - enable */
+       unsigned char en;
+       /* defect detection method */
+       enum vpfe_ipipe_otfdpc_det_meth det_method;
+       /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
+        * used
+        */
+       enum vpfe_ipipe_otfdpc_alg alg;
+       union {
+               /* if alg is IPIPE_OTFDPC_2_0 */
+               struct vpfe_ipipe_otfdpc_2_0_cfg dpc_2_0;
+               /* if alg is IPIPE_OTFDPC_3_0 */
+               struct vpfe_ipipe_otfdpc_3_0_cfg dpc_3_0;
+       } alg_cfg;
+};
+
+/* Threshold values table size */
+#define VPFE_IPIPE_NF_THR_TABLE_SIZE           8
+/* Intensity values table size */
+#define VPFE_IPIPE_NF_STR_TABLE_SIZE           8
+
+/* NF, sampling method for green pixels */
+enum vpfe_ipipe_nf_sampl_meth {
+       /* Same as R or B */
+       VPFE_IPIPE_NF_BOX,
+       /* Diamond mode */
+       VPFE_IPIPE_NF_DIAMOND
+};
+
+/* Structure for configuring NF module */
+struct vpfe_ipipe_nf {
+       /* 0 - disable, 1 - enable */
+       unsigned char en;
+       /* Sampling method for green pixels */
+       enum vpfe_ipipe_nf_sampl_meth gr_sample_meth;
+       /* Down shift value in LUT reference address
+        */
+       unsigned char shft_val;
+       /* Spread value in NF algorithm
+        */
+       unsigned char spread_val;
+       /* Apply LSC gain to threshold. Enable this only if
+        * LSC is enabled in ISIF
+        */
+       unsigned char apply_lsc_gain;
+       /* Threshold values table */
+       unsigned short thr[VPFE_IPIPE_NF_THR_TABLE_SIZE];
+       /* intensity values table */
+       unsigned char str[VPFE_IPIPE_NF_STR_TABLE_SIZE];
+       /* Edge detection minimum threshold */
+       unsigned short edge_det_min_thr;
+       /* Edge detection maximum threshold */
+       unsigned short edge_det_max_thr;
+};
+
+enum vpfe_ipipe_gic_alg {
+       VPFE_IPIPE_GIC_ALG_CONST_GAIN,
+       VPFE_IPIPE_GIC_ALG_ADAPT_GAIN
+};
+
+enum vpfe_ipipe_gic_thr_sel {
+       VPFE_IPIPE_GIC_THR_REG,
+       VPFE_IPIPE_GIC_THR_NF
+};
+
+enum vpfe_ipipe_gic_wt_fn_type {
+       /* Use difference as index */
+       VPFE_IPIPE_GIC_WT_FN_TYP_DIF,
+       /* Use weight function as index */
+       VPFE_IPIPE_GIC_WT_FN_TYP_HP_VAL
+};
+
+/* structure for Green Imbalance Correction */
+struct vpfe_ipipe_gic {
+       /* 0 - disable, 1 - enable */
+       unsigned char en;
+       /* 0 - Constant gain , 1 - Adaptive gain algorithm */
+       enum vpfe_ipipe_gic_alg gic_alg;
+       /* GIC gain or weight. Used for Constant gain and Adaptive algorithms
+        */
+       unsigned short gain;
+       /* Threshold selection. GIC register values or NF2 thr table */
+       enum vpfe_ipipe_gic_thr_sel thr_sel;
+       /* thr1. Used when thr_sel is  IPIPE_GIC_THR_REG */
+       unsigned short thr;
+       /* this value is used for thr2-thr1, thr3-thr2 or
+        * thr4-thr3 when wt_fn_type is index. Otherwise it
+        * is the
+        */
+       unsigned short slope;
+       /* Apply LSC gain to threshold. Enable this only if
+        * LSC is enabled in ISIF & thr_sel is IPIPE_GIC_THR_REG
+        */
+       unsigned char apply_lsc_gain;
+       /* Multiply Nf2 threshold by this gain. Use this when thr_sel
+        * is IPIPE_GIC_THR_NF
+        */
+       struct ipipe_float_u8 nf2_thr_gain;
+       /* Weight function uses difference as index or high pass value.
+        * Used for adaptive gain algorithm
+        */
+       enum vpfe_ipipe_gic_wt_fn_type wt_fn_type;
+};
+
+/* Structure for configuring WB module */
+struct vpfe_ipipe_wb {
+       /* Offset (S12) for R */
+       short ofst_r;
+       /* Offset (S12) for Gr */
+       short ofst_gr;
+       /* Offset (S12) for Gb */
+       short ofst_gb;
+       /* Offset (S12) for B */
+       short ofst_b;
+       /* Gain (U13Q9) for Red */
+       struct ipipe_float_u16 gain_r;
+       /* Gain (U13Q9) for Gr */
+       struct ipipe_float_u16 gain_gr;
+       /* Gain (U13Q9) for Gb */
+       struct ipipe_float_u16 gain_gb;
+       /* Gain (U13Q9) for Blue */
+       struct ipipe_float_u16 gain_b;
+};
+
+enum vpfe_ipipe_cfa_alg {
+       /* Algorithm is 2DirAC */
+       VPFE_IPIPE_CFA_ALG_2DIRAC,
+       /* Algorithm is 2DirAC + Digital Antialiasing (DAA) */
+       VPFE_IPIPE_CFA_ALG_2DIRAC_DAA,
+       /* Algorithm is DAA */
+       VPFE_IPIPE_CFA_ALG_DAA
+};
+
+/* Structure for CFA Interpolation */
+struct vpfe_ipipe_cfa {
+       /* 2DirAC or 2DirAC + DAA */
+       enum vpfe_ipipe_cfa_alg alg;
+       /* 2Dir CFA HP value Low Threshold */
+       unsigned short hpf_thr_2dir;
+       /* 2Dir CFA HP value slope */
+       unsigned short hpf_slp_2dir;
+       /* 2Dir CFA HP mix threshold */
+       unsigned short hp_mix_thr_2dir;
+       /* 2Dir CFA HP mix slope */
+       unsigned short hp_mix_slope_2dir;
+       /* 2Dir Direction threshold */
+       unsigned short dir_thr_2dir;
+       /* 2Dir Direction slope */
+       unsigned short dir_slope_2dir;
+       /* 2Dir Non Directional Weight */
+       unsigned short nd_wt_2dir;
+       /* DAA Mono Hue Fraction */
+       unsigned short hue_fract_daa;
+       /* DAA Mono Edge threshold */
+       unsigned short edge_thr_daa;
+       /* DAA Mono threshold minimum */
+       unsigned short thr_min_daa;
+       /* DAA Mono threshold slope */
+       unsigned short thr_slope_daa;
+       /* DAA Mono slope minimum */
+       unsigned short slope_min_daa;
+       /* DAA Mono slope slope */
+       unsigned short slope_slope_daa;
+       /* DAA Mono LP wight */
+       unsigned short lp_wt_daa;
+};
+
+/* Struct for configuring RGB2RGB blending module */
+struct vpfe_ipipe_rgb2rgb {
+       /* Matrix coefficient for RR S12Q8 for ID = 1 and S11Q8 for ID = 2 */
+       struct ipipe_float_s16 coef_rr;
+       /* Matrix coefficient for GR S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_gr;
+       /* Matrix coefficient for BR S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_br;
+       /* Matrix coefficient for RG S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_rg;
+       /* Matrix coefficient for GG S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_gg;
+       /* Matrix coefficient for BG S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_bg;
+       /* Matrix coefficient for RB S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_rb;
+       /* Matrix coefficient for GB S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_gb;
+       /* Matrix coefficient for BB S12Q8/S11Q8 */
+       struct ipipe_float_s16 coef_bb;
+       /* Output offset for R S13/S11 */
+       int out_ofst_r;
+       /* Output offset for G S13/S11 */
+       int out_ofst_g;
+       /* Output offset for B S13/S11 */
+       int out_ofst_b;
+};
+
+#define VPFE_IPIPE_MAX_SIZE_GAMMA              512
+
+enum vpfe_ipipe_gamma_tbl_size {
+       VPFE_IPIPE_GAMMA_TBL_SZ_64 = 64,
+       VPFE_IPIPE_GAMMA_TBL_SZ_128 = 128,
+       VPFE_IPIPE_GAMMA_TBL_SZ_256 = 256,
+       VPFE_IPIPE_GAMMA_TBL_SZ_512 = 512,
+};
+
+enum vpfe_ipipe_gamma_tbl_sel {
+       VPFE_IPIPE_GAMMA_TBL_RAM = 0,
+       VPFE_IPIPE_GAMMA_TBL_ROM = 1,
+};
+
+struct vpfe_ipipe_gamma_entry {
+       /* 10 bit slope */
+       short slope;
+       /* 10 bit offset */
+       unsigned short offset;
+};
+
+/* Structure for configuring Gamma correction module */
+struct vpfe_ipipe_gamma {
+       /* 0 - Enable Gamma correction for Red
+        * 1 - bypass Gamma correction. Data is divided by 16
+        */
+       unsigned char bypass_r;
+       /* 0 - Enable Gamma correction for Blue
+        * 1 - bypass Gamma correction. Data is divided by 16
+        */
+       unsigned char bypass_b;
+       /* 0 - Enable Gamma correction for Green
+        * 1 - bypass Gamma correction. Data is divided by 16
+        */
+       unsigned char bypass_g;
+       /* IPIPE_GAMMA_TBL_RAM or IPIPE_GAMMA_TBL_ROM */
+       enum vpfe_ipipe_gamma_tbl_sel tbl_sel;
+       /* Table size for RAM gamma table.
+        */
+       enum vpfe_ipipe_gamma_tbl_size tbl_size;
+       /* R table */
+       struct vpfe_ipipe_gamma_entry table_r[VPFE_IPIPE_MAX_SIZE_GAMMA];
+       /* Blue table */
+       struct vpfe_ipipe_gamma_entry table_b[VPFE_IPIPE_MAX_SIZE_GAMMA];
+       /* Green table */
+       struct vpfe_ipipe_gamma_entry table_g[VPFE_IPIPE_MAX_SIZE_GAMMA];
+};
+
+#define VPFE_IPIPE_MAX_SIZE_3D_LUT             729
+
+struct vpfe_ipipe_3d_lut_entry {
+       /* 10 bit entry for red */
+       unsigned short r;
+       /* 10 bit entry for green */
+       unsigned short g;
+       /* 10 bit entry for blue */
+       unsigned short b;
+};
+
+/* structure for 3D-LUT */
+struct vpfe_ipipe_3d_lut {
+       /* enable/disable 3D lut */
+       unsigned char en;
+       /* 3D - LUT table entry */
+       struct vpfe_ipipe_3d_lut_entry table[VPFE_IPIPE_MAX_SIZE_3D_LUT];
+};
+
+/* Struct for configuring rgb2ycbcr module */
+struct vpfe_ipipe_rgb2yuv {
+       /* Matrix coefficient for RY S12Q8 */
+       struct ipipe_float_s16 coef_ry;
+       /* Matrix coefficient for GY S12Q8 */
+       struct ipipe_float_s16 coef_gy;
+       /* Matrix coefficient for BY S12Q8 */
+       struct ipipe_float_s16 coef_by;
+       /* Matrix coefficient for RCb S12Q8 */
+       struct ipipe_float_s16 coef_rcb;
+       /* Matrix coefficient for GCb S12Q8 */
+       struct ipipe_float_s16 coef_gcb;
+       /* Matrix coefficient for BCb S12Q8 */
+       struct ipipe_float_s16 coef_bcb;
+       /* Matrix coefficient for RCr S12Q8 */
+       struct ipipe_float_s16 coef_rcr;
+       /* Matrix coefficient for GCr S12Q8 */
+       struct ipipe_float_s16 coef_gcr;
+       /* Matrix coefficient for BCr S12Q8 */
+       struct ipipe_float_s16 coef_bcr;
+       /* Output offset for R S11 */
+       int out_ofst_y;
+       /* Output offset for Cb S11 */
+       int out_ofst_cb;
+       /* Output offset for Cr S11 */
+       int out_ofst_cr;
+};
+
+enum vpfe_ipipe_gbce_type {
+       VPFE_IPIPE_GBCE_Y_VAL_TBL = 0,
+       VPFE_IPIPE_GBCE_GAIN_TBL = 1,
+};
+
+#define VPFE_IPIPE_MAX_SIZE_GBCE_LUT           1024
+
+/* structure for Global brightness and Contrast */
+struct vpfe_ipipe_gbce {
+       /* enable/disable GBCE */
+       unsigned char en;
+       /* Y - value table or Gain table */
+       enum vpfe_ipipe_gbce_type type;
+       /* ptr to LUT for GBCE with 1024 entries */
+       unsigned short table[VPFE_IPIPE_MAX_SIZE_GBCE_LUT];
+};
+
+/* Chrominance position. Applicable only for YCbCr input
+ * Applied after edge enhancement
+ */
+enum vpfe_chr_pos {
+       /* Co-siting, same position with luminance */
+       VPFE_IPIPE_YUV422_CHR_POS_COSITE = 0,
+       /* Centering, In the middle of luminance */
+       VPFE_IPIPE_YUV422_CHR_POS_CENTRE = 1,
+};
+
+/* Structure for configuring yuv422 conversion module */
+struct vpfe_ipipe_yuv422_conv {
+       /* Max Chrominance value */
+       unsigned char en_chrom_lpf;
+       /* 1 - enable LPF for chrminance, 0 - disable */
+       enum vpfe_chr_pos chrom_pos;
+};
+
+#define VPFE_IPIPE_MAX_SIZE_YEE_LUT            1024
+
+enum vpfe_ipipe_yee_merge_meth {
+       VPFE_IPIPE_YEE_ABS_MAX = 0,
+       VPFE_IPIPE_YEE_EE_ES = 1,
+};
+
+/* Structure for configuring YUV Edge Enhancement module */
+struct vpfe_ipipe_yee {
+       /* 1 - enable enhancement, 0 - disable */
+       unsigned char en;
+       /* enable/disable halo reduction in edge sharpner */
+       unsigned char en_halo_red;
+       /* Merge method between Edge Enhancer and Edge sharpner */
+       enum vpfe_ipipe_yee_merge_meth merge_meth;
+       /* HPF Shift length */
+       unsigned char hpf_shft;
+       /* HPF Coefficient 00, S10 */
+       short hpf_coef_00;
+       /* HPF Coefficient 01, S10 */
+       short hpf_coef_01;
+       /* HPF Coefficient 02, S10 */
+       short hpf_coef_02;
+       /* HPF Coefficient 10, S10 */
+       short hpf_coef_10;
+       /* HPF Coefficient 11, S10 */
+       short hpf_coef_11;
+       /* HPF Coefficient 12, S10 */
+       short hpf_coef_12;
+       /* HPF Coefficient 20, S10 */
+       short hpf_coef_20;
+       /* HPF Coefficient 21, S10 */
+       short hpf_coef_21;
+       /* HPF Coefficient 22, S10 */
+       short hpf_coef_22;
+       /* Lower threshold before referring to LUT */
+       unsigned short yee_thr;
+       /* Edge sharpener Gain */
+       unsigned short es_gain;
+       /* Edge sharpener lower threshold */
+       unsigned short es_thr1;
+       /* Edge sharpener upper threshold */
+       unsigned short es_thr2;
+       /* Edge sharpener gain on gradient */
+       unsigned short es_gain_grad;
+       /* Edge sharpener offset on gradient */
+       unsigned short es_ofst_grad;
+       /* Ptr to EE table. Must have 1024 entries */
+       short table[VPFE_IPIPE_MAX_SIZE_YEE_LUT];
+};
+
+enum vpfe_ipipe_car_meth {
+       /* Chromatic Gain Control */
+       VPFE_IPIPE_CAR_CHR_GAIN_CTRL = 0,
+       /* Dynamic switching between CHR_GAIN_CTRL
+        * and MED_FLTR
+        */
+       VPFE_IPIPE_CAR_DYN_SWITCH = 1,
+       /* Median Filter */
+       VPFE_IPIPE_CAR_MED_FLTR = 2,
+};
+
+enum vpfe_ipipe_car_hpf_type {
+       VPFE_IPIPE_CAR_HPF_Y = 0,
+       VPFE_IPIPE_CAR_HPF_H = 1,
+       VPFE_IPIPE_CAR_HPF_V = 2,
+       VPFE_IPIPE_CAR_HPF_2D = 3,
+       /* 2D HPF from YUV Edge Enhancement */
+       VPFE_IPIPE_CAR_HPF_2D_YEE = 4,
+};
+
+struct vpfe_ipipe_car_gain {
+       /* csup_gain */
+       unsigned char gain;
+       /* csup_shf. */
+       unsigned char shft;
+       /* gain minimum */
+       unsigned short gain_min;
+};
+
+/* Structure for Chromatic Artifact Reduction */
+struct vpfe_ipipe_car {
+       /* enable/disable */
+       unsigned char en;
+       /* Gain control or Dynamic switching */
+       enum vpfe_ipipe_car_meth meth;
+       /* Gain1 function configuration for Gain control */
+       struct vpfe_ipipe_car_gain gain1;
+       /* Gain2 function configuration for Gain control */
+       struct vpfe_ipipe_car_gain gain2;
+       /* HPF type used for CAR */
+       enum vpfe_ipipe_car_hpf_type hpf;
+       /* csup_thr: HPF threshold for Gain control */
+       unsigned char hpf_thr;
+       /* Down shift value for hpf. 2 bits */
+       unsigned char hpf_shft;
+       /* switch limit for median filter */
+       unsigned char sw0;
+       /* switch coefficient for Gain control */
+       unsigned char sw1;
+};
+
+/* structure for Chromatic Gain Suppression */
+struct vpfe_ipipe_cgs {
+       /* enable/disable */
+       unsigned char en;
+       /* gain1 bright side threshold */
+       unsigned char h_thr;
+       /* gain1 bright side slope */
+       unsigned char h_slope;
+       /* gain1 down shift value for bright side */
+       unsigned char h_shft;
+       /* gain1 bright side minimum gain */
+       unsigned char h_min;
+};
+
+/* Max pixels allowed in the input. If above this either decimation
+ * or frame division mode to be enabled
+ */
+#define VPFE_IPIPE_MAX_INPUT_WIDTH     2600
+
+struct vpfe_ipipe_input_config {
+       unsigned int vst;
+       unsigned int hst;
+};
+
+/**
+ * struct vpfe_ipipe_config - IPIPE engine configuration (user)
+ * @input_config: Pointer to structure for ipipe configuration.
+ * @flag: Specifies which ISP IPIPE functions should be enabled.
+ * @lutdpc: Pointer to luma enhancement structure.
+ * @otfdpc: Pointer to structure for defect correction.
+ * @nf1: Pointer to structure for Noise Filter.
+ * @nf2: Pointer to structure for Noise Filter.
+ * @gic: Pointer to structure for Green Imbalance.
+ * @wbal: Pointer to structure for White Balance.
+ * @cfa: Pointer to structure containing the CFA interpolation.
+ * @rgb2rgb1: Pointer to structure for RGB to RGB Blending.
+ * @rgb2rgb2: Pointer to structure for RGB to RGB Blending.
+ * @gamma: Pointer to gamma structure.
+ * @lut: Pointer to structure for 3D LUT.
+ * @rgb2yuv: Pointer to structure for RGB-YCbCr conversion.
+ * @gbce: Pointer to structure for Global Brightness,Contrast Control.
+ * @yuv422_conv: Pointer to structure for YUV 422 conversion.
+ * @yee: Pointer to structure for Edge Enhancer.
+ * @car: Pointer to structure for Chromatic Artifact Reduction.
+ * @cgs: Pointer to structure for Chromatic Gain Suppression.
+ */
+struct vpfe_ipipe_config {
+       __u32 flag;
+       struct vpfe_ipipe_input_config __user *input_config;
+       struct vpfe_ipipe_lutdpc __user *lutdpc;
+       struct vpfe_ipipe_otfdpc __user *otfdpc;
+       struct vpfe_ipipe_nf __user *nf1;
+       struct vpfe_ipipe_nf __user *nf2;
+       struct vpfe_ipipe_gic __user *gic;
+       struct vpfe_ipipe_wb __user *wbal;
+       struct vpfe_ipipe_cfa __user *cfa;
+       struct vpfe_ipipe_rgb2rgb __user *rgb2rgb1;
+       struct vpfe_ipipe_rgb2rgb __user *rgb2rgb2;
+       struct vpfe_ipipe_gamma __user *gamma;
+       struct vpfe_ipipe_3d_lut __user *lut;
+       struct vpfe_ipipe_rgb2yuv __user *rgb2yuv;
+       struct vpfe_ipipe_gbce __user *gbce;
+       struct vpfe_ipipe_yuv422_conv __user *yuv422_conv;
+       struct vpfe_ipipe_yee __user *yee;
+       struct vpfe_ipipe_car __user *car;
+       struct vpfe_ipipe_cgs __user *cgs;
+};
+
+/*******************************************************************
+**  Resizer API structures
+*******************************************************************/
+/* Interpolation types used for horizontal rescale */
+enum vpfe_rsz_intp_t {
+       VPFE_RSZ_INTP_CUBIC,
+       VPFE_RSZ_INTP_LINEAR
+};
+
+/* Horizontal LPF intensity selection */
+enum vpfe_rsz_h_lpf_lse_t {
+       VPFE_RSZ_H_LPF_LSE_INTERN,
+       VPFE_RSZ_H_LPF_LSE_USER_VAL
+};
+
+enum vpfe_rsz_down_scale_ave_sz {
+       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+       VPFE_IPIPE_DWN_SCALE_1_OVER_4,
+       VPFE_IPIPE_DWN_SCALE_1_OVER_8,
+       VPFE_IPIPE_DWN_SCALE_1_OVER_16,
+       VPFE_IPIPE_DWN_SCALE_1_OVER_32,
+       VPFE_IPIPE_DWN_SCALE_1_OVER_64,
+       VPFE_IPIPE_DWN_SCALE_1_OVER_128,
+       VPFE_IPIPE_DWN_SCALE_1_OVER_256
+};
+
+struct vpfe_rsz_output_spec {
+       /* enable horizontal flip */
+       unsigned char h_flip;
+       /* enable vertical flip */
+       unsigned char v_flip;
+       /* line start offset for y. */
+       unsigned int vst_y;
+       /* line start offset for c. Only for 420 */
+       unsigned int vst_c;
+       /* vertical rescale interpolation type, YCbCr or Luminance */
+       enum vpfe_rsz_intp_t v_typ_y;
+       /* vertical rescale interpolation type for Chrominance */
+       enum vpfe_rsz_intp_t v_typ_c;
+       /* vertical lpf intensity - Luminance */
+       unsigned char v_lpf_int_y;
+       /* vertical lpf intensity - Chrominance */
+       unsigned char v_lpf_int_c;
+       /* horizontal rescale interpolation types, YCbCr or Luminance  */
+       enum vpfe_rsz_intp_t h_typ_y;
+       /* horizontal rescale interpolation types, Chrominance */
+       enum vpfe_rsz_intp_t h_typ_c;
+       /* horizontal lpf intensity - Luminance */
+       unsigned char h_lpf_int_y;
+       /* horizontal lpf intensity - Chrominance */
+       unsigned char h_lpf_int_c;
+       /* Use down scale mode for scale down */
+       unsigned char en_down_scale;
+       /* if downscale, set the downscale more average size for horizontal
+        * direction. Used only if output width and height is less than
+        * input sizes
+        */
+       enum vpfe_rsz_down_scale_ave_sz h_dscale_ave_sz;
+       /* if downscale, set the downscale more average size for vertical
+        * direction. Used only if output width and height is less than
+        * input sizes
+        */
+       enum vpfe_rsz_down_scale_ave_sz v_dscale_ave_sz;
+       /* Y offset. If set, the offset would be added to the base address
+        */
+       unsigned int user_y_ofst;
+       /* C offset. If set, the offset would be added to the base address
+        */
+       unsigned int user_c_ofst;
+};
+
+struct vpfe_rsz_config_params {
+       unsigned int vst;
+       /* horizontal start position of the image
+        * data to IPIPE
+        */
+       unsigned int hst;
+       /* output spec of the image data coming out of resizer - 0(UYVY).
+        */
+       struct vpfe_rsz_output_spec output1;
+       /* output spec of the image data coming out of resizer - 1(UYVY).
+        */
+       struct vpfe_rsz_output_spec output2;
+       /* 0 , chroma sample at odd pixel, 1 - even pixel */
+       unsigned char chroma_sample_even;
+       unsigned char frame_div_mode_en;
+       unsigned char yuv_y_min;
+       unsigned char yuv_y_max;
+       unsigned char yuv_c_min;
+       unsigned char yuv_c_max;
+       enum vpfe_chr_pos out_chr_pos;
+       unsigned char bypass;
+};
+
+/* Structure for VIDIOC_VPFE_RSZ_[S/G]_CONFIG IOCTLs */
+struct vpfe_rsz_config {
+       struct vpfe_rsz_config_params *config;
+};
+
+#endif         /* _DAVINCI_VPFE_USER_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
new file mode 100644 (file)
index 0000000..9285353
--- /dev/null
@@ -0,0 +1,1863 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ *
+ *
+ * IPIPE allows fine tuning of the input image using different
+ * tuning modules in IPIPE. Some examples :- Noise filter, Defect
+ * pixel correction etc. It essentially operate on Bayer Raw data
+ * or YUV raw data. To do image tuning, application call,
+ *
+ */
+
+#include <linux/slab.h>
+
+#include "dm365_ipipe.h"
+#include "dm365_ipipe_hw.h"
+#include "vpfe_mc_capture.h"
+
+#define MIN_OUT_WIDTH  32
+#define MIN_OUT_HEIGHT 32
+
+/* ipipe input format's */
+static const unsigned int ipipe_input_fmts[] = {
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_SGRBG12_1X12,
+       V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+       V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
+};
+
+/* ipipe output format's */
+static const unsigned int ipipe_output_fmts[] = {
+       V4L2_MBUS_FMT_UYVY8_2X8,
+};
+
+static int ipipe_validate_lutdpc_params(struct vpfe_ipipe_lutdpc *lutdpc)
+{
+       int i;
+
+       if (lutdpc->en > 1 || lutdpc->repl_white > 1 ||
+           lutdpc->dpc_size > LUT_DPC_MAX_SIZE)
+               return -EINVAL;
+
+       if (lutdpc->en && !lutdpc->table)
+               return -EINVAL;
+
+       for (i = 0; i < lutdpc->dpc_size; i++)
+               if (lutdpc->table[i].horz_pos > LUT_DPC_H_POS_MASK ||
+                  lutdpc->table[i].vert_pos > LUT_DPC_V_POS_MASK)
+                       return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc;
+       struct vpfe_ipipe_lutdpc *dpc_param;
+       struct device *dev;
+
+       if (!param) {
+               memset((void *)lutdpc, 0, sizeof(struct vpfe_ipipe_lutdpc));
+               goto success;
+       }
+
+       dev = ipipe->subdev.v4l2_dev->dev;
+       dpc_param = (struct vpfe_ipipe_lutdpc *)param;
+       lutdpc->en = dpc_param->en;
+       lutdpc->repl_white = dpc_param->repl_white;
+       lutdpc->dpc_size = dpc_param->dpc_size;
+       memcpy(&lutdpc->table, &dpc_param->table,
+              (dpc_param->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry)));
+       if (ipipe_validate_lutdpc_params(lutdpc) < 0)
+               return -EINVAL;
+
+success:
+       ipipe_set_lutdpc_regs(ipipe->base_addr, ipipe->isp5_base_addr, lutdpc);
+
+       return 0;
+}
+
+static int ipipe_get_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_lutdpc *lut_param = (struct vpfe_ipipe_lutdpc *)param;
+       struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc;
+
+       lut_param->en = lutdpc->en;
+       lut_param->repl_white = lutdpc->repl_white;
+       lut_param->dpc_size = lutdpc->dpc_size;
+       memcpy(&lut_param->table, &lutdpc->table,
+          (lutdpc->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry)));
+
+       return 0;
+}
+
+static int ipipe_set_input_config(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
+
+       if (!param)
+               memset(config, 0, sizeof(struct vpfe_ipipe_input_config));
+       else
+               memcpy(config, param, sizeof(struct vpfe_ipipe_input_config));
+       return 0;
+}
+
+static int ipipe_get_input_config(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
+
+       if (!param)
+               return -EINVAL;
+
+       memcpy(param, config, sizeof(struct vpfe_ipipe_input_config));
+
+       return 0;
+}
+
+static int ipipe_validate_otfdpc_params(struct vpfe_ipipe_otfdpc *dpc_param)
+{
+       struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0;
+       struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0;
+
+       if (dpc_param->en > 1)
+               return -EINVAL;
+
+       if (dpc_param->alg == VPFE_IPIPE_OTFDPC_2_0) {
+               dpc_2_0 = &dpc_param->alg_cfg.dpc_2_0;
+               if (dpc_2_0->det_thr.r > OTFDPC_DPC2_THR_MASK ||
+                   dpc_2_0->det_thr.gr > OTFDPC_DPC2_THR_MASK ||
+                   dpc_2_0->det_thr.gb > OTFDPC_DPC2_THR_MASK ||
+                   dpc_2_0->det_thr.b > OTFDPC_DPC2_THR_MASK ||
+                   dpc_2_0->corr_thr.r > OTFDPC_DPC2_THR_MASK ||
+                   dpc_2_0->corr_thr.gr > OTFDPC_DPC2_THR_MASK ||
+                   dpc_2_0->corr_thr.gb > OTFDPC_DPC2_THR_MASK ||
+                   dpc_2_0->corr_thr.b > OTFDPC_DPC2_THR_MASK)
+                       return -EINVAL;
+               return 0;
+       }
+
+       dpc_3_0 = &dpc_param->alg_cfg.dpc_3_0;
+
+       if (dpc_3_0->act_adj_shf > OTF_DPC3_0_SHF_MASK ||
+           dpc_3_0->det_thr > OTF_DPC3_0_DET_MASK ||
+           dpc_3_0->det_slp > OTF_DPC3_0_SLP_MASK ||
+           dpc_3_0->det_thr_min > OTF_DPC3_0_DET_MASK ||
+           dpc_3_0->det_thr_max > OTF_DPC3_0_DET_MASK ||
+           dpc_3_0->corr_thr > OTF_DPC3_0_CORR_MASK ||
+           dpc_3_0->corr_slp > OTF_DPC3_0_SLP_MASK ||
+           dpc_3_0->corr_thr_min > OTF_DPC3_0_CORR_MASK ||
+           dpc_3_0->corr_thr_max > OTF_DPC3_0_CORR_MASK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_otfdpc *dpc_param = (struct vpfe_ipipe_otfdpc *)param;
+       struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc;
+       struct device *dev;
+
+       if (!param) {
+               memset((void *)otfdpc, 0, sizeof(struct ipipe_otfdpc_2_0));
+               goto success;
+       }
+       dev = ipipe->subdev.v4l2_dev->dev;
+       memcpy(otfdpc, dpc_param, sizeof(struct vpfe_ipipe_otfdpc));
+       if (ipipe_validate_otfdpc_params(otfdpc) < 0) {
+               dev_err(dev, "Invalid otfdpc params\n");
+               return -EINVAL;
+       }
+
+success:
+       ipipe_set_otfdpc_regs(ipipe->base_addr, otfdpc);
+
+       return 0;
+}
+
+static int ipipe_get_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_otfdpc *dpc_param = (struct vpfe_ipipe_otfdpc *)param;
+       struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc;
+
+       memcpy(dpc_param, otfdpc, sizeof(struct vpfe_ipipe_otfdpc));
+       return 0;
+}
+
+static int ipipe_validate_nf_params(struct vpfe_ipipe_nf *nf_param)
+{
+       int i;
+
+       if (nf_param->en > 1 || nf_param->shft_val > D2F_SHFT_VAL_MASK ||
+           nf_param->spread_val > D2F_SPR_VAL_MASK ||
+           nf_param->apply_lsc_gain > 1 ||
+           nf_param->edge_det_min_thr > D2F_EDGE_DET_THR_MASK ||
+           nf_param->edge_det_max_thr > D2F_EDGE_DET_THR_MASK)
+               return -EINVAL;
+
+       for (i = 0; i < VPFE_IPIPE_NF_THR_TABLE_SIZE; i++)
+               if (nf_param->thr[i] > D2F_THR_VAL_MASK)
+                       return -EINVAL;
+
+       for (i = 0; i < VPFE_IPIPE_NF_STR_TABLE_SIZE; i++)
+               if (nf_param->str[i] > D2F_STR_VAL_MASK)
+                       return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_nf_params(struct vpfe_ipipe_device *ipipe,
+                              unsigned int id, void *param)
+{
+       struct vpfe_ipipe_nf *nf_param = (struct vpfe_ipipe_nf *)param;
+       struct vpfe_ipipe_nf *nf = &ipipe->config.nf1;
+       struct device *dev;
+
+       if (id == IPIPE_D2F_2ND)
+               nf = &ipipe->config.nf2;
+
+       if (!nf_param) {
+               memset((void *)nf, 0, sizeof(struct vpfe_ipipe_nf));
+               goto success;
+       }
+
+       dev = ipipe->subdev.v4l2_dev->dev;
+       memcpy(nf, nf_param, sizeof(struct vpfe_ipipe_nf));
+       if (ipipe_validate_nf_params(nf) < 0) {
+               dev_err(dev, "Invalid nf params\n");
+               return -EINVAL;
+       }
+
+success:
+       ipipe_set_d2f_regs(ipipe->base_addr, id, nf);
+
+       return 0;
+}
+
+static int ipipe_set_nf1_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_set_nf_params(ipipe, IPIPE_D2F_1ST, param);
+}
+
+static int ipipe_set_nf2_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_set_nf_params(ipipe, IPIPE_D2F_2ND, param);
+}
+
+static int ipipe_get_nf_params(struct vpfe_ipipe_device *ipipe,
+                              unsigned int id, void *param)
+{
+       struct vpfe_ipipe_nf *nf_param = (struct vpfe_ipipe_nf *)param;
+       struct vpfe_ipipe_nf *nf = &ipipe->config.nf1;
+
+       if (id == IPIPE_D2F_2ND)
+               nf = &ipipe->config.nf2;
+
+       memcpy(nf_param, nf, sizeof(struct vpfe_ipipe_nf));
+
+       return 0;
+}
+
+static int ipipe_get_nf1_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_get_nf_params(ipipe, IPIPE_D2F_1ST, param);
+}
+
+static int ipipe_get_nf2_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_get_nf_params(ipipe, IPIPE_D2F_2ND, param);
+}
+
+static int ipipe_validate_gic_params(struct vpfe_ipipe_gic *gic)
+{
+       if (gic->en > 1 || gic->gain > GIC_GAIN_MASK ||
+           gic->thr > GIC_THR_MASK || gic->slope > GIC_SLOPE_MASK ||
+           gic->apply_lsc_gain > 1 ||
+           gic->nf2_thr_gain.integer > GIC_NFGAN_INT_MASK ||
+           gic->nf2_thr_gain.decimal > GIC_NFGAN_DECI_MASK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_gic_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_gic *gic_param = (struct vpfe_ipipe_gic *)param;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       struct vpfe_ipipe_gic *gic = &ipipe->config.gic;
+
+       if (!gic_param) {
+               memset((void *)gic, 0, sizeof(struct vpfe_ipipe_gic));
+               goto success;
+       }
+
+       memcpy(gic, gic_param, sizeof(struct vpfe_ipipe_gic));
+       if (ipipe_validate_gic_params(gic) < 0) {
+               dev_err(dev, "Invalid gic params\n");
+               return -EINVAL;
+       }
+
+success:
+       ipipe_set_gic_regs(ipipe->base_addr, gic);
+
+       return 0;
+}
+
+static int ipipe_get_gic_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_gic *gic_param = (struct vpfe_ipipe_gic *)param;
+       struct vpfe_ipipe_gic *gic = &ipipe->config.gic;
+
+       memcpy(gic_param, gic, sizeof(struct vpfe_ipipe_gic));
+
+       return 0;
+}
+
+static int ipipe_validate_wb_params(struct vpfe_ipipe_wb *wbal)
+{
+       if (wbal->ofst_r > WB_OFFSET_MASK ||
+           wbal->ofst_gr > WB_OFFSET_MASK ||
+           wbal->ofst_gb > WB_OFFSET_MASK ||
+           wbal->ofst_b > WB_OFFSET_MASK ||
+           wbal->gain_r.integer > WB_GAIN_INT_MASK ||
+           wbal->gain_r.decimal > WB_GAIN_DECI_MASK ||
+           wbal->gain_gr.integer > WB_GAIN_INT_MASK ||
+           wbal->gain_gr.decimal > WB_GAIN_DECI_MASK ||
+           wbal->gain_gb.integer > WB_GAIN_INT_MASK ||
+           wbal->gain_gb.decimal > WB_GAIN_DECI_MASK ||
+           wbal->gain_b.integer > WB_GAIN_INT_MASK ||
+           wbal->gain_b.decimal > WB_GAIN_DECI_MASK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_wb_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_wb *wb_param = (struct vpfe_ipipe_wb *)param;
+       struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal;
+
+       if (!wb_param) {
+               const struct vpfe_ipipe_wb wb_defaults = {
+                       .gain_r  = {2, 0x0},
+                       .gain_gr = {2, 0x0},
+                       .gain_gb = {2, 0x0},
+                       .gain_b  = {2, 0x0}
+               };
+               memcpy(wbal, &wb_defaults, sizeof(struct vpfe_ipipe_wb));
+               goto success;
+       }
+
+       memcpy(wbal, wb_param, sizeof(struct vpfe_ipipe_wb));
+       if (ipipe_validate_wb_params(wbal) < 0)
+               return -EINVAL;
+
+success:
+       ipipe_set_wb_regs(ipipe->base_addr, wbal);
+
+       return 0;
+}
+
+static int ipipe_get_wb_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_wb *wb_param = (struct vpfe_ipipe_wb *)param;
+       struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal;
+
+       memcpy(wb_param, wbal, sizeof(struct vpfe_ipipe_wb));
+       return 0;
+}
+
+static int ipipe_validate_cfa_params(struct vpfe_ipipe_cfa *cfa)
+{
+       if (cfa->hpf_thr_2dir > CFA_HPF_THR_2DIR_MASK ||
+           cfa->hpf_slp_2dir > CFA_HPF_SLOPE_2DIR_MASK ||
+           cfa->hp_mix_thr_2dir > CFA_HPF_MIX_THR_2DIR_MASK ||
+           cfa->hp_mix_slope_2dir > CFA_HPF_MIX_SLP_2DIR_MASK ||
+           cfa->dir_thr_2dir > CFA_DIR_THR_2DIR_MASK ||
+           cfa->dir_slope_2dir > CFA_DIR_SLP_2DIR_MASK ||
+           cfa->nd_wt_2dir > CFA_ND_WT_2DIR_MASK ||
+           cfa->hue_fract_daa > CFA_DAA_HUE_FRA_MASK ||
+           cfa->edge_thr_daa > CFA_DAA_EDG_THR_MASK ||
+           cfa->thr_min_daa > CFA_DAA_THR_MIN_MASK ||
+           cfa->thr_slope_daa > CFA_DAA_THR_SLP_MASK ||
+           cfa->slope_min_daa > CFA_DAA_SLP_MIN_MASK ||
+           cfa->slope_slope_daa > CFA_DAA_SLP_SLP_MASK ||
+           cfa->lp_wt_daa > CFA_DAA_LP_WT_MASK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_cfa_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_cfa *cfa_param = (struct vpfe_ipipe_cfa *)param;
+       struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa;
+
+       if (!cfa_param) {
+               memset(cfa, 0, sizeof(struct vpfe_ipipe_cfa));
+               cfa->alg = VPFE_IPIPE_CFA_ALG_2DIRAC;
+               goto success;
+       }
+
+       memcpy(cfa, cfa_param, sizeof(struct vpfe_ipipe_cfa));
+       if (ipipe_validate_cfa_params(cfa) < 0)
+               return -EINVAL;
+
+success:
+       ipipe_set_cfa_regs(ipipe->base_addr, cfa);
+
+       return 0;
+}
+
+static int ipipe_get_cfa_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_cfa *cfa_param = (struct vpfe_ipipe_cfa *)param;
+       struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa;
+
+       memcpy(cfa_param, cfa, sizeof(struct vpfe_ipipe_cfa));
+       return 0;
+}
+
+static int
+ipipe_validate_rgb2rgb_params(struct vpfe_ipipe_rgb2rgb *rgb2rgb,
+                             unsigned int id)
+{
+       u32 gain_int_upper = RGB2RGB_1_GAIN_INT_MASK;
+       u32 offset_upper = RGB2RGB_1_OFST_MASK;
+
+       if (id == IPIPE_RGB2RGB_2) {
+               offset_upper = RGB2RGB_2_OFST_MASK;
+               gain_int_upper = RGB2RGB_2_GAIN_INT_MASK;
+       }
+
+       if (rgb2rgb->coef_rr.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_rr.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_gr.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_gr.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_br.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_br.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_rg.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_rg.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_gg.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_gg.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_bg.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_bg.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_rb.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_rb.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_gb.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_gb.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->coef_bb.decimal > RGB2RGB_GAIN_DECI_MASK ||
+           rgb2rgb->coef_bb.integer > gain_int_upper)
+               return -EINVAL;
+
+       if (rgb2rgb->out_ofst_r > offset_upper ||
+           rgb2rgb->out_ofst_g > offset_upper ||
+           rgb2rgb->out_ofst_b > offset_upper)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_rgb2rgb_params(struct vpfe_ipipe_device *ipipe,
+                             unsigned int id, void *param)
+{
+       struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       struct vpfe_ipipe_rgb2rgb *rgb2rgb_param;
+
+       rgb2rgb_param = (struct vpfe_ipipe_rgb2rgb *)param;
+
+       if (id == IPIPE_RGB2RGB_2)
+               rgb2rgb = &ipipe->config.rgb2rgb2;
+
+       if (!rgb2rgb_param) {
+               const struct vpfe_ipipe_rgb2rgb rgb2rgb_defaults = {
+                       .coef_rr = {1, 0},      /* 256 */
+                       .coef_gr = {0, 0},
+                       .coef_br = {0, 0},
+                       .coef_rg = {0, 0},
+                       .coef_gg = {1, 0},      /* 256 */
+                       .coef_bg = {0, 0},
+                       .coef_rb = {0, 0},
+                       .coef_gb = {0, 0},
+                       .coef_bb = {1, 0},      /* 256 */
+               };
+               /* Copy defaults for rgb2rgb conversion */
+               memcpy(rgb2rgb, &rgb2rgb_defaults,
+                      sizeof(struct vpfe_ipipe_rgb2rgb));
+               goto success;
+       }
+
+       memcpy(rgb2rgb, rgb2rgb_param, sizeof(struct vpfe_ipipe_rgb2rgb));
+       if (ipipe_validate_rgb2rgb_params(rgb2rgb, id) < 0) {
+               dev_err(dev, "Invalid rgb2rgb params\n");
+               return -EINVAL;
+       }
+
+success:
+       ipipe_set_rgb2rgb_regs(ipipe->base_addr, id, rgb2rgb);
+
+       return 0;
+}
+
+static int
+ipipe_set_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param);
+}
+
+static int
+ipipe_set_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param);
+}
+
+static int ipipe_get_rgb2rgb_params(struct vpfe_ipipe_device *ipipe,
+                             unsigned int id, void *param)
+{
+       struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1;
+       struct vpfe_ipipe_rgb2rgb *rgb2rgb_param;
+
+       rgb2rgb_param = (struct vpfe_ipipe_rgb2rgb *)param;
+
+       if (id == IPIPE_RGB2RGB_2)
+               rgb2rgb = &ipipe->config.rgb2rgb2;
+
+       memcpy(rgb2rgb_param, rgb2rgb, sizeof(struct vpfe_ipipe_rgb2rgb));
+
+       return 0;
+}
+
+static int
+ipipe_get_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param);
+}
+
+static int
+ipipe_get_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param);
+}
+
+static int
+ipipe_validate_gamma_entry(struct vpfe_ipipe_gamma_entry *table, int size)
+{
+       int i;
+
+       if (!table)
+               return -EINVAL;
+
+       for (i = 0; i < size; i++)
+               if (table[i].slope > GAMMA_MASK ||
+                   table[i].offset > GAMMA_MASK)
+                       return -EINVAL;
+
+       return 0;
+}
+
+static int
+ipipe_validate_gamma_params(struct vpfe_ipipe_gamma *gamma, struct device *dev)
+{
+       int table_size;
+       int err;
+
+       if (gamma->bypass_r > 1 ||
+           gamma->bypass_b > 1 ||
+           gamma->bypass_g > 1)
+               return -EINVAL;
+
+       if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
+               return 0;
+
+       table_size = gamma->tbl_size;
+       if (!gamma->bypass_r) {
+               err = ipipe_validate_gamma_entry(gamma->table_r, table_size);
+               if (err) {
+                       dev_err(dev, "GAMMA R - table entry invalid\n");
+                       return err;
+               }
+       }
+
+       if (!gamma->bypass_b) {
+               err = ipipe_validate_gamma_entry(gamma->table_b, table_size);
+               if (err) {
+                       dev_err(dev, "GAMMA B - table entry invalid\n");
+                       return err;
+               }
+       }
+
+       if (!gamma->bypass_g) {
+               err = ipipe_validate_gamma_entry(gamma->table_g, table_size);
+               if (err) {
+                       dev_err(dev, "GAMMA G - table entry invalid\n");
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static int
+ipipe_set_gamma_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_gamma *gamma_param = (struct vpfe_ipipe_gamma *)param;
+       struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       int table_size;
+
+       if (!gamma_param) {
+               memset(gamma, 0, sizeof(struct vpfe_ipipe_gamma));
+               gamma->tbl_sel = VPFE_IPIPE_GAMMA_TBL_ROM;
+               goto success;
+       }
+
+       gamma->bypass_r = gamma_param->bypass_r;
+       gamma->bypass_b = gamma_param->bypass_b;
+       gamma->bypass_g = gamma_param->bypass_g;
+       gamma->tbl_sel = gamma_param->tbl_sel;
+       gamma->tbl_size = gamma_param->tbl_size;
+
+       if (ipipe_validate_gamma_params(gamma, dev) < 0)
+               return -EINVAL;
+
+       if (gamma_param->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
+               goto success;
+
+       table_size = gamma->tbl_size;
+       if (!gamma_param->bypass_r)
+               memcpy(&gamma->table_r, &gamma_param->table_r,
+                      (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
+
+       if (!gamma_param->bypass_b)
+               memcpy(&gamma->table_b, &gamma_param->table_b,
+                      (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
+
+       if (!gamma_param->bypass_g)
+               memcpy(&gamma->table_g, &gamma_param->table_g,
+                      (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
+
+success:
+       ipipe_set_gamma_regs(ipipe->base_addr, ipipe->isp5_base_addr, gamma);
+
+       return 0;
+}
+
+static int ipipe_get_gamma_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_gamma *gamma_param = (struct vpfe_ipipe_gamma *)param;
+       struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       int table_size;
+
+       gamma_param->bypass_r = gamma->bypass_r;
+       gamma_param->bypass_g = gamma->bypass_g;
+       gamma_param->bypass_b = gamma->bypass_b;
+       gamma_param->tbl_sel = gamma->tbl_sel;
+       gamma_param->tbl_size = gamma->tbl_size;
+
+       if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
+               return 0;
+
+       table_size = gamma->tbl_size;
+
+       if (!gamma->bypass_r && !gamma_param->table_r) {
+               dev_err(dev,
+                       "ipipe_get_gamma_params: table ptr empty for R\n");
+               return -EINVAL;
+       }
+       memcpy(gamma_param->table_r, gamma->table_r,
+              (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
+
+       if (!gamma->bypass_g && !gamma_param->table_g) {
+               dev_err(dev, "ipipe_get_gamma_params: table ptr empty for G\n");
+               return -EINVAL;
+       }
+       memcpy(gamma_param->table_g, gamma->table_g,
+              (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
+
+       if (!gamma->bypass_b && !gamma_param->table_b) {
+               dev_err(dev, "ipipe_get_gamma_params: table ptr empty for B\n");
+               return -EINVAL;
+       }
+       memcpy(gamma_param->table_b, gamma->table_b,
+              (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
+
+       return 0;
+}
+
+static int ipipe_validate_3d_lut_params(struct vpfe_ipipe_3d_lut *lut)
+{
+       int i;
+
+       if (!lut->en)
+               return 0;
+
+       for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++)
+               if (lut->table[i].r > D3_LUT_ENTRY_MASK ||
+                   lut->table[i].g > D3_LUT_ENTRY_MASK ||
+                   lut->table[i].b > D3_LUT_ENTRY_MASK)
+                       return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_get_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_3d_lut *lut_param = (struct vpfe_ipipe_3d_lut *)param;
+       struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+
+       lut_param->en = lut->en;
+       if (!lut_param->table) {
+               dev_err(dev, "ipipe_get_3d_lut_params: Invalid table ptr\n");
+               return -EINVAL;
+       }
+
+       memcpy(lut_param->table, &lut->table,
+              (VPFE_IPIPE_MAX_SIZE_3D_LUT *
+              sizeof(struct vpfe_ipipe_3d_lut_entry)));
+
+       return 0;
+}
+
+static int
+ipipe_set_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_3d_lut *lut_param = (struct vpfe_ipipe_3d_lut *)param;
+       struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+
+       if (!lut_param) {
+               memset(lut, 0, sizeof(struct vpfe_ipipe_3d_lut));
+               goto success;
+       }
+
+       memcpy(lut, lut_param, sizeof(struct vpfe_ipipe_3d_lut));
+       if (ipipe_validate_3d_lut_params(lut) < 0) {
+               dev_err(dev, "Invalid 3D-LUT Params\n");
+               return -EINVAL;
+       }
+
+success:
+       ipipe_set_3d_lut_regs(ipipe->base_addr, ipipe->isp5_base_addr, lut);
+
+       return 0;
+}
+
+static int ipipe_validate_rgb2yuv_params(struct vpfe_ipipe_rgb2yuv *rgb2yuv)
+{
+       if (rgb2yuv->coef_ry.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_ry.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_gy.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_gy.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_by.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_by.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_rcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_rcb.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_gcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_gcb.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_bcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_bcb.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_rcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_rcr.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_gcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_gcr.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->coef_bcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+          rgb2yuv->coef_bcr.integer > RGB2YCBCR_COEF_INT_MASK)
+               return -EINVAL;
+
+       if (rgb2yuv->out_ofst_y > RGB2YCBCR_OFST_MASK ||
+          rgb2yuv->out_ofst_cb > RGB2YCBCR_OFST_MASK ||
+          rgb2yuv->out_ofst_cr > RGB2YCBCR_OFST_MASK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int
+ipipe_set_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       struct vpfe_ipipe_rgb2yuv *rgb2yuv_param;
+
+       rgb2yuv_param = (struct vpfe_ipipe_rgb2yuv *)param;
+       if (!rgb2yuv_param) {
+               /* Defaults for rgb2yuv conversion */
+               const struct vpfe_ipipe_rgb2yuv rgb2yuv_defaults = {
+                       .coef_ry  = {0, 0x4d},
+                       .coef_gy  = {0, 0x96},
+                       .coef_by  = {0, 0x1d},
+                       .coef_rcb = {0xf, 0xd5},
+                       .coef_gcb = {0xf, 0xab},
+                       .coef_bcb = {0, 0x80},
+                       .coef_rcr = {0, 0x80},
+                       .coef_gcr = {0xf, 0x95},
+                       .coef_bcr = {0xf, 0xeb},
+                       .out_ofst_cb = 0x80,
+                       .out_ofst_cr = 0x80,
+               };
+               /* Copy defaults for rgb2yuv conversion  */
+               memcpy(rgb2yuv, &rgb2yuv_defaults,
+                      sizeof(struct vpfe_ipipe_rgb2yuv));
+               goto success;
+       }
+
+       memcpy(rgb2yuv, rgb2yuv_param, sizeof(struct vpfe_ipipe_rgb2yuv));
+       if (ipipe_validate_rgb2yuv_params(rgb2yuv) < 0) {
+               dev_err(dev, "Invalid rgb2yuv params\n");
+               return -EINVAL;
+       }
+
+success:
+       ipipe_set_rgb2ycbcr_regs(ipipe->base_addr, rgb2yuv);
+
+       return 0;
+}
+
+static int
+ipipe_get_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv;
+       struct vpfe_ipipe_rgb2yuv *rgb2yuv_param;
+
+       rgb2yuv_param = (struct vpfe_ipipe_rgb2yuv *)param;
+       memcpy(rgb2yuv_param, rgb2yuv, sizeof(struct vpfe_ipipe_rgb2yuv));
+       return 0;
+}
+
+static int ipipe_validate_gbce_params(struct vpfe_ipipe_gbce *gbce)
+{
+       u32 max = GBCE_Y_VAL_MASK;
+       int i;
+
+       if (!gbce->en)
+               return 0;
+
+       if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
+               max = GBCE_GAIN_VAL_MASK;
+
+       for (i = 0; i < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; i++)
+               if (gbce->table[i] > max)
+                       return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_gbce_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_gbce *gbce_param = (struct vpfe_ipipe_gbce *)param;
+       struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+
+       if (!gbce_param) {
+               memset(gbce, 0 , sizeof(struct vpfe_ipipe_gbce));
+       } else {
+               memcpy(gbce, gbce_param, sizeof(struct vpfe_ipipe_gbce));
+               if (ipipe_validate_gbce_params(gbce) < 0) {
+                       dev_err(dev, "Invalid gbce params\n");
+                       return -EINVAL;
+               }
+       }
+
+       ipipe_set_gbce_regs(ipipe->base_addr, ipipe->isp5_base_addr, gbce);
+
+       return 0;
+}
+
+static int ipipe_get_gbce_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_gbce *gbce_param = (struct vpfe_ipipe_gbce *)param;
+       struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+
+       gbce_param->en = gbce->en;
+       gbce_param->type = gbce->type;
+       if (!gbce_param->table) {
+               dev_err(dev, "ipipe_get_gbce_params: Invalid table ptr\n");
+               return -EINVAL;
+       }
+
+       memcpy(gbce_param->table, gbce->table,
+               (VPFE_IPIPE_MAX_SIZE_GBCE_LUT * sizeof(unsigned short)));
+
+       return 0;
+}
+
+static int
+ipipe_validate_yuv422_conv_params(struct vpfe_ipipe_yuv422_conv *yuv422_conv)
+{
+       if (yuv422_conv->en_chrom_lpf > 1)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int
+ipipe_set_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv;
+       struct vpfe_ipipe_yuv422_conv *yuv422_conv_param;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+
+       yuv422_conv_param = (struct vpfe_ipipe_yuv422_conv *)param;
+       if (!yuv422_conv_param) {
+               memset(yuv422_conv, 0, sizeof(struct vpfe_ipipe_yuv422_conv));
+               yuv422_conv->chrom_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE;
+       } else {
+               memcpy(yuv422_conv, yuv422_conv_param,
+                       sizeof(struct vpfe_ipipe_yuv422_conv));
+               if (ipipe_validate_yuv422_conv_params(yuv422_conv) < 0) {
+                       dev_err(dev, "Invalid yuv422 params\n");
+                       return -EINVAL;
+               }
+       }
+
+       ipipe_set_yuv422_conv_regs(ipipe->base_addr, yuv422_conv);
+
+       return 0;
+}
+
+static int
+ipipe_get_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv;
+       struct vpfe_ipipe_yuv422_conv *yuv422_conv_param;
+
+       yuv422_conv_param = (struct vpfe_ipipe_yuv422_conv *)param;
+       memcpy(yuv422_conv_param, yuv422_conv,
+              sizeof(struct vpfe_ipipe_yuv422_conv));
+
+       return 0;
+}
+
+static int ipipe_validate_yee_params(struct vpfe_ipipe_yee *yee)
+{
+       int i;
+
+       if (yee->en > 1 ||
+           yee->en_halo_red > 1 ||
+           yee->hpf_shft > YEE_HPF_SHIFT_MASK)
+               return -EINVAL;
+
+       if (yee->hpf_coef_00 > YEE_COEF_MASK ||
+           yee->hpf_coef_01 > YEE_COEF_MASK ||
+           yee->hpf_coef_02 > YEE_COEF_MASK ||
+           yee->hpf_coef_10 > YEE_COEF_MASK ||
+           yee->hpf_coef_11 > YEE_COEF_MASK ||
+           yee->hpf_coef_12 > YEE_COEF_MASK ||
+           yee->hpf_coef_20 > YEE_COEF_MASK ||
+           yee->hpf_coef_21 > YEE_COEF_MASK ||
+           yee->hpf_coef_22 > YEE_COEF_MASK)
+               return -EINVAL;
+
+       if (yee->yee_thr > YEE_THR_MASK ||
+           yee->es_gain > YEE_ES_GAIN_MASK ||
+           yee->es_thr1 > YEE_ES_THR1_MASK ||
+           yee->es_thr2 > YEE_THR_MASK ||
+           yee->es_gain_grad > YEE_THR_MASK ||
+           yee->es_ofst_grad > YEE_THR_MASK)
+               return -EINVAL;
+
+       for (i = 0; i < VPFE_IPIPE_MAX_SIZE_YEE_LUT ; i++)
+               if (yee->table[i] > YEE_ENTRY_MASK)
+                       return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_yee_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_yee *yee_param = (struct vpfe_ipipe_yee *)param;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       struct vpfe_ipipe_yee *yee = &ipipe->config.yee;
+
+       if (!yee_param) {
+               memset(yee, 0, sizeof(struct vpfe_ipipe_yee));
+       } else {
+               memcpy(yee, yee_param, sizeof(struct vpfe_ipipe_yee));
+               if (ipipe_validate_yee_params(yee) < 0) {
+                       dev_err(dev, "Invalid yee params\n");
+                       return -EINVAL;
+               }
+       }
+
+       ipipe_set_ee_regs(ipipe->base_addr, ipipe->isp5_base_addr, yee);
+
+       return 0;
+}
+
+static int ipipe_get_yee_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_yee *yee_param = (struct vpfe_ipipe_yee *)param;
+       struct vpfe_ipipe_yee *yee = &ipipe->config.yee;
+
+       yee_param->en = yee->en;
+       yee_param->en_halo_red = yee->en_halo_red;
+       yee_param->merge_meth = yee->merge_meth;
+       yee_param->hpf_shft = yee->hpf_shft;
+       yee_param->hpf_coef_00 = yee->hpf_coef_00;
+       yee_param->hpf_coef_01 = yee->hpf_coef_01;
+       yee_param->hpf_coef_02 = yee->hpf_coef_02;
+       yee_param->hpf_coef_10 = yee->hpf_coef_10;
+       yee_param->hpf_coef_11 = yee->hpf_coef_11;
+       yee_param->hpf_coef_12 = yee->hpf_coef_12;
+       yee_param->hpf_coef_20 = yee->hpf_coef_20;
+       yee_param->hpf_coef_21 = yee->hpf_coef_21;
+       yee_param->hpf_coef_22 = yee->hpf_coef_22;
+       yee_param->yee_thr = yee->yee_thr;
+       yee_param->es_gain = yee->es_gain;
+       yee_param->es_thr1 = yee->es_thr1;
+       yee_param->es_thr2 = yee->es_thr2;
+       yee_param->es_gain_grad = yee->es_gain_grad;
+       yee_param->es_ofst_grad = yee->es_ofst_grad;
+       memcpy(yee_param->table, &yee->table,
+              (VPFE_IPIPE_MAX_SIZE_YEE_LUT * sizeof(short)));
+
+       return 0;
+}
+
+static int ipipe_validate_car_params(struct vpfe_ipipe_car *car)
+{
+       if (car->en > 1 || car->hpf_shft > CAR_HPF_SHIFT_MASK ||
+           car->gain1.shft > CAR_GAIN1_SHFT_MASK ||
+           car->gain1.gain_min > CAR_GAIN_MIN_MASK ||
+           car->gain2.shft > CAR_GAIN2_SHFT_MASK ||
+           car->gain2.gain_min > CAR_GAIN_MIN_MASK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_car_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_car *car_param = (struct vpfe_ipipe_car *)param;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       struct vpfe_ipipe_car *car = &ipipe->config.car;
+
+       if (!car_param) {
+               memset(car , 0, sizeof(struct vpfe_ipipe_car));
+       } else {
+               memcpy(car, car_param, sizeof(struct vpfe_ipipe_car));
+               if (ipipe_validate_car_params(car) < 0) {
+                       dev_err(dev, "Invalid car params\n");
+                       return -EINVAL;
+               }
+       }
+
+       ipipe_set_car_regs(ipipe->base_addr, car);
+
+       return 0;
+}
+
+static int ipipe_get_car_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_car *car_param = (struct vpfe_ipipe_car *)param;
+       struct vpfe_ipipe_car *car = &ipipe->config.car;
+
+       memcpy(car_param, car, sizeof(struct vpfe_ipipe_car));
+       return 0;
+}
+
+static int ipipe_validate_cgs_params(struct vpfe_ipipe_cgs *cgs)
+{
+       if (cgs->en > 1 || cgs->h_shft > CAR_SHIFT_MASK)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ipipe_set_cgs_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_cgs *cgs_param = (struct vpfe_ipipe_cgs *)param;
+       struct device *dev = ipipe->subdev.v4l2_dev->dev;
+       struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs;
+
+       if (!cgs_param) {
+               memset(cgs, 0, sizeof(struct vpfe_ipipe_cgs));
+       } else {
+               memcpy(cgs, cgs_param, sizeof(struct vpfe_ipipe_cgs));
+               if (ipipe_validate_cgs_params(cgs) < 0) {
+                       dev_err(dev, "Invalid cgs params\n");
+                       return -EINVAL;
+               }
+       }
+
+       ipipe_set_cgs_regs(ipipe->base_addr, cgs);
+
+       return 0;
+}
+
+static int ipipe_get_cgs_params(struct vpfe_ipipe_device *ipipe, void *param)
+{
+       struct vpfe_ipipe_cgs *cgs_param = (struct vpfe_ipipe_cgs *)param;
+       struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs;
+
+       memcpy(cgs_param, cgs, sizeof(struct vpfe_ipipe_cgs));
+
+       return 0;
+}
+
+static const struct ipipe_module_if ipipe_modules[VPFE_IPIPE_MAX_MODULES] = {
+       /* VPFE_IPIPE_INPUT_CONFIG */ {
+               offsetof(struct ipipe_module_params, input_config),
+               FIELD_SIZEOF(struct ipipe_module_params, input_config),
+               offsetof(struct vpfe_ipipe_config, input_config),
+               ipipe_set_input_config,
+               ipipe_get_input_config,
+       }, /* VPFE_IPIPE_LUTDPC */ {
+               offsetof(struct ipipe_module_params, lutdpc),
+               FIELD_SIZEOF(struct ipipe_module_params, lutdpc),
+               offsetof(struct vpfe_ipipe_config, lutdpc),
+               ipipe_set_lutdpc_params,
+               ipipe_get_lutdpc_params,
+       }, /* VPFE_IPIPE_OTFDPC */ {
+               offsetof(struct ipipe_module_params, otfdpc),
+               FIELD_SIZEOF(struct ipipe_module_params, otfdpc),
+               offsetof(struct vpfe_ipipe_config, otfdpc),
+               ipipe_set_otfdpc_params,
+               ipipe_get_otfdpc_params,
+       }, /* VPFE_IPIPE_NF1 */ {
+               offsetof(struct ipipe_module_params, nf1),
+               FIELD_SIZEOF(struct ipipe_module_params, nf1),
+               offsetof(struct vpfe_ipipe_config, nf1),
+               ipipe_set_nf1_params,
+               ipipe_get_nf1_params,
+       }, /* VPFE_IPIPE_NF2 */ {
+               offsetof(struct ipipe_module_params, nf2),
+               FIELD_SIZEOF(struct ipipe_module_params, nf2),
+               offsetof(struct vpfe_ipipe_config, nf2),
+               ipipe_set_nf2_params,
+               ipipe_get_nf2_params,
+       }, /* VPFE_IPIPE_WB */ {
+               offsetof(struct ipipe_module_params, wbal),
+               FIELD_SIZEOF(struct ipipe_module_params, wbal),
+               offsetof(struct vpfe_ipipe_config, wbal),
+               ipipe_set_wb_params,
+               ipipe_get_wb_params,
+       }, /* VPFE_IPIPE_RGB2RGB_1 */ {
+               offsetof(struct ipipe_module_params, rgb2rgb1),
+               FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb1),
+               offsetof(struct vpfe_ipipe_config, rgb2rgb1),
+               ipipe_set_rgb2rgb_1_params,
+               ipipe_get_rgb2rgb_1_params,
+       }, /* VPFE_IPIPE_RGB2RGB_2 */ {
+               offsetof(struct ipipe_module_params, rgb2rgb2),
+               FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb2),
+               offsetof(struct vpfe_ipipe_config, rgb2rgb2),
+               ipipe_set_rgb2rgb_2_params,
+               ipipe_get_rgb2rgb_2_params,
+       }, /* VPFE_IPIPE_GAMMA */ {
+               offsetof(struct ipipe_module_params, gamma),
+               FIELD_SIZEOF(struct ipipe_module_params, gamma),
+               offsetof(struct vpfe_ipipe_config, gamma),
+               ipipe_set_gamma_params,
+               ipipe_get_gamma_params,
+       }, /* VPFE_IPIPE_3D_LUT */ {
+               offsetof(struct ipipe_module_params, lut),
+               FIELD_SIZEOF(struct ipipe_module_params, lut),
+               offsetof(struct vpfe_ipipe_config, lut),
+               ipipe_set_3d_lut_params,
+               ipipe_get_3d_lut_params,
+       }, /* VPFE_IPIPE_RGB2YUV */ {
+               offsetof(struct ipipe_module_params, rgb2yuv),
+               FIELD_SIZEOF(struct ipipe_module_params, rgb2yuv),
+               offsetof(struct vpfe_ipipe_config, rgb2yuv),
+               ipipe_set_rgb2yuv_params,
+               ipipe_get_rgb2yuv_params,
+       }, /* VPFE_IPIPE_YUV422_CONV */ {
+               offsetof(struct ipipe_module_params, yuv422_conv),
+               FIELD_SIZEOF(struct ipipe_module_params, yuv422_conv),
+               offsetof(struct vpfe_ipipe_config, yuv422_conv),
+               ipipe_set_yuv422_conv_params,
+               ipipe_get_yuv422_conv_params,
+       }, /* VPFE_IPIPE_YEE */ {
+               offsetof(struct ipipe_module_params, yee),
+               FIELD_SIZEOF(struct ipipe_module_params, yee),
+               offsetof(struct vpfe_ipipe_config, yee),
+               ipipe_set_yee_params,
+               ipipe_get_yee_params,
+       }, /* VPFE_IPIPE_GIC */ {
+               offsetof(struct ipipe_module_params, gic),
+               FIELD_SIZEOF(struct ipipe_module_params, gic),
+               offsetof(struct vpfe_ipipe_config, gic),
+               ipipe_set_gic_params,
+               ipipe_get_gic_params,
+       }, /* VPFE_IPIPE_CFA */ {
+               offsetof(struct ipipe_module_params, cfa),
+               FIELD_SIZEOF(struct ipipe_module_params, cfa),
+               offsetof(struct vpfe_ipipe_config, cfa),
+               ipipe_set_cfa_params,
+               ipipe_get_cfa_params,
+       }, /* VPFE_IPIPE_CAR */ {
+               offsetof(struct ipipe_module_params, car),
+               FIELD_SIZEOF(struct ipipe_module_params, car),
+               offsetof(struct vpfe_ipipe_config, car),
+               ipipe_set_car_params,
+               ipipe_get_car_params,
+       }, /* VPFE_IPIPE_CGS */ {
+               offsetof(struct ipipe_module_params, cgs),
+               FIELD_SIZEOF(struct ipipe_module_params, cgs),
+               offsetof(struct vpfe_ipipe_config, cgs),
+               ipipe_set_cgs_params,
+               ipipe_get_cgs_params,
+       }, /* VPFE_IPIPE_GBCE */ {
+               offsetof(struct ipipe_module_params, gbce),
+               FIELD_SIZEOF(struct ipipe_module_params, gbce),
+               offsetof(struct vpfe_ipipe_config, gbce),
+               ipipe_set_gbce_params,
+               ipipe_get_gbce_params,
+       },
+};
+
+static int ipipe_s_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg)
+{
+       struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       unsigned int i;
+       int rval = 0;
+
+       for (i = 0; i < ARRAY_SIZE(ipipe_modules); i++) {
+               unsigned int bit = 1 << i;
+               if (cfg->flag & bit) {
+                       const struct ipipe_module_if *module_if =
+                                               &ipipe_modules[i];
+                       struct ipipe_module_params *params;
+                       void __user *from = *(void * __user *)
+                               ((void *)cfg + module_if->config_offset);
+                       size_t size;
+                       void *to;
+
+                       params = kmalloc(sizeof(struct ipipe_module_params),
+                                        GFP_KERNEL);
+                       to = (void *)params + module_if->param_offset;
+                       size = module_if->param_size;
+
+                       if (to && from && size) {
+                               if (copy_from_user(to, from, size)) {
+                                       rval = -EFAULT;
+                                       break;
+                               }
+                               rval = module_if->set(ipipe, to);
+                               if (rval)
+                                       goto error;
+                       } else if (to && !from && size) {
+                               rval = module_if->set(ipipe, NULL);
+                               if (rval)
+                                       goto error;
+                       }
+                       kfree(params);
+               }
+       }
+error:
+       return rval;
+}
+
+static int ipipe_g_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg)
+{
+       struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       unsigned int i;
+       int rval = 0;
+
+       for (i = 1; i < ARRAY_SIZE(ipipe_modules); i++) {
+               unsigned int bit = 1 << i;
+               if (cfg->flag & bit) {
+                       const struct ipipe_module_if *module_if =
+                                               &ipipe_modules[i];
+                       struct ipipe_module_params *params;
+                       void __user *to = *(void * __user *)
+                               ((void *)cfg + module_if->config_offset);
+                       size_t size;
+                       void *from;
+
+                       params =  kmalloc(sizeof(struct ipipe_module_params),
+                                               GFP_KERNEL);
+                       from = (void *)params + module_if->param_offset;
+                       size = module_if->param_size;
+
+                       if (to && from && size) {
+                               rval = module_if->get(ipipe, from);
+                               if (rval)
+                                       goto error;
+                               if (copy_to_user(to, from, size)) {
+                                       rval = -EFAULT;
+                                       break;
+                               }
+                       }
+                       kfree(params);
+               }
+       }
+error:
+       return rval;
+}
+
+/*
+ * ipipe_ioctl() - Handle ipipe module private ioctl's
+ * @sd: pointer to v4l2 subdev structure
+ * @cmd: configuration command
+ * @arg: configuration argument
+ */
+static long ipipe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+       int ret = 0;
+
+       switch (cmd) {
+       case VIDIOC_VPFE_IPIPE_S_CONFIG:
+               ret = ipipe_s_config(sd, arg);
+               break;
+
+       case VIDIOC_VPFE_IPIPE_G_CONFIG:
+               ret = ipipe_g_config(sd, arg);
+               break;
+
+       default:
+               ret = -ENOIOCTLCMD;
+       }
+       return ret;
+}
+
+void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en)
+{
+       struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
+       struct vpfe_ipipe_device *ipipe = &vpfe_dev->vpfe_ipipe;
+       unsigned char val;
+
+       if (ipipe->input == IPIPE_INPUT_NONE)
+               return;
+
+       /* ipipe is set to single shot */
+       if (ipipeif->input == IPIPEIF_INPUT_MEMORY && en) {
+               /* for single-shot mode, need to wait for h/w to
+                * reset many register bits
+                */
+               do {
+                       val = regr_ip(vpfe_dev->vpfe_ipipe.base_addr,
+                                     IPIPE_SRC_EN);
+               } while (val);
+       }
+       regw_ip(vpfe_dev->vpfe_ipipe.base_addr, en, IPIPE_SRC_EN);
+}
+
+/*
+ * ipipe_set_stream() - Enable/Disable streaming on the ipipe subdevice
+ * @sd: pointer to v4l2 subdev structure
+ * @enable: 1 == Enable, 0 == Disable
+ */
+static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
+
+       if (enable && ipipe->input != IPIPE_INPUT_NONE &&
+               ipipe->output != IPIPE_OUTPUT_NONE) {
+               if (config_ipipe_hw(ipipe) < 0)
+                       return -EINVAL;
+       }
+
+       vpfe_ipipe_enable(vpfe_dev, enable);
+
+       return 0;
+}
+
+/*
+ * __ipipe_get_format() - helper function for getting ipipe format
+ * @ipipe: pointer to ipipe private structure.
+ * @pad: pad number.
+ * @fh: V4L2 subdev file handle.
+ * @which: wanted subdev format.
+ *
+ */
+static struct v4l2_mbus_framefmt *
+__ipipe_get_format(struct vpfe_ipipe_device *ipipe,
+                      struct v4l2_subdev_fh *fh, unsigned int pad,
+                      enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+
+       return &ipipe->formats[pad];
+}
+
+/*
+ * ipipe_try_format() - Handle try format by pad subdev method
+ * @ipipe: VPFE ipipe device.
+ * @fh: V4L2 subdev file handle.
+ * @pad: pad num.
+ * @fmt: pointer to v4l2 format structure.
+ * @which : wanted subdev format
+ */
+static void
+ipipe_try_format(struct vpfe_ipipe_device *ipipe,
+                  struct v4l2_subdev_fh *fh, unsigned int pad,
+                  struct v4l2_mbus_framefmt *fmt,
+                  enum v4l2_subdev_format_whence which)
+{
+       unsigned int max_out_height;
+       unsigned int max_out_width;
+       unsigned int i;
+
+       max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
+       max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+
+       if (pad == IPIPE_PAD_SINK) {
+               for (i = 0; i < ARRAY_SIZE(ipipe_input_fmts); i++)
+                       if (fmt->code == ipipe_input_fmts[i])
+                               break;
+
+               /* If not found, use SBGGR10 as default */
+               if (i >= ARRAY_SIZE(ipipe_input_fmts))
+                       fmt->code = V4L2_MBUS_FMT_SGRBG12_1X12;
+       } else if (pad == IPIPE_PAD_SOURCE) {
+               for (i = 0; i < ARRAY_SIZE(ipipe_output_fmts); i++)
+                       if (fmt->code == ipipe_output_fmts[i])
+                               break;
+
+               /* If not found, use UYVY as default */
+               if (i >= ARRAY_SIZE(ipipe_output_fmts))
+                       fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
+       }
+
+       fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width);
+       fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height);
+}
+
+/*
+ * ipipe_set_format() - Handle set format by pads subdev method
+ * @sd: pointer to v4l2 subdev structure
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int
+ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                    struct v4l2_subdev_format *fmt)
+{
+       struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       ipipe_try_format(ipipe, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       if (fmt->pad == IPIPE_PAD_SINK &&
+          (ipipe->input == IPIPE_INPUT_CCDC ||
+           ipipe->input == IPIPE_INPUT_MEMORY))
+               ipipe->formats[fmt->pad] = fmt->format;
+       else if (fmt->pad == IPIPE_PAD_SOURCE &&
+               ipipe->output == IPIPE_OUTPUT_RESIZER)
+               ipipe->formats[fmt->pad] = fmt->format;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+/*
+ * ipipe_get_format() - Handle get format by pads subdev method.
+ * @sd: pointer to v4l2 subdev structure.
+ * @fh: V4L2 subdev file handle.
+ * @fmt: pointer to v4l2 subdev format structure.
+ */
+static int
+ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                    struct v4l2_subdev_format *fmt)
+{
+       struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               fmt->format = ipipe->formats[fmt->pad];
+       else
+               fmt->format = *(v4l2_subdev_get_try_format(fh, fmt->pad));
+
+       return 0;
+}
+
+/*
+ * ipipe_enum_frame_size() - enum frame sizes on pads
+ * @sd: pointer to v4l2 subdev structure.
+ * @fh: V4L2 subdev file handle.
+ * @fse: pointer to v4l2_subdev_frame_size_enum structure.
+ */
+static int
+ipipe_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                         struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       ipipe_try_format(ipipe, fh, fse->pad, &format,
+                          V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       ipipe_try_format(ipipe, fh, fse->pad, &format,
+                          V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * ipipe_enum_mbus_code() - enum mbus codes for pads
+ * @sd: pointer to v4l2 subdev structure.
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ */
+static int
+ipipe_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                    struct v4l2_subdev_mbus_code_enum *code)
+{
+       switch (code->pad) {
+       case IPIPE_PAD_SINK:
+               if (code->index >= ARRAY_SIZE(ipipe_input_fmts))
+                       return -EINVAL;
+               code->code = ipipe_input_fmts[code->index];
+               break;
+
+       case IPIPE_PAD_SOURCE:
+               if (code->index >= ARRAY_SIZE(ipipe_output_fmts))
+                       return -EINVAL;
+               code->code = ipipe_output_fmts[code->index];
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * ipipe_s_ctrl() - Handle set control subdev method
+ * @ctrl: pointer to v4l2 control structure
+ */
+static int ipipe_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vpfe_ipipe_device *ipipe =
+            container_of(ctrl->handler, struct vpfe_ipipe_device, ctrls);
+       struct ipipe_lum_adj *lum_adj = &ipipe->config.lum_adj;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               lum_adj->brightness = ctrl->val;
+               ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj);
+               break;
+
+       case V4L2_CID_CONTRAST:
+               lum_adj->contrast = ctrl->val;
+               ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * ipipe_init_formats() - Initialize formats on all pads
+ * @sd: pointer to v4l2 subdev structure.
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int
+ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_subdev_format format;
+
+       memset(&format, 0, sizeof(format));
+       format.pad = IPIPE_PAD_SINK;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+       format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
+       format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+       ipipe_set_format(sd, fh, &format);
+
+       memset(&format, 0, sizeof(format));
+       format.pad = IPIPE_PAD_SOURCE;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
+       format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
+       format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+       ipipe_set_format(sd, fh, &format);
+
+       return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops ipipe_v4l2_core_ops = {
+       .ioctl = ipipe_ioctl,
+};
+
+static const struct v4l2_ctrl_ops ipipe_ctrl_ops = {
+       .s_ctrl = ipipe_s_ctrl,
+};
+
+/* subdev file operations */
+static const struct  v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = {
+       .open = ipipe_init_formats,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = {
+       .s_stream = ipipe_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = {
+       .enum_mbus_code = ipipe_enum_mbus_code,
+       .enum_frame_size = ipipe_enum_frame_size,
+       .get_fmt = ipipe_get_format,
+       .set_fmt = ipipe_set_format,
+};
+
+/* v4l2 subdev operation */
+static const struct v4l2_subdev_ops ipipe_v4l2_ops = {
+       .core = &ipipe_v4l2_core_ops,
+       .video = &ipipe_v4l2_video_ops,
+       .pad = &ipipe_v4l2_pad_ops,
+};
+
+/*
+ * Media entity operations
+ */
+
+/*
+ * ipipe_link_setup() - Setup ipipe connections
+ * @entity: ipipe media entity
+ * @local: Pad at the local end of the link
+ * @remote: Pad at the remote end of the link
+ * @flags: Link flags
+ *
+ * return -EINVAL or zero on success
+ */
+static int
+ipipe_link_setup(struct media_entity *entity, const struct media_pad *local,
+                    const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
+       u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case IPIPE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       ipipe->input = IPIPE_INPUT_NONE;
+                       break;
+               }
+               if (ipipe->input != IPIPE_INPUT_NONE)
+                       return -EBUSY;
+               if (ipipeif_sink == IPIPEIF_INPUT_MEMORY)
+                       ipipe->input = IPIPE_INPUT_MEMORY;
+               else
+                       ipipe->input = IPIPE_INPUT_CCDC;
+               break;
+
+       case IPIPE_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* out to RESIZER */
+               if (flags & MEDIA_LNK_FL_ENABLED)
+                       ipipe->output = IPIPE_OUTPUT_RESIZER;
+               else
+                       ipipe->output = IPIPE_OUTPUT_NONE;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct media_entity_operations ipipe_media_ops = {
+       .link_setup = ipipe_link_setup,
+};
+
+/*
+ * vpfe_ipipe_unregister_entities() - ipipe unregister entity
+ * @vpfe_ipipe: pointer to ipipe subdevice structure.
+ */
+void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *vpfe_ipipe)
+{
+       /* cleanup entity */
+       media_entity_cleanup(&vpfe_ipipe->subdev.entity);
+       /* unregister subdev */
+       v4l2_device_unregister_subdev(&vpfe_ipipe->subdev);
+}
+
+/*
+ * vpfe_ipipe_register_entities() - ipipe register entity
+ * @ipipe: pointer to ipipe subdevice structure.
+ * @vdev: pointer to v4l2 device structure.
+ */
+int
+vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe,
+                                struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev */
+       ret = v4l2_device_register_subdev(vdev, &ipipe->subdev);
+       if (ret) {
+               pr_err("Failed to register ipipe as v4l2 subdevice\n");
+               return ret;
+       }
+
+       return ret;
+}
+
+#define IPIPE_CONTRAST_HIGH            0xff
+#define IPIPE_BRIGHT_HIGH              0xff
+
+/*
+ * vpfe_ipipe_init() - ipipe module initialization.
+ * @ipipe: pointer to ipipe subdevice structure.
+ * @pdev: platform device pointer.
+ */
+int
+vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, struct platform_device *pdev)
+{
+       struct media_pad *pads = &ipipe->pads[0];
+       struct v4l2_subdev *sd = &ipipe->subdev;
+       struct media_entity *me = &sd->entity;
+       static resource_size_t  res_len;
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
+       if (!res)
+               return -ENOENT;
+
+       res_len = resource_size(res);
+       res = request_mem_region(res->start, res_len, res->name);
+       if (!res)
+               return -EBUSY;
+       ipipe->base_addr = ioremap_nocache(res->start, res_len);
+       if (!ipipe->base_addr)
+               return -EBUSY;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 6);
+       if (!res)
+               return -ENOENT;
+       ipipe->isp5_base_addr = ioremap_nocache(res->start, res_len);
+       if (!ipipe->isp5_base_addr)
+               return -EBUSY;
+
+       v4l2_subdev_init(sd, &ipipe_v4l2_ops);
+       sd->internal_ops = &ipipe_v4l2_internal_ops;
+       strlcpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
+       v4l2_set_subdevdata(sd, ipipe);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[IPIPE_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+       ipipe->input = IPIPE_INPUT_NONE;
+       ipipe->output = IPIPE_OUTPUT_NONE;
+
+       me->ops = &ipipe_media_ops;
+       v4l2_ctrl_handler_init(&ipipe->ctrls, 2);
+       v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops,
+                         V4L2_CID_BRIGHTNESS, 0,
+                         IPIPE_BRIGHT_HIGH, 1, 16);
+       v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops,
+                         V4L2_CID_CONTRAST, 0,
+                         IPIPE_CONTRAST_HIGH, 1, 16);
+
+
+       v4l2_ctrl_handler_setup(&ipipe->ctrls);
+       sd->ctrl_handler = &ipipe->ctrls;
+
+       return media_entity_init(me, IPIPE_PADS_NUM, pads, 0);
+}
+
+/*
+ * vpfe_ipipe_cleanup() - ipipe subdevice cleanup.
+ * @ipipe: pointer to ipipe subdevice
+ * @dev: pointer to platform device
+ */
+void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe,
+                       struct platform_device *pdev)
+{
+       struct resource *res;
+
+       v4l2_ctrl_handler_free(&ipipe->ctrls);
+
+       iounmap(ipipe->base_addr);
+       iounmap(ipipe->isp5_base_addr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
+       if (res)
+               release_mem_region(res->start, res->end - res->start + 1);
+}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe.h
new file mode 100644 (file)
index 0000000..cf42046
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_IPIPE_H
+#define _DAVINCI_VPFE_DM365_IPIPE_H
+
+#include <linux/platform_device.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "davinci_vpfe_user.h"
+#include "vpfe_video.h"
+
+#define CEIL(a, b)     (((a) + (b-1)) / (b))
+
+enum ipipe_noise_filter {
+       IPIPE_D2F_1ST = 0,
+       IPIPE_D2F_2ND = 1,
+};
+
+/* Used for driver storage */
+struct ipipe_otfdpc_2_0 {
+       /* 0 - disable, 1 - enable */
+       unsigned char en;
+       /* defect detection method */
+       enum vpfe_ipipe_otfdpc_det_meth det_method;
+       /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
+        * used
+        */
+       enum vpfe_ipipe_otfdpc_alg alg;
+       struct vpfe_ipipe_otfdpc_2_0_cfg otfdpc_2_0;
+};
+
+struct ipipe_otfdpc_3_0 {
+       /* 0 - disable, 1 - enable */
+       unsigned char en;
+       /* defect detection method */
+       enum vpfe_ipipe_otfdpc_det_meth det_method;
+       /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
+        * used
+        */
+       enum vpfe_ipipe_otfdpc_alg alg;
+       struct vpfe_ipipe_otfdpc_3_0_cfg otfdpc_3_0;
+};
+
+/* Structure for configuring Luminance Adjustment module */
+struct ipipe_lum_adj {
+       /* Brightness adjustments */
+       unsigned char brightness;
+       /* contrast adjustments */
+       unsigned char contrast;
+};
+
+enum ipipe_rgb2rgb {
+       IPIPE_RGB2RGB_1 = 0,
+       IPIPE_RGB2RGB_2 = 1,
+};
+
+struct ipipe_module_params {
+       __u32 flag;
+       struct vpfe_ipipe_input_config input_config;
+       struct vpfe_ipipe_lutdpc lutdpc;
+       struct vpfe_ipipe_otfdpc otfdpc;
+       struct vpfe_ipipe_nf nf1;
+       struct vpfe_ipipe_nf nf2;
+       struct vpfe_ipipe_gic gic;
+       struct vpfe_ipipe_wb wbal;
+       struct vpfe_ipipe_cfa cfa;
+       struct vpfe_ipipe_rgb2rgb rgb2rgb1;
+       struct vpfe_ipipe_rgb2rgb rgb2rgb2;
+       struct vpfe_ipipe_gamma gamma;
+       struct vpfe_ipipe_3d_lut lut;
+       struct vpfe_ipipe_rgb2yuv rgb2yuv;
+       struct vpfe_ipipe_gbce gbce;
+       struct vpfe_ipipe_yuv422_conv yuv422_conv;
+       struct vpfe_ipipe_yee yee;
+       struct vpfe_ipipe_car car;
+       struct vpfe_ipipe_cgs cgs;
+       struct ipipe_lum_adj lum_adj;
+};
+
+#define IPIPE_PAD_SINK                 0
+#define IPIPE_PAD_SOURCE               1
+
+#define IPIPE_PADS_NUM                 2
+
+#define IPIPE_OUTPUT_NONE              0
+#define IPIPE_OUTPUT_RESIZER           (1 << 0)
+
+enum ipipe_input_entity {
+       IPIPE_INPUT_NONE = 0,
+       IPIPE_INPUT_MEMORY = 1,
+       IPIPE_INPUT_CCDC = 2,
+};
+
+
+struct vpfe_ipipe_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[IPIPE_PADS_NUM];
+       struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM];
+       enum ipipe_input_entity input;
+       unsigned int output;
+       struct v4l2_ctrl_handler ctrls;
+       void *__iomem base_addr;
+       void *__iomem isp5_base_addr;
+       struct ipipe_module_params config;
+};
+
+struct ipipe_module_if {
+       unsigned int param_offset;
+       unsigned int param_size;
+       unsigned int config_offset;
+       int (*set)(struct vpfe_ipipe_device *ipipe, void *param);
+       int (*get)(struct vpfe_ipipe_device *ipipe, void *param);
+};
+
+/* data paths */
+enum ipipe_data_paths {
+       IPIPE_RAW2YUV,
+       /* Bayer RAW input to YCbCr output */
+       IPIPE_RAW2RAW,
+       /* Bayer Raw to Bayer output */
+       IPIPE_RAW2BOX,
+       /* Bayer Raw to Boxcar output */
+       IPIPE_YUV2YUV
+       /* YUV Raw to YUV Raw output */
+};
+
+#define IPIPE_COLPTN_R_Ye      0x0
+#define IPIPE_COLPTN_Gr_Cy     0x1
+#define IPIPE_COLPTN_Gb_G      0x2
+#define IPIPE_COLPTN_B_Mg      0x3
+
+#define COLPAT_EE_SHIFT                0
+#define COLPAT_EO_SHIFT                2
+#define COLPAT_OE_SHIFT                4
+#define COLPAT_OO_SHIFT                6
+
+#define ipipe_sgrbg_pattern \
+       (IPIPE_COLPTN_Gr_Cy <<  COLPAT_EE_SHIFT | \
+       IPIPE_COLPTN_R_Ye  << COLPAT_EO_SHIFT | \
+       IPIPE_COLPTN_B_Mg  << COLPAT_OE_SHIFT | \
+       IPIPE_COLPTN_Gb_G  << COLPAT_OO_SHIFT)
+
+#define ipipe_srggb_pattern \
+       (IPIPE_COLPTN_R_Ye <<  COLPAT_EE_SHIFT | \
+       IPIPE_COLPTN_Gr_Cy  << COLPAT_EO_SHIFT | \
+       IPIPE_COLPTN_Gb_G  << COLPAT_OE_SHIFT | \
+       IPIPE_COLPTN_B_Mg  << COLPAT_OO_SHIFT)
+
+int vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe,
+               struct v4l2_device *v4l2_dev);
+int vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe,
+               struct platform_device *pdev);
+void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *ipipe);
+void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe,
+               struct platform_device *pdev);
+void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en);
+
+#endif         /* _DAVINCI_VPFE_DM365_IPIPE_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c
new file mode 100644 (file)
index 0000000..e027b92
--- /dev/null
@@ -0,0 +1,1048 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#include "dm365_ipipe_hw.h"
+
+#define IPIPE_MODE_CONTINUOUS          0
+#define IPIPE_MODE_SINGLE_SHOT         1
+
+static void ipipe_clock_enable(void *__iomem base_addr)
+{
+       /* enable IPIPE MMR for register write access */
+       regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR);
+
+       /* enable the clock wb,cfa,dfc,d2f,pre modules */
+       regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX);
+}
+
+static void
+rsz_set_common_params(void *__iomem rsz_base, struct resizer_params *params)
+{
+       struct rsz_common_params *rsz_common = &params->rsz_common;
+       u32 val;
+
+       /* Set mode */
+       regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE);
+
+       /* data source selection  and bypass */
+       val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) |
+             rsz_common->source;
+       regw_rsz(rsz_base, val, RSZ_SRC_FMT0);
+
+       /* src image selection */
+       val = (rsz_common->raw_flip & 1) |
+             (rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) |
+             ((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT);
+       regw_rsz(rsz_base, val, RSZ_SRC_FMT1);
+
+       regw_rsz(rsz_base, rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS);
+       regw_rsz(rsz_base, rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS);
+       regw_rsz(rsz_base, rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ);
+       regw_rsz(rsz_base, rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ);
+       regw_rsz(rsz_base, rsz_common->yuv_y_min, RSZ_YUV_Y_MIN);
+       regw_rsz(rsz_base, rsz_common->yuv_y_max, RSZ_YUV_Y_MAX);
+       regw_rsz(rsz_base, rsz_common->yuv_c_min, RSZ_YUV_C_MIN);
+       regw_rsz(rsz_base, rsz_common->yuv_c_max, RSZ_YUV_C_MAX);
+       /* chromatic position */
+       regw_rsz(rsz_base, rsz_common->out_chr_pos, RSZ_YUV_PHS);
+}
+
+static void
+rsz_set_rsz_regs(void *__iomem rsz_base, unsigned int rsz_id,
+                struct resizer_params *params)
+{
+       struct resizer_scale_param *rsc_params;
+       struct rsz_ext_mem_param *ext_mem;
+       struct resizer_rgb *rgb;
+       u32 reg_base;
+       u32 val;
+
+       rsc_params = &params->rsz_rsc_param[rsz_id];
+       rgb = &params->rsz2rgb[rsz_id];
+       ext_mem = &params->ext_mem_param[rsz_id];
+
+       if (rsz_id == RSZ_A) {
+               val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT;
+               val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT;
+               reg_base = RSZ_EN_A;
+       } else {
+               val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT;
+               val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT;
+               reg_base = RSZ_EN_B;
+       }
+       /* update flip settings */
+       regw_rsz(rsz_base, val, RSZ_SEQ);
+
+       regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE);
+
+       val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen;
+       regw_rsz(rsz_base, val, reg_base + RSZ_420);
+
+       regw_rsz(rsz_base, rsc_params->i_vps & RSZ_VPS_MASK,
+                reg_base + RSZ_I_VPS);
+       regw_rsz(rsz_base, rsc_params->i_hps & RSZ_HPS_MASK,
+                reg_base + RSZ_I_HPS);
+       regw_rsz(rsz_base, rsc_params->o_vsz & RSZ_O_VSZ_MASK,
+                reg_base + RSZ_O_VSZ);
+       regw_rsz(rsz_base, rsc_params->o_hsz & RSZ_O_HSZ_MASK,
+                reg_base + RSZ_O_HSZ);
+       regw_rsz(rsz_base, rsc_params->v_phs_y & RSZ_V_PHS_MASK,
+                reg_base + RSZ_V_PHS_Y);
+       regw_rsz(rsz_base, rsc_params->v_phs_c & RSZ_V_PHS_MASK,
+                reg_base + RSZ_V_PHS_C);
+
+       /* keep this additional adjustment to zero for now */
+       regw_rsz(rsz_base, rsc_params->v_dif & RSZ_V_DIF_MASK,
+                reg_base + RSZ_V_DIF);
+
+       val = (rsc_params->v_typ_y & 1) |
+             ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT);
+       regw_rsz(rsz_base, val, reg_base + RSZ_V_TYP);
+
+       val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) |
+             ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) <<
+             RSZ_LPF_INT_C_SHIFT);
+       regw_rsz(rsz_base, val, reg_base + RSZ_V_LPF);
+
+       regw_rsz(rsz_base, rsc_params->h_phs &
+               RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS);
+
+       regw_rsz(rsz_base, 0, reg_base + RSZ_H_PHS_ADJ);
+       regw_rsz(rsz_base, rsc_params->h_dif &
+               RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF);
+
+       val = (rsc_params->h_typ_y & 1) |
+             ((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT);
+       regw_rsz(rsz_base, val, reg_base + RSZ_H_TYP);
+
+       val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) |
+                ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) <<
+                RSZ_LPF_INT_C_SHIFT);
+       regw_rsz(rsz_base, val, reg_base + RSZ_H_LPF);
+
+       regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN);
+
+       val = (rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) |
+             ((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) <<
+             RSZ_DWN_SCALE_AV_SZ_V_SHIFT);
+       regw_rsz(rsz_base, val, reg_base + RSZ_DWN_AV);
+
+       /* setting rgb conversion parameters */
+       regw_rsz(rsz_base, rgb->rgb_en, reg_base + RSZ_RGB_EN);
+
+       val = (rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) |
+             (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) |
+             (rgb->rgb_msk1 << RSZ_RGB_MSK1_SHIFT);
+       regw_rsz(rsz_base, val, reg_base + RSZ_RGB_TYP);
+
+       regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK,
+               reg_base + RSZ_RGB_BLD);
+
+       /* setting external memory parameters */
+       regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT);
+       regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_y,
+                reg_base + RSZ_SDR_Y_PTR_S);
+       regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_e_y,
+                reg_base + RSZ_SDR_Y_PTR_E);
+       regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT);
+       regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_c,
+                reg_base + RSZ_SDR_C_PTR_S);
+       regw_rsz(rsz_base, (ext_mem->rsz_sdr_ptr_e_c >> 1),
+                reg_base + RSZ_SDR_C_PTR_E);
+}
+
+/*set the registers of either RSZ0 or RSZ1 */
+static void
+ipipe_setup_resizer(void *__iomem rsz_base, struct resizer_params *params)
+{
+       /* enable MMR gate to write to Resizer */
+       regw_rsz(rsz_base, 1, RSZ_GCK_MMR);
+
+       /* Enable resizer if it is not in bypass mode */
+       if (params->rsz_common.passthrough)
+               regw_rsz(rsz_base, 0, RSZ_GCK_SDR);
+       else
+               regw_rsz(rsz_base, 1, RSZ_GCK_SDR);
+
+       rsz_set_common_params(rsz_base, params);
+
+       regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A);
+
+       if (params->rsz_en[RSZ_A])
+               /*setting rescale parameters */
+               rsz_set_rsz_regs(rsz_base, RSZ_A, params);
+
+       regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B);
+
+       if (params->rsz_en[RSZ_B])
+               rsz_set_rsz_regs(rsz_base, RSZ_B, params);
+}
+
+static u32 ipipe_get_color_pat(enum v4l2_mbus_pixelcode pix)
+{
+       switch (pix) {
+       case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               return ipipe_sgrbg_pattern;
+
+       default:
+               return ipipe_srggb_pattern;
+       }
+}
+
+static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe)
+{
+       enum v4l2_mbus_pixelcode temp_pix_fmt;
+
+       switch (ipipe->formats[IPIPE_PAD_SINK].code) {
+       case V4L2_MBUS_FMT_SBGGR8_1X8:
+       case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               temp_pix_fmt = V4L2_MBUS_FMT_SGRBG12_1X12;
+               break;
+
+       default:
+               temp_pix_fmt = V4L2_MBUS_FMT_UYVY8_2X8;
+       }
+
+       if (temp_pix_fmt == V4L2_MBUS_FMT_SGRBG12_1X12) {
+               if (ipipe->formats[IPIPE_PAD_SOURCE].code ==
+                       V4L2_MBUS_FMT_SGRBG12_1X12)
+                       return IPIPE_RAW2RAW;
+               return IPIPE_RAW2YUV;
+       }
+
+       return IPIPE_YUV2YUV;
+}
+
+static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
+       u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
+
+       if (ipipeif_sink == IPIPEIF_INPUT_MEMORY)
+               return IPIPE_MODE_SINGLE_SHOT;
+       else if (ipipeif_sink == IPIPEIF_INPUT_ISIF)
+               return IPIPE_MODE_CONTINUOUS;
+
+       return -EINVAL;
+}
+
+int config_ipipe_hw(struct vpfe_ipipe_device *ipipe)
+{
+       struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
+       void __iomem *ipipe_base = ipipe->base_addr;
+       struct v4l2_mbus_framefmt *outformat;
+       u32 color_pat;
+       u32 ipipe_mode;
+       u32 data_path;
+
+       /* enable clock to IPIPE */
+       vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
+       ipipe_clock_enable(ipipe_base);
+
+       if (ipipe->input == IPIPE_INPUT_NONE) {
+               regw_ip(ipipe_base, 0, IPIPE_SRC_EN);
+               return 0;
+       }
+
+       ipipe_mode = get_ipipe_mode(ipipe);
+       if (ipipe < 0) {
+               pr_err("Failed to get ipipe mode");
+               return -EINVAL;
+       }
+       regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE);
+
+       data_path = ipipe_get_data_path(ipipe);
+       regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT);
+
+       regw_ip(ipipe_base, config->vst & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS);
+       regw_ip(ipipe_base, config->hst & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS);
+
+       outformat = &ipipe->formats[IPIPE_PAD_SOURCE];
+       regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK,
+               IPIPE_SRC_VSZ);
+       regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK,
+               IPIPE_SRC_HSZ);
+
+       if (data_path == IPIPE_RAW2YUV ||
+           data_path == IPIPE_RAW2RAW) {
+               color_pat =
+               ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code);
+               regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL);
+       }
+
+       return 0;
+}
+
+/*
+ * config_rsz_hw() - Performs hardware setup of resizer.
+ */
+int config_rsz_hw(struct vpfe_resizer_device *resizer,
+                 struct resizer_params *config)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       void *__iomem ipipe_base = vpfe_dev->vpfe_ipipe.base_addr;
+       void *__iomem rsz_base = vpfe_dev->vpfe_resizer.base_addr;
+
+       /* enable VPSS clock */
+       vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
+       ipipe_clock_enable(ipipe_base);
+
+       ipipe_setup_resizer(rsz_base, config);
+
+       return 0;
+}
+
+static void
+rsz_set_y_address(void *__iomem rsz_base, unsigned int address,
+                 unsigned int offset)
+{
+       u32 val;
+
+       val = address & SET_LOW_ADDR;
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_L);
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_L);
+
+       val = (address & SET_HIGH_ADDR) >> 16;
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_H);
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_H);
+}
+
+static void
+rsz_set_c_address(void *__iomem rsz_base, unsigned int address,
+                 unsigned int offset)
+{
+       u32 val;
+
+       val = address & SET_LOW_ADDR;
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_L);
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_L);
+
+       val = (address & SET_HIGH_ADDR) >> 16;
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_H);
+       regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_H);
+}
+
+/*
+ * resizer_set_outaddr() - set the address for given resize_no
+ * @rsz_base: resizer base address
+ * @params: pointer to ipipe_params structure
+ * @resize_no: 0 - Resizer-A, 1 - Resizer B
+ * @address: the address to set
+ */
+int
+resizer_set_outaddr(void *__iomem rsz_base, struct resizer_params *params,
+                   int resize_no, unsigned int address)
+{
+       struct resizer_scale_param *rsc_param;
+       struct rsz_ext_mem_param *mem_param;
+       struct rsz_common_params *rsz_common;
+       unsigned int rsz_start_add;
+       unsigned int val;
+
+       if (resize_no != RSZ_A && resize_no != RSZ_B)
+               return -EINVAL;
+
+       mem_param = &params->ext_mem_param[resize_no];
+       rsc_param = &params->rsz_rsc_param[resize_no];
+       rsz_common = &params->rsz_common;
+
+       if (resize_no == RSZ_A)
+               rsz_start_add = RSZ_EN_A;
+       else
+               rsz_start_add = RSZ_EN_B;
+
+       /* y_c = 0 for y, = 1 for c */
+       if (rsz_common->src_img_fmt == RSZ_IMG_420) {
+               if (rsz_common->y_c) {
+                       /* C channel */
+                       val = address + mem_param->flip_ofst_c;
+                       rsz_set_c_address(rsz_base, val, rsz_start_add);
+               } else {
+                       val = address + mem_param->flip_ofst_y;
+                       rsz_set_y_address(rsz_base, val, rsz_start_add);
+               }
+       } else {
+               if (rsc_param->cen && rsc_param->yen) {
+                       /* 420 */
+                       val = address + mem_param->c_offset +
+                             mem_param->flip_ofst_c +
+                             mem_param->user_y_ofst +
+                             mem_param->user_c_ofst;
+                       if (resize_no == RSZ_B)
+                               val +=
+                               params->ext_mem_param[RSZ_A].user_y_ofst +
+                               params->ext_mem_param[RSZ_A].user_c_ofst;
+                       /* set C address */
+                       rsz_set_c_address(rsz_base, val, rsz_start_add);
+               }
+               val = address + mem_param->flip_ofst_y + mem_param->user_y_ofst;
+               if (resize_no == RSZ_B)
+                       val += params->ext_mem_param[RSZ_A].user_y_ofst +
+                               params->ext_mem_param[RSZ_A].user_c_ofst;
+               /* set Y address */
+               rsz_set_y_address(rsz_base, val, rsz_start_add);
+       }
+       /* resizer must be enabled */
+       regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add);
+
+       return 0;
+}
+
+void
+ipipe_set_lutdpc_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
+                     struct vpfe_ipipe_lutdpc *dpc)
+{
+       u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1;
+       u32 lut_start_addr = DPC_TB0_START_ADDR;
+       u32 val;
+       u32 count;
+
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, dpc->en, DPC_LUT_EN);
+
+       if (dpc->en != 1)
+               return;
+
+       val = LUTDPC_TBL_256_EN | (dpc->repl_white & 1);
+       regw_ip(base_addr, val, DPC_LUT_SEL);
+       regw_ip(base_addr, LUT_DPC_START_ADDR, DPC_LUT_ADR);
+       regw_ip(base_addr, dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK);
+
+       if (dpc->table == NULL)
+               return;
+
+       for (count = 0; count < dpc->dpc_size; count++) {
+               if (count >= max_tbl_size)
+                       lut_start_addr = DPC_TB1_START_ADDR;
+               val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) |
+                     ((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) <<
+                       LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method <<
+                       LUT_DPC_CORR_METH_SHIFT);
+               w_ip_table(isp5_base_addr, val, (lut_start_addr +
+               ((count % max_tbl_size) << 2)));
+       }
+}
+
+static void
+set_dpc_thresholds(void *__iomem base_addr,
+                  struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr)
+{
+       regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2C_THR_R);
+       regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2C_THR_GR);
+       regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2C_THR_GB);
+       regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2C_THR_B);
+       regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2D_THR_R);
+       regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2D_THR_GR);
+       regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2D_THR_GB);
+       regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK,
+               DPC_OTF_2D_THR_B);
+}
+
+void ipipe_set_otfdpc_regs(void *__iomem base_addr,
+                          struct vpfe_ipipe_otfdpc *otfdpc)
+{
+       struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0;
+       struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0;
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+
+       regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN);
+       if (!otfdpc->en)
+               return;
+
+       /* dpc enabled */
+       val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg;
+       regw_ip(base_addr, val, DPC_OTF_TYP);
+
+       if (otfdpc->det_method == VPFE_IPIPE_DPC_OTF_MIN_MAX) {
+               /* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0
+                * DPC_OTF_2C_THR_[x] = Maximum thresohld
+                * MinMax method
+                */
+               dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb =
+               dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0;
+               set_dpc_thresholds(base_addr, dpc_2_0);
+               return;
+       }
+       /* MinMax2 */
+       if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) {
+               set_dpc_thresholds(base_addr, dpc_2_0);
+               return;
+       }
+       regw_ip(base_addr, dpc_3_0->act_adj_shf &
+               OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF);
+       /* Detection thresholds */
+       regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) <<
+               OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR);
+       regw_ip(base_addr, dpc_3_0->det_slp &
+               OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP);
+       regw_ip(base_addr, dpc_3_0->det_thr_min &
+               OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN);
+       regw_ip(base_addr, dpc_3_0->det_thr_max &
+               OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX);
+       /* Correction thresholds */
+       regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) <<
+               OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR);
+       regw_ip(base_addr, dpc_3_0->corr_slp &
+               OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP);
+       regw_ip(base_addr, dpc_3_0->corr_thr_min &
+               OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN);
+       regw_ip(base_addr, dpc_3_0->corr_thr_max &
+               OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX);
+}
+
+/* 2D Noise filter */
+void
+ipipe_set_d2f_regs(void *__iomem base_addr, unsigned int id,
+                  struct vpfe_ipipe_nf *noise_filter)
+{
+
+       u32 offset = D2F_1ST;
+       int count;
+       u32 val;
+
+       if (id == IPIPE_D2F_2ND)
+               offset = D2F_2ND;
+
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN);
+       if (!noise_filter->en)
+               return;
+
+       /*noise filter enabled */
+       /* Combine all the fields to make D2F_CFG register of IPIPE */
+       val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) <<
+               D2F_SPR_VAL_SHIFT) | ((noise_filter->shft_val &
+               D2F_SHFT_VAL_MASK) << D2F_SHFT_VAL_SHIFT) |
+               (noise_filter->gr_sample_meth << D2F_SAMPLE_METH_SHIFT) |
+               ((noise_filter->apply_lsc_gain & 1) <<
+               D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL;
+       regw_ip(base_addr, val, offset + D2F_TYP);
+
+       /* edge detection minimum */
+       regw_ip(base_addr, noise_filter->edge_det_min_thr &
+               D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN);
+
+       /* edge detection maximum */
+       regw_ip(base_addr, noise_filter->edge_det_max_thr &
+               D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX);
+
+       for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++)
+               regw_ip(base_addr,
+                       (noise_filter->str[count] & D2F_STR_VAL_MASK),
+                       offset + D2F_STR + count * 4);
+
+       for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++)
+               regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK,
+                       offset + D2F_THR + count * 4);
+}
+
+#define IPIPE_U8Q5(decimal, integer) \
+       (((decimal & 0x1f) | ((integer & 0x7) << 5)))
+
+/* Green Imbalance Correction */
+void ipipe_set_gic_regs(void *__iomem base_addr, struct vpfe_ipipe_gic *gic)
+{
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, gic->en & 1, GIC_EN);
+
+       if (!gic->en)
+               return;
+
+       /*gic enabled */
+       val = (gic->wt_fn_type << GIC_TYP_SHIFT) |
+             (gic->thr_sel << GIC_THR_SEL_SHIFT) |
+             ((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT);
+       regw_ip(base_addr, val, GIC_TYP);
+
+       regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN);
+
+       if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) {
+               /* Constant Gain. Set threshold to maximum */
+               regw_ip(base_addr, GIC_THR_MASK, GIC_THR);
+               return;
+       }
+
+       if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) {
+               regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR);
+               regw_ip(base_addr, gic->slope & GIC_SLOPE_MASK, GIC_SLP);
+       } else {
+               /* Use NF thresholds */
+               val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal,
+                               gic->nf2_thr_gain.integer);
+               regw_ip(base_addr, val, GIC_NFGAN);
+       }
+}
+
+#define IPIPE_U13Q9(decimal, integer) \
+       (((decimal & 0x1ff) | ((integer & 0xf) << 9)))
+/* White balance */
+void ipipe_set_wb_regs(void *__iomem base_addr, struct vpfe_ipipe_wb *wb)
+{
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+       /* Ofsets. S12 */
+       regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R);
+       regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR);
+       regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB);
+       regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B);
+
+       /* Gains. U13Q9 */
+       val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer);
+       regw_ip(base_addr, val, WB2_WGN_R);
+
+       val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer);
+       regw_ip(base_addr, val, WB2_WGN_GR);
+
+       val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer);
+       regw_ip(base_addr, val, WB2_WGN_GB);
+
+       val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer);
+       regw_ip(base_addr, val, WB2_WGN_B);
+}
+
+/* CFA */
+void ipipe_set_cfa_regs(void *__iomem base_addr, struct vpfe_ipipe_cfa *cfa)
+{
+       ipipe_clock_enable(base_addr);
+
+       regw_ip(base_addr, cfa->alg, CFA_MODE);
+       regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK,
+               CFA_2DIR_HPF_THR);
+       regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK,
+               CFA_2DIR_HPF_SLP);
+       regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK,
+               CFA_2DIR_MIX_THR);
+       regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK,
+               CFA_2DIR_MIX_SLP);
+       regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK,
+               CFA_2DIR_DIR_THR);
+       regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK,
+               CFA_2DIR_DIR_SLP);
+       regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK,
+               CFA_2DIR_NDWT);
+       regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK,
+               CFA_MONO_HUE_FRA);
+       regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK,
+               CFA_MONO_EDG_THR);
+       regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK,
+               CFA_MONO_THR_MIN);
+       regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK,
+               CFA_MONO_THR_SLP);
+       regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK,
+               CFA_MONO_SLP_MIN);
+       regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK,
+               CFA_MONO_SLP_SLP);
+       regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK,
+               CFA_MONO_LPWT);
+}
+
+void
+ipipe_set_rgb2rgb_regs(void *__iomem base_addr, unsigned int id,
+                      struct vpfe_ipipe_rgb2rgb *rgb)
+{
+       u32 offset_mask = RGB2RGB_1_OFST_MASK;
+       u32 offset = RGB1_MUL_BASE;
+       u32 integ_mask = 0xf;
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+
+       if (id == IPIPE_RGB2RGB_2) {
+               /* For second RGB module, gain integer is 3 bits instead
+               of 4, offset has 11 bits insread of 13 */
+               offset = RGB2_MUL_BASE;
+               integ_mask = 0x7;
+               offset_mask = RGB2RGB_2_OFST_MASK;
+       }
+       /* Gains */
+       val = (rgb->coef_rr.decimal & 0xff) |
+               ((rgb->coef_rr.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_RR);
+       val = (rgb->coef_gr.decimal & 0xff) |
+               ((rgb->coef_gr.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_GR);
+       val = (rgb->coef_br.decimal & 0xff) |
+               ((rgb->coef_br.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_BR);
+       val = (rgb->coef_rg.decimal & 0xff) |
+               ((rgb->coef_rg.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_RG);
+       val = (rgb->coef_gg.decimal & 0xff) |
+               ((rgb->coef_gg.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_GG);
+       val = (rgb->coef_bg.decimal & 0xff) |
+               ((rgb->coef_bg.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_BG);
+       val = (rgb->coef_rb.decimal & 0xff) |
+               ((rgb->coef_rb.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_RB);
+       val = (rgb->coef_gb.decimal & 0xff) |
+               ((rgb->coef_gb.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_GB);
+       val = (rgb->coef_bb.decimal & 0xff) |
+               ((rgb->coef_bb.integer & integ_mask) << 8);
+       regw_ip(base_addr, val, offset + RGB_MUL_BB);
+
+       /* Offsets */
+       regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR);
+       regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG);
+       regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB);
+}
+
+static void
+ipipe_update_gamma_tbl(void *__iomem isp5_base_addr,
+       struct vpfe_ipipe_gamma_entry *table, int size, u32 addr)
+{
+       int count;
+       u32 val;
+
+       for (count = 0; count < size; count++) {
+               val = table[count].slope & GAMMA_MASK;
+               val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT;
+               w_ip_table(isp5_base_addr, val, (addr + (count * 4)));
+       }
+}
+
+void
+ipipe_set_gamma_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
+                         struct vpfe_ipipe_gamma *gamma)
+{
+       int table_size;
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+       val = (gamma->bypass_r << GAMMA_BYPR_SHIFT) |
+               (gamma->bypass_b << GAMMA_BYPG_SHIFT) |
+               (gamma->bypass_g << GAMMA_BYPB_SHIFT) |
+               (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) |
+               (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT);
+
+       regw_ip(base_addr, val, GMM_CFG);
+
+       if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
+               return;
+
+       table_size = gamma->tbl_size;
+
+       if (!gamma->bypass_r && gamma->table_r != NULL)
+               ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r,
+                       table_size, GAMMA_R_START_ADDR);
+       if (!gamma->bypass_b && gamma->table_b != NULL)
+               ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b,
+                       table_size, GAMMA_B_START_ADDR);
+       if (!gamma->bypass_g && gamma->table_g != NULL)
+               ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g,
+                       table_size, GAMMA_G_START_ADDR);
+}
+
+void
+ipipe_set_3d_lut_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
+                          struct vpfe_ipipe_3d_lut *lut_3d)
+{
+       struct vpfe_ipipe_3d_lut_entry *tbl;
+       u32 bnk_index;
+       u32 tbl_index;
+       u32 val;
+       u32 i;
+
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, lut_3d->en, D3LUT_EN);
+
+       if (!lut_3d->en)
+               return;
+
+       /* lut_3d enabled */
+       if (!lut_3d->table)
+               return;
+
+       /* valied table */
+       tbl = lut_3d->table;
+       for (i = 0 ; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) {
+               /* Each entry has 0-9 (B), 10-19 (G) and
+               20-29 R values */
+               val = tbl[i].b & D3_LUT_ENTRY_MASK;
+               val |= (tbl[i].g & D3_LUT_ENTRY_MASK) <<
+                        D3_LUT_ENTRY_G_SHIFT;
+               val |= (tbl[i].r & D3_LUT_ENTRY_MASK) <<
+                        D3_LUT_ENTRY_R_SHIFT;
+               bnk_index = i % 4;
+               tbl_index = i >> 2;
+               tbl_index <<= 2;
+               if (bnk_index == 0)
+                       w_ip_table(isp5_base_addr, val,
+                                  tbl_index + D3L_TB0_START_ADDR);
+               else if (bnk_index == 1)
+                       w_ip_table(isp5_base_addr, val,
+                                  tbl_index + D3L_TB1_START_ADDR);
+               else if (bnk_index == 2)
+                       w_ip_table(isp5_base_addr, val,
+                                  tbl_index + D3L_TB2_START_ADDR);
+               else
+                       w_ip_table(isp5_base_addr, val,
+                                  tbl_index + D3L_TB3_START_ADDR);
+       }
+}
+
+/* Lumina adjustments */
+void
+ipipe_set_lum_adj_regs(void *__iomem base_addr, struct ipipe_lum_adj *lum_adj)
+{
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+
+       /* combine fields of YUV_ADJ to set brightness and contrast */
+       val = lum_adj->contrast << LUM_ADJ_CONTR_SHIFT |
+             lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT;
+       regw_ip(base_addr, val, YUV_ADJ);
+}
+
+#define IPIPE_S12Q8(decimal, integer) \
+       (((decimal & 0xff) | ((integer & 0xf) << 8)))
+
+void ipipe_set_rgb2ycbcr_regs(void *__iomem base_addr,
+                             struct vpfe_ipipe_rgb2yuv *yuv)
+{
+       u32 val;
+
+       /* S10Q8 */
+       ipipe_clock_enable(base_addr);
+       val = IPIPE_S12Q8(yuv->coef_ry.decimal, yuv->coef_ry.integer);
+       regw_ip(base_addr, val, YUV_MUL_RY);
+       val = IPIPE_S12Q8(yuv->coef_gy.decimal, yuv->coef_gy.integer);
+       regw_ip(base_addr, val, YUV_MUL_GY);
+       val = IPIPE_S12Q8(yuv->coef_by.decimal, yuv->coef_by.integer);
+       regw_ip(base_addr, val, YUV_MUL_BY);
+       val = IPIPE_S12Q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer);
+       regw_ip(base_addr, val, YUV_MUL_RCB);
+       val = IPIPE_S12Q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer);
+       regw_ip(base_addr, val, YUV_MUL_GCB);
+       val = IPIPE_S12Q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer);
+       regw_ip(base_addr, val, YUV_MUL_BCB);
+       val = IPIPE_S12Q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer);
+       regw_ip(base_addr, val, YUV_MUL_RCR);
+       val = IPIPE_S12Q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer);
+       regw_ip(base_addr, val, YUV_MUL_GCR);
+       val = IPIPE_S12Q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer);
+       regw_ip(base_addr, val, YUV_MUL_BCR);
+       regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y);
+       regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB);
+       regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR);
+}
+
+/* YUV 422 conversion */
+void
+ipipe_set_yuv422_conv_regs(void *__iomem base_addr,
+                          struct vpfe_ipipe_yuv422_conv *conv)
+{
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+
+       /* Combine all the fields to make YUV_PHS register of IPIPE */
+       val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1);
+       regw_ip(base_addr, val, YUV_PHS);
+}
+
+void
+ipipe_set_gbce_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
+                   struct vpfe_ipipe_gbce *gbce)
+{
+       unsigned int count;
+       u32 mask = GBCE_Y_VAL_MASK;
+
+       if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
+               mask = GBCE_GAIN_VAL_MASK;
+
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, gbce->en & 1, GBCE_EN);
+
+       if (!gbce->en)
+               return;
+
+       regw_ip(base_addr, gbce->type, GBCE_TYP);
+
+       if (!gbce->table)
+               return;
+
+       for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT ; count += 2)
+               w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) <<
+               GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask),
+               ((count/2) << 2) + GBCE_TB_START_ADDR);
+}
+
+void
+ipipe_set_ee_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
+                 struct vpfe_ipipe_yee *ee)
+{
+       unsigned int count;
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, ee->en, YEE_EN);
+
+       if (!ee->en)
+               return;
+
+       val = ee->en_halo_red & 1;
+       val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT;
+       regw_ip(base_addr, val, YEE_TYP);
+
+       regw_ip(base_addr, ee->hpf_shft, YEE_SHF);
+       regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00);
+       regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01);
+       regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02);
+       regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10);
+       regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11);
+       regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12);
+       regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20);
+       regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21);
+       regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22);
+       regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR);
+       regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN);
+       regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1);
+       regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2);
+       regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN);
+       regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT);
+
+       if (ee->table == NULL)
+               return;
+
+       for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2)
+               w_ip_table(isp5_base_addr, ((ee->table[count + 1] &
+               YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) |
+               (ee->table[count] & YEE_ENTRY_MASK),
+               ((count/2) << 2) + YEE_TB_START_ADDR);
+}
+
+/* Chromatic Artifact Correction. CAR */
+static void ipipe_set_mf(void *__iomem base_addr)
+{
+       /* typ to dynamic switch */
+       regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
+       /* Set SW0 to maximum */
+       regw_ip(base_addr, CAR_MF_THR, CAR_SW);
+}
+
+static void
+ipipe_set_gain_ctrl(void *__iomem base_addr, struct vpfe_ipipe_car *car)
+{
+       regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP);
+       regw_ip(base_addr, car->hpf, CAR_HPF_TYP);
+       regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF);
+       regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR);
+       regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN);
+       regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF);
+       regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK,
+               CAR_GN1_MIN);
+       regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN);
+       regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF);
+       regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK,
+               CAR_GN2_MIN);
+}
+
+void ipipe_set_car_regs(void *__iomem base_addr, struct vpfe_ipipe_car *car)
+{
+       u32 val;
+
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, car->en, CAR_EN);
+
+       if (!car->en)
+               return;
+
+       switch (car->meth) {
+       case VPFE_IPIPE_CAR_MED_FLTR:
+               ipipe_set_mf(base_addr);
+               break;
+
+       case VPFE_IPIPE_CAR_CHR_GAIN_CTRL:
+               ipipe_set_gain_ctrl(base_addr, car);
+               break;
+
+       default:
+               /* Dynamic switch between MF and Gain Ctrl. */
+               ipipe_set_mf(base_addr);
+               ipipe_set_gain_ctrl(base_addr, car);
+               /* Set the threshold for switching between
+                 * the two Here we overwrite the MF SW0 value
+                 */
+               regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
+               val = car->sw1;
+               val <<= CAR_SW1_SHIFT;
+               val |= car->sw0;
+               regw_ip(base_addr, val, CAR_SW);
+       }
+}
+
+/* Chromatic Gain Suppression */
+void ipipe_set_cgs_regs(void *__iomem base_addr, struct vpfe_ipipe_cgs *cgs)
+{
+       ipipe_clock_enable(base_addr);
+       regw_ip(base_addr, cgs->en, CGS_EN);
+
+       if (!cgs->en)
+               return;
+
+       /* Set the bright side parameters */
+       regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR);
+       regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN);
+       regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF);
+       regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN);
+}
+
+void rsz_src_enable(void *__iomem rsz_base, int enable)
+{
+       regw_rsz(rsz_base, enable, RSZ_SRC_EN);
+}
+
+int rsz_enable(void *__iomem rsz_base, int rsz_id, int enable)
+{
+       if (rsz_id == RSZ_A) {
+               regw_rsz(rsz_base, enable, RSZ_EN_A);
+               /* We always enable RSZ_A. RSZ_B is enable upon request from
+                * application. So enable RSZ_SRC_EN along with RSZ_A
+                */
+               regw_rsz(rsz_base, enable, RSZ_SRC_EN);
+       } else if (rsz_id == RSZ_B) {
+               regw_rsz(rsz_base, enable, RSZ_EN_B);
+       } else {
+               BUG();
+       }
+
+       return 0;
+}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h
new file mode 100644 (file)
index 0000000..010fdb2
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_IPIPE_HW_H
+#define _DAVINCI_VPFE_DM365_IPIPE_HW_H
+
+#include "vpfe_mc_capture.h"
+
+#define SET_LOW_ADDR     0x0000ffff
+#define SET_HIGH_ADDR    0xffff0000
+
+/* Below are the internal tables */
+#define DPC_TB0_START_ADDR     0x8000
+#define DPC_TB1_START_ADDR     0x8400
+
+#define GAMMA_R_START_ADDR     0xa800
+#define GAMMA_G_START_ADDR     0xb000
+#define GAMMA_B_START_ADDR     0xb800
+
+/* RAM table addresses for edge enhancement correction*/
+#define YEE_TB_START_ADDR      0x8800
+
+/* RAM table address for GBC LUT */
+#define GBCE_TB_START_ADDR     0x9000
+
+/* RAM table for 3D NF LUT */
+#define D3L_TB0_START_ADDR     0x9800
+#define D3L_TB1_START_ADDR     0x9c00
+#define D3L_TB2_START_ADDR     0xa000
+#define D3L_TB3_START_ADDR     0xa400
+
+/* IPIPE Register Offsets from the base address */
+#define IPIPE_SRC_EN           0x0000
+#define IPIPE_SRC_MODE         0x0004
+#define IPIPE_SRC_FMT          0x0008
+#define IPIPE_SRC_COL          0x000c
+#define IPIPE_SRC_VPS          0x0010
+#define IPIPE_SRC_VSZ          0x0014
+#define IPIPE_SRC_HPS          0x0018
+#define IPIPE_SRC_HSZ          0x001c
+
+#define IPIPE_SEL_SBU          0x0020
+
+#define IPIPE_DMA_STA          0x0024
+#define IPIPE_GCK_MMR          0x0028
+#define IPIPE_GCK_PIX          0x002c
+#define IPIPE_RESERVED0                0x0030
+
+/* Defect Correction */
+#define DPC_LUT_EN             0x0034
+#define DPC_LUT_SEL            0x0038
+#define DPC_LUT_ADR            0x003c
+#define DPC_LUT_SIZ            0x0040
+#define DPC_OTF_EN             0x0044
+#define DPC_OTF_TYP            0x0048
+#define DPC_OTF_2D_THR_R       0x004c
+#define DPC_OTF_2D_THR_GR      0x0050
+#define DPC_OTF_2D_THR_GB      0x0054
+#define DPC_OTF_2D_THR_B       0x0058
+#define DPC_OTF_2C_THR_R       0x005c
+#define DPC_OTF_2C_THR_GR      0x0060
+#define DPC_OTF_2C_THR_GB      0x0064
+#define DPC_OTF_2C_THR_B       0x0068
+#define DPC_OTF_3_SHF          0x006c
+#define DPC_OTF_3D_THR         0x0070
+#define DPC_OTF_3D_SLP         0x0074
+#define DPC_OTF_3D_MIN         0x0078
+#define DPC_OTF_3D_MAX         0x007c
+#define DPC_OTF_3C_THR         0x0080
+#define DPC_OTF_3C_SLP         0x0084
+#define DPC_OTF_3C_MIN         0x0088
+#define DPC_OTF_3C_MAX         0x008c
+
+/* Lense Shading Correction */
+#define LSC_VOFT               0x90
+#define LSC_VA2                        0x94
+#define LSC_VA1                        0x98
+#define LSC_VS                 0x9c
+#define LSC_HOFT               0xa0
+#define LSC_HA2                        0xa4
+#define LSC_HA1                        0xa8
+#define LSC_HS                 0xac
+#define LSC_GAIN_R             0xb0
+#define LSC_GAIN_GR            0xb4
+#define LSC_GAIN_GB            0xb8
+#define LSC_GAIN_B             0xbc
+#define LSC_OFT_R              0xc0
+#define LSC_OFT_GR             0xc4
+#define LSC_OFT_GB             0xc8
+#define LSC_OFT_B              0xcc
+#define LSC_SHF                        0xd0
+#define LSC_MAX                        0xd4
+
+/* Noise Filter 1. Ofsets from start address given */
+#define D2F_1ST                        0xd8
+#define D2F_EN                 0x0
+#define D2F_TYP                        0x4
+#define D2F_THR                        0x8
+#define D2F_STR                        0x28
+#define D2F_SPR                        0x48
+#define D2F_EDG_MIN            0x68
+#define D2F_EDG_MAX            0x6c
+
+/* Noise Filter 2 */
+#define D2F_2ND                        0x148
+
+/* GIC */
+#define GIC_EN                 0x1b8
+#define GIC_TYP                        0x1bc
+#define GIC_GAN                        0x1c0
+#define GIC_NFGAN              0x1c4
+#define GIC_THR                        0x1c8
+#define GIC_SLP                        0x1cc
+
+/* White Balance */
+#define WB2_OFT_R              0x1d0
+#define WB2_OFT_GR             0x1d4
+#define WB2_OFT_GB             0x1d8
+#define WB2_OFT_B              0x1dc
+#define WB2_WGN_R              0x1e0
+#define WB2_WGN_GR             0x1e4
+#define WB2_WGN_GB             0x1e8
+#define WB2_WGN_B              0x1ec
+
+/* CFA interpolation */
+#define CFA_MODE               0x1f0
+#define CFA_2DIR_HPF_THR       0x1f4
+#define CFA_2DIR_HPF_SLP       0x1f8
+#define CFA_2DIR_MIX_THR       0x1fc
+#define CFA_2DIR_MIX_SLP       0x200
+#define CFA_2DIR_DIR_THR       0x204
+#define CFA_2DIR_DIR_SLP       0x208
+#define CFA_2DIR_NDWT          0x20c
+#define CFA_MONO_HUE_FRA       0x210
+#define CFA_MONO_EDG_THR       0x214
+#define CFA_MONO_THR_MIN       0x218
+#define CFA_MONO_THR_SLP       0x21c
+#define CFA_MONO_SLP_MIN       0x220
+#define CFA_MONO_SLP_SLP       0x224
+#define CFA_MONO_LPWT          0x228
+
+/* RGB to RGB conversiona - 1st */
+#define RGB1_MUL_BASE          0x22c
+/* Offsets from base */
+#define RGB_MUL_RR             0x0
+#define RGB_MUL_GR             0x4
+#define RGB_MUL_BR             0x8
+#define RGB_MUL_RG             0xc
+#define RGB_MUL_GG             0x10
+#define RGB_MUL_BG             0x14
+#define RGB_MUL_RB             0x18
+#define RGB_MUL_GB             0x1c
+#define RGB_MUL_BB             0x20
+#define RGB_OFT_OR             0x24
+#define RGB_OFT_OG             0x28
+#define RGB_OFT_OB             0x2c
+
+/* Gamma */
+#define GMM_CFG                        0x25c
+
+/* RGB to RGB conversiona - 2nd */
+#define RGB2_MUL_BASE          0x260
+
+/* 3D LUT */
+#define D3LUT_EN               0x290
+
+/* RGB to YUV(YCbCr) conversion */
+#define YUV_ADJ                        0x294
+#define YUV_MUL_RY             0x298
+#define YUV_MUL_GY             0x29c
+#define YUV_MUL_BY             0x2a0
+#define YUV_MUL_RCB            0x2a4
+#define YUV_MUL_GCB            0x2a8
+#define YUV_MUL_BCB            0x2ac
+#define YUV_MUL_RCR            0x2b0
+#define YUV_MUL_GCR            0x2b4
+#define YUV_MUL_BCR            0x2b8
+#define YUV_OFT_Y              0x2bc
+#define YUV_OFT_CB             0x2c0
+#define YUV_OFT_CR             0x2c4
+#define YUV_PHS                        0x2c8
+
+/* Global Brightness and Contrast */
+#define GBCE_EN                        0x2cc
+#define GBCE_TYP               0x2d0
+
+/* Edge Enhancer */
+#define YEE_EN                 0x2d4
+#define YEE_TYP                        0x2d8
+#define YEE_SHF                        0x2dc
+#define YEE_MUL_00             0x2e0
+#define YEE_MUL_01             0x2e4
+#define YEE_MUL_02             0x2e8
+#define YEE_MUL_10             0x2ec
+#define YEE_MUL_11             0x2f0
+#define YEE_MUL_12             0x2f4
+#define YEE_MUL_20             0x2f8
+#define YEE_MUL_21             0x2fc
+#define YEE_MUL_22             0x300
+#define YEE_THR                        0x304
+#define YEE_E_GAN              0x308
+#define YEE_E_THR1             0x30c
+#define YEE_E_THR2             0x310
+#define YEE_G_GAN              0x314
+#define YEE_G_OFT              0x318
+
+/* Chroma Artifact Reduction */
+#define CAR_EN                 0x31c
+#define CAR_TYP                        0x320
+#define CAR_SW                 0x324
+#define CAR_HPF_TYP            0x328
+#define CAR_HPF_SHF            0x32c
+#define        CAR_HPF_THR             0x330
+#define CAR_GN1_GAN            0x334
+#define CAR_GN1_SHF            0x338
+#define CAR_GN1_MIN            0x33c
+#define CAR_GN2_GAN            0x340
+#define CAR_GN2_SHF            0x344
+#define CAR_GN2_MIN            0x348
+
+/* Chroma Gain Suppression */
+#define CGS_EN                 0x34c
+#define CGS_GN1_L_THR          0x350
+#define CGS_GN1_L_GAN          0x354
+#define CGS_GN1_L_SHF          0x358
+#define CGS_GN1_L_MIN          0x35c
+#define CGS_GN1_H_THR          0x360
+#define CGS_GN1_H_GAN          0x364
+#define CGS_GN1_H_SHF          0x368
+#define CGS_GN1_H_MIN          0x36c
+#define CGS_GN2_L_THR          0x370
+#define CGS_GN2_L_GAN          0x374
+#define CGS_GN2_L_SHF          0x378
+#define CGS_GN2_L_MIN          0x37c
+
+/* Resizer */
+#define RSZ_SRC_EN             0x0
+#define RSZ_SRC_MODE           0x4
+#define RSZ_SRC_FMT0           0x8
+#define RSZ_SRC_FMT1           0xc
+#define RSZ_SRC_VPS            0x10
+#define RSZ_SRC_VSZ            0x14
+#define RSZ_SRC_HPS            0x18
+#define RSZ_SRC_HSZ            0x1c
+#define RSZ_DMA_RZA            0x20
+#define RSZ_DMA_RZB            0x24
+#define RSZ_DMA_STA            0x28
+#define RSZ_GCK_MMR            0x2c
+#define RSZ_RESERVED0          0x30
+#define RSZ_GCK_SDR            0x34
+#define RSZ_IRQ_RZA            0x38
+#define RSZ_IRQ_RZB            0x3c
+#define RSZ_YUV_Y_MIN          0x40
+#define RSZ_YUV_Y_MAX          0x44
+#define RSZ_YUV_C_MIN          0x48
+#define RSZ_YUV_C_MAX          0x4c
+#define RSZ_YUV_PHS            0x50
+#define RSZ_SEQ                        0x54
+
+/* Resizer Rescale Parameters */
+#define RSZ_EN_A               0x58
+#define RSZ_EN_B               0xe8
+/* offset of the registers to be added with base register of
+   either RSZ0 or RSZ1
+*/
+#define RSZ_MODE               0x4
+#define RSZ_420                        0x8
+#define RSZ_I_VPS              0xc
+#define RSZ_I_HPS              0x10
+#define RSZ_O_VSZ              0x14
+#define RSZ_O_HSZ              0x18
+#define RSZ_V_PHS_Y            0x1c
+#define RSZ_V_PHS_C            0x20
+#define RSZ_V_DIF              0x24
+#define RSZ_V_TYP              0x28
+#define RSZ_V_LPF              0x2c
+#define RSZ_H_PHS              0x30
+#define RSZ_H_PHS_ADJ          0x34
+#define RSZ_H_DIF              0x38
+#define RSZ_H_TYP              0x3c
+#define RSZ_H_LPF              0x40
+#define RSZ_DWN_EN             0x44
+#define RSZ_DWN_AV             0x48
+
+/* Resizer RGB Conversion Parameters */
+#define RSZ_RGB_EN             0x4c
+#define RSZ_RGB_TYP            0x50
+#define RSZ_RGB_BLD            0x54
+
+/* Resizer External Memory Parameters */
+#define RSZ_SDR_Y_BAD_H                0x58
+#define RSZ_SDR_Y_BAD_L                0x5c
+#define RSZ_SDR_Y_SAD_H                0x60
+#define RSZ_SDR_Y_SAD_L                0x64
+#define RSZ_SDR_Y_OFT          0x68
+#define RSZ_SDR_Y_PTR_S                0x6c
+#define RSZ_SDR_Y_PTR_E                0x70
+#define RSZ_SDR_C_BAD_H                0x74
+#define RSZ_SDR_C_BAD_L                0x78
+#define RSZ_SDR_C_SAD_H                0x7c
+#define RSZ_SDR_C_SAD_L                0x80
+#define RSZ_SDR_C_OFT          0x84
+#define RSZ_SDR_C_PTR_S                0x88
+#define RSZ_SDR_C_PTR_E                0x8c
+
+/* Macro for resizer */
+#define RSZ_YUV_Y_MIN          0x40
+#define RSZ_YUV_Y_MAX          0x44
+#define RSZ_YUV_C_MIN          0x48
+#define RSZ_YUV_C_MAX          0x4c
+
+#define IPIPE_GCK_MMR_DEFAULT  1
+#define IPIPE_GCK_PIX_DEFAULT  0xe
+#define RSZ_GCK_MMR_DEFAULT    1
+#define RSZ_GCK_SDR_DEFAULT    1
+
+/* LUTDPC */
+#define LUTDPC_TBL_256_EN      0
+#define LUTDPC_INF_TBL_EN      1
+#define LUT_DPC_START_ADDR     0
+#define LUT_DPC_H_POS_MASK     0x1fff
+#define LUT_DPC_V_POS_MASK     0x1fff
+#define LUT_DPC_V_POS_SHIFT    13
+#define LUT_DPC_CORR_METH_SHIFT        26
+#define LUT_DPC_MAX_SIZE       256
+#define LUT_DPC_SIZE_MASK      0x3ff
+
+/* OTFDPC */
+#define OTFDPC_DPC2_THR_MASK   0xfff
+#define OTF_DET_METHOD_SHIFT   1
+#define OTF_DPC3_0_SHF_MASK    3
+#define OTF_DPC3_0_THR_SHIFT   6
+#define OTF_DPC3_0_THR_MASK    0x3f
+#define OTF_DPC3_0_SLP_MASK    0x3f
+#define OTF_DPC3_0_DET_MASK    0xfff
+#define OTF_DPC3_0_CORR_MASK   0xfff
+
+/* NF (D2F) */
+#define D2F_SPR_VAL_MASK               0x1f
+#define D2F_SPR_VAL_SHIFT              0
+#define D2F_SHFT_VAL_MASK              3
+#define D2F_SHFT_VAL_SHIFT             5
+#define D2F_SAMPLE_METH_SHIFT          7
+#define D2F_APPLY_LSC_GAIN_SHIFT       8
+#define D2F_USE_SPR_REG_VAL            0
+#define D2F_STR_VAL_MASK               0x1f
+#define D2F_THR_VAL_MASK               0x3ff
+#define D2F_EDGE_DET_THR_MASK          0x7ff
+
+/* Green Imbalance Correction */
+#define GIC_TYP_SHIFT                  0
+#define GIC_THR_SEL_SHIFT              1
+#define        GIC_APPLY_LSC_GAIN_SHIFT        2
+#define GIC_GAIN_MASK                  0xff
+#define GIC_THR_MASK                   0xfff
+#define GIC_SLOPE_MASK                 0xfff
+#define GIC_NFGAN_INT_MASK             7
+#define GIC_NFGAN_DECI_MASK            0x1f
+
+/* WB */
+#define WB_OFFSET_MASK                 0xfff
+#define WB_GAIN_INT_MASK               0xf
+#define WB_GAIN_DECI_MASK              0x1ff
+
+/* CFA */
+#define CFA_HPF_THR_2DIR_MASK          0x1fff
+#define CFA_HPF_SLOPE_2DIR_MASK                0x3ff
+#define CFA_HPF_MIX_THR_2DIR_MASK      0x1fff
+#define CFA_HPF_MIX_SLP_2DIR_MASK      0x3ff
+#define CFA_DIR_THR_2DIR_MASK          0x3ff
+#define CFA_DIR_SLP_2DIR_MASK          0x7f
+#define CFA_ND_WT_2DIR_MASK            0x3f
+#define CFA_DAA_HUE_FRA_MASK           0x3f
+#define CFA_DAA_EDG_THR_MASK           0xff
+#define CFA_DAA_THR_MIN_MASK           0x3ff
+#define CFA_DAA_THR_SLP_MASK           0x3ff
+#define CFA_DAA_SLP_MIN_MASK           0x3ff
+#define CFA_DAA_SLP_SLP_MASK           0x3ff
+#define CFA_DAA_LP_WT_MASK             0x3f
+
+/* RGB2RGB */
+#define RGB2RGB_1_OFST_MASK            0x1fff
+#define RGB2RGB_1_GAIN_INT_MASK                0xf
+#define RGB2RGB_GAIN_DECI_MASK         0xff
+#define RGB2RGB_2_OFST_MASK            0x7ff
+#define RGB2RGB_2_GAIN_INT_MASK                0x7
+
+/* Gamma */
+#define GAMMA_BYPR_SHIFT               0
+#define GAMMA_BYPG_SHIFT               1
+#define GAMMA_BYPB_SHIFT               2
+#define GAMMA_TBL_SEL_SHIFT            4
+#define GAMMA_TBL_SIZE_SHIFT           5
+#define GAMMA_MASK                     0x3ff
+#define GAMMA_SHIFT                    10
+
+/* 3D LUT */
+#define D3_LUT_ENTRY_MASK              0x3ff
+#define D3_LUT_ENTRY_R_SHIFT           20
+#define D3_LUT_ENTRY_G_SHIFT           10
+#define D3_LUT_ENTRY_B_SHIFT           0
+
+/* Lumina adj */
+#define        LUM_ADJ_CONTR_SHIFT             0
+#define        LUM_ADJ_BRIGHT_SHIFT            8
+
+/* RGB2YCbCr */
+#define RGB2YCBCR_OFST_MASK            0x7ff
+#define RGB2YCBCR_COEF_INT_MASK                0xf
+#define RGB2YCBCR_COEF_DECI_MASK       0xff
+
+/* GBCE */
+#define GBCE_Y_VAL_MASK                        0xff
+#define GBCE_GAIN_VAL_MASK             0x3ff
+#define GBCE_ENTRY_SHIFT               10
+
+/* Edge Enhancements */
+#define YEE_HALO_RED_EN_SHIFT          1
+#define YEE_HPF_SHIFT_MASK             0xf
+#define YEE_COEF_MASK                  0x3ff
+#define YEE_THR_MASK                   0x3f
+#define YEE_ES_GAIN_MASK               0xfff
+#define YEE_ES_THR1_MASK               0xfff
+#define YEE_ENTRY_SHIFT                        9
+#define YEE_ENTRY_MASK                 0x1ff
+
+/* CAR */
+#define CAR_MF_THR                     0xff
+#define CAR_SW1_SHIFT                  8
+#define CAR_GAIN1_SHFT_MASK            7
+#define CAR_GAIN_MIN_MASK              0x1ff
+#define CAR_GAIN2_SHFT_MASK            0xf
+#define CAR_HPF_SHIFT_MASK             3
+
+/* CGS */
+#define CAR_SHIFT_MASK                 3
+
+/* Resizer */
+#define RSZ_BYPASS_SHIFT               1
+#define RSZ_SRC_IMG_FMT_SHIFT          1
+#define RSZ_SRC_Y_C_SEL_SHIFT          2
+#define IPIPE_RSZ_VPS_MASK             0xffff
+#define IPIPE_RSZ_HPS_MASK             0xffff
+#define IPIPE_RSZ_VSZ_MASK             0x1fff
+#define IPIPE_RSZ_HSZ_MASK             0x1fff
+#define RSZ_HPS_MASK                   0x1fff
+#define RSZ_VPS_MASK                   0x1fff
+#define RSZ_O_HSZ_MASK                 0x1fff
+#define RSZ_O_VSZ_MASK                 0x1fff
+#define RSZ_V_PHS_MASK                 0x3fff
+#define RSZ_V_DIF_MASK                 0x3fff
+
+#define RSZA_H_FLIP_SHIFT              0
+#define RSZA_V_FLIP_SHIFT              1
+#define RSZB_H_FLIP_SHIFT              2
+#define RSZB_V_FLIP_SHIFT              3
+#define RSZ_A                          0
+#define RSZ_B                          1
+#define RSZ_CEN_SHIFT                  1
+#define RSZ_YEN_SHIFT                  0
+#define RSZ_TYP_Y_SHIFT                        0
+#define RSZ_TYP_C_SHIFT                        1
+#define RSZ_LPF_INT_MASK               0x3f
+#define RSZ_LPF_INT_MASK               0x3f
+#define RSZ_LPF_INT_C_SHIFT            6
+#define RSZ_H_PHS_MASK                 0x3fff
+#define RSZ_H_DIF_MASK                 0x3fff
+#define RSZ_DIFF_DOWN_THR              256
+#define RSZ_DWN_SCALE_AV_SZ_V_SHIFT    3
+#define RSZ_DWN_SCALE_AV_SZ_MASK       7
+#define RSZ_RGB_MSK1_SHIFT             2
+#define RSZ_RGB_MSK0_SHIFT             1
+#define RSZ_RGB_TYP_SHIFT              0
+#define RSZ_RGB_ALPHA_MASK             0xff
+
+static inline u32 regr_ip(void *__iomem addr, u32 offset)
+{
+       return readl(addr + offset);
+}
+
+static inline void regw_ip(void *__iomem addr, u32 val, u32 offset)
+{
+       writel(val, addr + offset);
+}
+
+static inline u32 w_ip_table(void *__iomem addr, u32 val, u32 offset)
+{
+       writel(val, addr + offset);
+
+       return val;
+}
+
+static inline u32 regr_rsz(void *__iomem addr, u32 offset)
+{
+       return readl(addr + offset);
+}
+
+static inline u32 regw_rsz(void *__iomem addr, u32 val, u32 offset)
+{
+       writel(val, addr + offset);
+
+       return val;
+}
+
+int config_ipipe_hw(struct vpfe_ipipe_device *ipipe);
+int resizer_set_outaddr(void *__iomem rsz_base, struct resizer_params *params,
+                       int resize_no, unsigned int address);
+int rsz_enable(void *__iomem rsz_base, int rsz_id, int enable);
+void rsz_src_enable(void *__iomem rsz_base, int enable);
+void rsz_set_in_pix_format(unsigned char y_c);
+int config_rsz_hw(struct vpfe_resizer_device *resizer,
+                 struct resizer_params *config);
+void ipipe_set_d2f_regs(void *__iomem base_addr, unsigned int id,
+       struct vpfe_ipipe_nf *noise_filter);
+void ipipe_set_rgb2rgb_regs(void *__iomem base_addr, unsigned int id,
+       struct vpfe_ipipe_rgb2rgb *rgb);
+void ipipe_set_yuv422_conv_regs(void *__iomem base_addr,
+       struct vpfe_ipipe_yuv422_conv *conv);
+void ipipe_set_lum_adj_regs(void *__iomem base_addr,
+       struct ipipe_lum_adj *lum_adj);
+void ipipe_set_rgb2ycbcr_regs(void *__iomem base_addr,
+       struct vpfe_ipipe_rgb2yuv *yuv);
+void ipipe_set_lutdpc_regs(void *__iomem base_addr,
+       void *__iomem isp5_base_addr, struct vpfe_ipipe_lutdpc *lutdpc);
+void ipipe_set_otfdpc_regs(void *__iomem base_addr,
+       struct vpfe_ipipe_otfdpc *otfdpc);
+void ipipe_set_3d_lut_regs(void *__iomem base_addr,
+       void *__iomem isp5_base_addr, struct vpfe_ipipe_3d_lut *lut_3d);
+void ipipe_set_gamma_regs(void *__iomem base_addr,
+       void *__iomem isp5_base_addr, struct vpfe_ipipe_gamma *gamma);
+void ipipe_set_ee_regs(void *__iomem base_addr,
+       void *__iomem isp5_base_addr, struct vpfe_ipipe_yee *ee);
+void ipipe_set_gbce_regs(void *__iomem base_addr,
+       void *__iomem isp5_base_addr, struct vpfe_ipipe_gbce *gbce);
+void ipipe_set_gic_regs(void *__iomem base_addr, struct vpfe_ipipe_gic *gic);
+void ipipe_set_cfa_regs(void *__iomem base_addr, struct vpfe_ipipe_cfa *cfa);
+void ipipe_set_car_regs(void *__iomem base_addr, struct vpfe_ipipe_car *car);
+void ipipe_set_cgs_regs(void *__iomem base_addr, struct vpfe_ipipe_cgs *cgs);
+void ipipe_set_wb_regs(void *__iomem base_addr, struct vpfe_ipipe_wb *wb);
+
+#endif         /* _DAVINCI_VPFE_DM365_IPIPE_HW_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
new file mode 100644 (file)
index 0000000..c8cae51
--- /dev/null
@@ -0,0 +1,1071 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#include "dm365_ipipeif.h"
+#include "vpfe_mc_capture.h"
+
+static const unsigned int ipipeif_input_fmts[] = {
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_SGRBG12_1X12,
+       V4L2_MBUS_FMT_Y8_1X8,
+       V4L2_MBUS_FMT_UV8_1X8,
+       V4L2_MBUS_FMT_YDYUYDYV8_1X16,
+       V4L2_MBUS_FMT_SBGGR8_1X8,
+};
+
+static const unsigned int ipipeif_output_fmts[] = {
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_SGRBG12_1X12,
+       V4L2_MBUS_FMT_Y8_1X8,
+       V4L2_MBUS_FMT_UV8_1X8,
+       V4L2_MBUS_FMT_YDYUYDYV8_1X16,
+       V4L2_MBUS_FMT_SBGGR8_1X8,
+       V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+       V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
+};
+
+static int
+ipipeif_get_pack_mode(enum v4l2_mbus_pixelcode in_pix_fmt)
+{
+       switch (in_pix_fmt) {
+       case V4L2_MBUS_FMT_SBGGR8_1X8:
+       case V4L2_MBUS_FMT_Y8_1X8:
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_UV8_1X8:
+               return IPIPEIF_5_1_PACK_8_BIT;
+
+       case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+               return IPIPEIF_5_1_PACK_8_BIT_A_LAW;
+
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               return IPIPEIF_5_1_PACK_16_BIT;
+
+       case V4L2_MBUS_FMT_SBGGR12_1X12:
+               return IPIPEIF_5_1_PACK_12_BIT;
+
+       default:
+               return IPIPEIF_5_1_PACK_16_BIT;
+       }
+}
+
+static inline u32 ipipeif_read(void *addr, u32 offset)
+{
+       return readl(addr + offset);
+}
+
+static inline void ipipeif_write(u32 val, void *addr, u32 offset)
+{
+       writel(val, addr + offset);
+}
+
+static void ipipeif_config_dpc(void *addr, struct ipipeif_dpc *dpc)
+{
+       u32 val = 0;
+
+       if (dpc->en) {
+               val = (dpc->en & 1) << IPIPEIF_DPC2_EN_SHIFT;
+               val |= dpc->thr & IPIPEIF_DPC2_THR_MASK;
+       }
+       ipipeif_write(val, addr, IPIPEIF_DPC2);
+}
+
+#define IPIPEIF_MODE_CONTINUOUS                        0
+#define IPIPEIF_MODE_ONE_SHOT                  1
+
+static int get_oneshot_mode(enum ipipeif_input_entity input)
+{
+       if (input == IPIPEIF_INPUT_MEMORY)
+               return IPIPEIF_MODE_ONE_SHOT;
+       else if (input == IPIPEIF_INPUT_ISIF)
+               return IPIPEIF_MODE_CONTINUOUS;
+
+       return -EINVAL;
+}
+
+static int
+ipipeif_get_cfg_src1(struct vpfe_ipipeif_device *ipipeif)
+{
+       struct v4l2_mbus_framefmt *informat;
+
+       informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
+       if (ipipeif->input == IPIPEIF_INPUT_MEMORY &&
+          (informat->code == V4L2_MBUS_FMT_Y8_1X8 ||
+           informat->code == V4L2_MBUS_FMT_UV8_1X8))
+               return IPIPEIF_CCDC;
+
+       return IPIPEIF_SRC1_PARALLEL_PORT;
+}
+
+static int
+ipipeif_get_data_shift(struct vpfe_ipipeif_device *ipipeif)
+{
+       struct v4l2_mbus_framefmt *informat;
+
+       informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
+
+       switch (informat->code) {
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               return IPIPEIF_5_1_BITS11_0;
+
+       case V4L2_MBUS_FMT_Y8_1X8:
+       case V4L2_MBUS_FMT_UV8_1X8:
+               return IPIPEIF_5_1_BITS11_0;
+
+       default:
+               return IPIPEIF_5_1_BITS7_0;
+       }
+}
+
+static enum ipipeif_input_source
+ipipeif_get_source(struct vpfe_ipipeif_device *ipipeif)
+{
+       struct v4l2_mbus_framefmt *informat;
+
+       informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
+       if (ipipeif->input == IPIPEIF_INPUT_ISIF)
+               return IPIPEIF_CCDC;
+
+       if (informat->code == V4L2_MBUS_FMT_UYVY8_2X8)
+               return IPIPEIF_SDRAM_YUV;
+
+       return IPIPEIF_SDRAM_RAW;
+}
+
+void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif)
+{
+       struct vpfe_video_device *video_in = &ipipeif->video_in;
+
+       if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
+               return;
+
+       spin_lock(&video_in->dma_queue_lock);
+       vpfe_video_process_buffer_complete(video_in);
+       video_in->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
+       vpfe_video_schedule_next_buffer(video_in);
+       spin_unlock(&video_in->dma_queue_lock);
+}
+
+int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev)
+{
+       struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
+
+       return ipipeif->config.decimation;
+}
+
+int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev)
+{
+       struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
+
+       return ipipeif->config.rsz;
+}
+
+#define RD_DATA_15_2           0x7
+
+/*
+ * ipipeif_hw_setup() - This function sets up IPIPEIF
+ * @sd: pointer to v4l2 subdev structure
+ * return -EINVAL or zero on success
+ */
+static int ipipeif_hw_setup(struct v4l2_subdev *sd)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *informat, *outformat;
+       struct ipipeif_params params = ipipeif->config;
+       enum ipipeif_input_source ipipeif_source;
+       enum v4l2_mbus_pixelcode isif_port_if;
+       void *ipipeif_base_addr;
+       unsigned int val;
+       int data_shift;
+       int pack_mode;
+       int source1;
+
+       ipipeif_base_addr = ipipeif->ipipeif_base_addr;
+
+       /* Enable clock to IPIPEIF and IPIPE */
+       vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
+
+       informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
+       outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE];
+
+       /* Combine all the fields to make CFG1 register of IPIPEIF */
+       val = get_oneshot_mode(ipipeif->input);
+       if (val < 0) {
+               pr_err("ipipeif: links setup required");
+               return -EINVAL;
+       }
+       val = val << ONESHOT_SHIFT;
+
+       ipipeif_source = ipipeif_get_source(ipipeif);
+       val |= ipipeif_source << INPSRC_SHIFT;
+
+       val |= params.clock_select << CLKSEL_SHIFT;
+       val |= params.avg_filter << AVGFILT_SHIFT;
+       val |= params.decimation << DECIM_SHIFT;
+
+       pack_mode = ipipeif_get_pack_mode(informat->code);
+       val |= pack_mode << PACK8IN_SHIFT;
+
+       source1 = ipipeif_get_cfg_src1(ipipeif);
+       val |= source1 << INPSRC1_SHIFT;
+
+       data_shift = ipipeif_get_data_shift(ipipeif);
+       if (ipipeif_source != IPIPEIF_SDRAM_YUV)
+               val |= data_shift << DATASFT_SHIFT;
+       else
+               val &= ~(RD_DATA_15_2 << DATASFT_SHIFT);
+
+       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG1);
+
+       switch (ipipeif_source) {
+       case IPIPEIF_CCDC:
+               ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN);
+               break;
+
+       case IPIPEIF_SDRAM_RAW:
+       case IPIPEIF_CCDC_DARKFM:
+               ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN);
+               /* fall through */
+       case IPIPEIF_SDRAM_YUV:
+               val |= data_shift << DATASFT_SHIFT;
+               ipipeif_write(params.ppln, ipipeif_base_addr, IPIPEIF_PPLN);
+               ipipeif_write(params.lpfr, ipipeif_base_addr, IPIPEIF_LPFR);
+               ipipeif_write(informat->width, ipipeif_base_addr, IPIPEIF_HNUM);
+               ipipeif_write(informat->height,
+                             ipipeif_base_addr, IPIPEIF_VNUM);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /*check if decimation is enable or not */
+       if (params.decimation)
+               ipipeif_write(params.rsz, ipipeif_base_addr, IPIPEIF_RSZ);
+
+       /* Setup sync alignment and initial rsz position */
+       val = params.if_5_1.align_sync & 1;
+       val <<= IPIPEIF_INIRSZ_ALNSYNC_SHIFT;
+       val |= params.if_5_1.rsz_start & IPIPEIF_INIRSZ_MASK;
+       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_INIRSZ);
+       isif_port_if = informat->code;
+
+       if (isif_port_if == V4L2_MBUS_FMT_Y8_1X8)
+               isif_port_if = V4L2_MBUS_FMT_YUYV8_1X16;
+       else if (isif_port_if == V4L2_MBUS_FMT_UV8_1X8)
+               isif_port_if = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+       /* Enable DPCM decompression */
+       switch (ipipeif_source) {
+       case IPIPEIF_SDRAM_RAW:
+               val = 0;
+               if (outformat->code == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8) {
+                       val = 1;
+                       val |= (IPIPEIF_DPCM_8BIT_10BIT & 1) <<
+                               IPIPEIF_DPCM_BITS_SHIFT;
+                       val |= (ipipeif->dpcm_predictor & 1) <<
+                               IPIPEIF_DPCM_PRED_SHIFT;
+               }
+               ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DPCM);
+
+               /* set DPC */
+               ipipeif_config_dpc(ipipeif_base_addr, &params.if_5_1.dpc);
+
+               ipipeif_write(params.if_5_1.clip,
+                             ipipeif_base_addr, IPIPEIF_OCLIP);
+
+               /* fall through for SDRAM YUV mode */
+               /* configure CFG2 */
+               val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CFG2);
+               switch (isif_port_if) {
+               case V4L2_MBUS_FMT_YUYV8_1X16:
+               case V4L2_MBUS_FMT_UYVY8_2X8:
+               case V4L2_MBUS_FMT_Y8_1X8:
+                       RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+                       SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+                       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
+                       break;
+
+               default:
+                       RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+                       RESETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+                       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
+                       break;
+               }
+
+       case IPIPEIF_SDRAM_YUV:
+               /* Set clock divider */
+               if (params.clock_select == IPIPEIF_SDRAM_CLK) {
+                       val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CLKDIV);
+                       val |= (params.if_5_1.clk_div.m - 1) <<
+                               IPIPEIF_CLKDIV_M_SHIFT;
+                       val |= (params.if_5_1.clk_div.n - 1);
+                       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CLKDIV);
+               }
+               break;
+
+       case IPIPEIF_CCDC:
+       case IPIPEIF_CCDC_DARKFM:
+               /* set DPC */
+               ipipeif_config_dpc(ipipeif_base_addr, &params.if_5_1.dpc);
+
+               /* Set DF gain & threshold control */
+               val = 0;
+               if (params.if_5_1.df_gain_en) {
+                       val = params.if_5_1.df_gain_thr &
+                               IPIPEIF_DF_GAIN_THR_MASK;
+                       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGTH);
+                       val = (params.if_5_1.df_gain_en & 1) <<
+                               IPIPEIF_DF_GAIN_EN_SHIFT;
+                       val |= params.if_5_1.df_gain &
+                               IPIPEIF_DF_GAIN_MASK;
+               }
+               ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGVL);
+               /* configure CFG2 */
+               val = VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_HDPOL_SHIFT;
+               val |= VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_VDPOL_SHIFT;
+
+               switch (isif_port_if) {
+               case V4L2_MBUS_FMT_YUYV8_1X16:
+               case V4L2_MBUS_FMT_YUYV10_1X20:
+                       RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+                       SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+                       break;
+
+               case V4L2_MBUS_FMT_YUYV8_2X8:
+               case V4L2_MBUS_FMT_UYVY8_2X8:
+               case V4L2_MBUS_FMT_Y8_1X8:
+               case V4L2_MBUS_FMT_YUYV10_2X10:
+                       SETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+                       SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+                       val |= IPIPEIF_CBCR_Y << IPIPEIF_CFG2_YUV8P_SHIFT;
+                       break;
+
+               default:
+                       /* Bayer */
+                       ipipeif_write(params.if_5_1.clip, ipipeif_base_addr,
+                               IPIPEIF_OCLIP);
+               }
+               ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+ipipeif_set_config(struct v4l2_subdev *sd, struct ipipeif_params *config)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct device *dev = ipipeif->subdev.v4l2_dev->dev;
+
+       if (!config) {
+               dev_err(dev, "Invalid configuration pointer\n");
+               return -EINVAL;
+       }
+
+       ipipeif->config.clock_select = config->clock_select;
+       ipipeif->config.ppln = config->ppln;
+       ipipeif->config.lpfr = config->lpfr;
+       ipipeif->config.rsz = config->rsz;
+       ipipeif->config.decimation = config->decimation;
+       if (ipipeif->config.decimation &&
+          (ipipeif->config.rsz < IPIPEIF_RSZ_MIN ||
+           ipipeif->config.rsz > IPIPEIF_RSZ_MAX)) {
+               dev_err(dev, "rsz range is %d to %d\n",
+                       IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
+               return -EINVAL;
+       }
+
+       ipipeif->config.avg_filter = config->avg_filter;
+
+       ipipeif->config.if_5_1.df_gain_thr = config->if_5_1.df_gain_thr;
+       ipipeif->config.if_5_1.df_gain = config->if_5_1.df_gain;
+       ipipeif->config.if_5_1.df_gain_en = config->if_5_1.df_gain_en;
+
+       ipipeif->config.if_5_1.rsz_start = config->if_5_1.rsz_start;
+       ipipeif->config.if_5_1.align_sync = config->if_5_1.align_sync;
+       ipipeif->config.if_5_1.clip = config->if_5_1.clip;
+
+       ipipeif->config.if_5_1.dpc.en = config->if_5_1.dpc.en;
+       ipipeif->config.if_5_1.dpc.thr = config->if_5_1.dpc.thr;
+
+       ipipeif->config.if_5_1.clk_div.m = config->if_5_1.clk_div.m;
+       ipipeif->config.if_5_1.clk_div.n = config->if_5_1.clk_div.n;
+
+       return 0;
+}
+
+static int
+ipipeif_get_config(struct v4l2_subdev *sd, void __user *arg)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct ipipeif_params *config = (struct ipipeif_params *)arg;
+       struct device *dev = ipipeif->subdev.v4l2_dev->dev;
+
+       if (!arg) {
+               dev_err(dev, "Invalid configuration pointer\n");
+               return -EINVAL;
+       }
+
+       config->clock_select = ipipeif->config.clock_select;
+       config->ppln = ipipeif->config.ppln;
+       config->lpfr = ipipeif->config.lpfr;
+       config->rsz = ipipeif->config.rsz;
+       config->decimation = ipipeif->config.decimation;
+       config->avg_filter = ipipeif->config.avg_filter;
+
+       config->if_5_1.df_gain_thr = ipipeif->config.if_5_1.df_gain_thr;
+       config->if_5_1.df_gain = ipipeif->config.if_5_1.df_gain;
+       config->if_5_1.df_gain_en = ipipeif->config.if_5_1.df_gain_en;
+
+       config->if_5_1.rsz_start = ipipeif->config.if_5_1.rsz_start;
+       config->if_5_1.align_sync = ipipeif->config.if_5_1.align_sync;
+       config->if_5_1.clip = ipipeif->config.if_5_1.clip;
+
+       config->if_5_1.dpc.en = ipipeif->config.if_5_1.dpc.en;
+       config->if_5_1.dpc.thr = ipipeif->config.if_5_1.dpc.thr;
+
+       config->if_5_1.clk_div.m = ipipeif->config.if_5_1.clk_div.m;
+       config->if_5_1.clk_div.n = ipipeif->config.if_5_1.clk_div.n;
+
+       return 0;
+}
+
+/*
+ * ipipeif_ioctl() - Handle ipipeif module private ioctl's
+ * @sd: pointer to v4l2 subdev structure
+ * @cmd: configuration command
+ * @arg: configuration argument
+ */
+static long ipipeif_ioctl(struct v4l2_subdev *sd,
+                         unsigned int cmd, void *arg)
+{
+       struct ipipeif_params *config = (struct ipipeif_params *)arg;
+       int ret = -ENOIOCTLCMD;
+
+       switch (cmd) {
+       case VIDIOC_VPFE_IPIPEIF_S_CONFIG:
+               ret = ipipeif_set_config(sd, config);
+               break;
+
+       case VIDIOC_VPFE_IPIPEIF_G_CONFIG:
+               ret = ipipeif_get_config(sd, arg);
+               break;
+       }
+       return ret;
+}
+
+/*
+ * ipipeif_s_ctrl() - Handle set control subdev method
+ * @ctrl: pointer to v4l2 control structure
+ */
+static int ipipeif_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vpfe_ipipeif_device *ipipeif =
+               container_of(ctrl->handler, struct vpfe_ipipeif_device, ctrls);
+
+       switch (ctrl->id) {
+       case VPFE_CID_DPCM_PREDICTOR:
+               ipipeif->dpcm_predictor = ctrl->val;
+               break;
+
+       case V4L2_CID_GAIN:
+               ipipeif->gain = ctrl->val;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+#define ENABLE_IPIPEIF         0x1
+
+void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev)
+{
+       struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
+       void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
+       unsigned char val;
+
+       if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
+               return;
+
+       do {
+               val = ipipeif_read(ipipeif_base_addr, IPIPEIF_ENABLE);
+       } while (val & 0x1);
+
+       ipipeif_write(ENABLE_IPIPEIF, ipipeif_base_addr, IPIPEIF_ENABLE);
+}
+
+/*
+ * ipipeif_set_stream() - Enable/Disable streaming on ipipeif subdev
+ * @sd: pointer to v4l2 subdev structure
+ * @enable: 1 == Enable, 0 == Disable
+ */
+static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
+       int ret = 0;
+
+       if (!enable)
+               return ret;
+
+       ret = ipipeif_hw_setup(sd);
+       if (!ret)
+               vpfe_ipipeif_enable(vpfe_dev);
+
+       return ret;
+}
+
+/*
+ * ipipeif_enum_mbus_code() - Handle pixel format enumeration
+ * @sd: pointer to v4l2 subdev structure
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                       struct v4l2_subdev_mbus_code_enum *code)
+{
+       switch (code->pad) {
+       case IPIPEIF_PAD_SINK:
+               if (code->index >= ARRAY_SIZE(ipipeif_input_fmts))
+                       return -EINVAL;
+
+               code->code = ipipeif_input_fmts[code->index];
+               break;
+
+       case IPIPEIF_PAD_SOURCE:
+               if (code->index >= ARRAY_SIZE(ipipeif_output_fmts))
+                       return -EINVAL;
+
+               code->code = ipipeif_output_fmts[code->index];
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * ipipeif_get_format() - Handle get format by pads subdev method
+ * @sd: pointer to v4l2 subdev structure
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ */
+static int
+ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+               struct v4l2_subdev_format *fmt)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               fmt->format = ipipeif->formats[fmt->pad];
+       else
+               fmt->format = *(v4l2_subdev_get_try_format(fh, fmt->pad));
+
+       return 0;
+}
+
+#define MIN_OUT_WIDTH                  32
+#define MIN_OUT_HEIGHT                 32
+
+/*
+ * ipipeif_try_format() - Handle try format by pad subdev method
+ * @ipipeif: VPFE ipipeif device.
+ * @fh: V4L2 subdev file handle.
+ * @pad: pad num.
+ * @fmt: pointer to v4l2 format structure.
+ * @which : wanted subdev format
+ */
+static void
+ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif,
+                  struct v4l2_subdev_fh *fh, unsigned int pad,
+                  struct v4l2_mbus_framefmt *fmt,
+                  enum v4l2_subdev_format_whence which)
+{
+       unsigned int max_out_height;
+       unsigned int max_out_width;
+       unsigned int i;
+
+       max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
+       max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+
+       if (pad == IPIPEIF_PAD_SINK) {
+               for (i = 0; i < ARRAY_SIZE(ipipeif_input_fmts); i++)
+                       if (fmt->code == ipipeif_input_fmts[i])
+                               break;
+
+               /* If not found, use SBGGR10 as default */
+               if (i >= ARRAY_SIZE(ipipeif_input_fmts))
+                       fmt->code = V4L2_MBUS_FMT_SGRBG12_1X12;
+       } else if (pad == IPIPEIF_PAD_SOURCE) {
+               for (i = 0; i < ARRAY_SIZE(ipipeif_output_fmts); i++)
+                       if (fmt->code == ipipeif_output_fmts[i])
+                               break;
+
+               /* If not found, use UYVY as default */
+               if (i >= ARRAY_SIZE(ipipeif_output_fmts))
+                       fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
+       }
+
+       fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width);
+       fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height);
+}
+
+static int
+ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                    struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       ipipeif_try_format(ipipeif, fh, fse->pad, &format,
+                          V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       ipipeif_try_format(ipipeif, fh, fse->pad, &format,
+                          V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * __ipipeif_get_format() - helper function for getting ipipeif format
+ * @ipipeif: pointer to ipipeif private structure.
+ * @pad: pad number.
+ * @fh: V4L2 subdev file handle.
+ * @which: wanted subdev format.
+ *
+ */
+static struct v4l2_mbus_framefmt *
+__ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif,
+                      struct v4l2_subdev_fh *fh, unsigned int pad,
+                      enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+
+       return &ipipeif->formats[pad];
+}
+
+/*
+ * ipipeif_set_format() - Handle set format by pads subdev method
+ * @sd: pointer to v4l2 subdev structure
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int
+ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+               struct v4l2_subdev_format *fmt)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       ipipeif_try_format(ipipeif, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       if (fmt->pad == IPIPEIF_PAD_SINK &&
+           ipipeif->input != IPIPEIF_INPUT_NONE)
+               ipipeif->formats[fmt->pad] = fmt->format;
+       else if (fmt->pad == IPIPEIF_PAD_SOURCE &&
+                ipipeif->output != IPIPEIF_OUTPUT_NONE)
+               ipipeif->formats[fmt->pad] = fmt->format;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif)
+{
+#define WIDTH_I                        640
+#define HEIGHT_I               480
+
+       const struct ipipeif_params ipipeif_defaults = {
+               .clock_select = IPIPEIF_SDRAM_CLK,
+               .ppln = WIDTH_I + 8,
+               .lpfr = HEIGHT_I + 10,
+               .rsz = 16,      /* resize ratio 16/rsz */
+               .decimation = IPIPEIF_DECIMATION_OFF,
+               .avg_filter = IPIPEIF_AVG_OFF,
+               .if_5_1 = {
+                       .clk_div = {
+                               .m = 1, /* clock = sdram clock * (m/n) */
+                               .n = 6
+                       },
+                       .clip = 4095,
+               },
+       };
+       memset(&ipipeif->config, 0, sizeof(struct ipipeif_params));
+       memcpy(&ipipeif->config, &ipipeif_defaults,
+              sizeof(struct ipipeif_params));
+}
+
+/*
+ * ipipeif_init_formats() - Initialize formats on all pads
+ * @sd: VPFE ipipeif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int
+ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_subdev_format format;
+
+       memset(&format, 0, sizeof(format));
+       format.pad = IPIPEIF_PAD_SINK;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+       format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
+       format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+       ipipeif_set_format(sd, fh, &format);
+
+       memset(&format, 0, sizeof(format));
+       format.pad = IPIPEIF_PAD_SOURCE;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
+       format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
+       format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+       ipipeif_set_format(sd, fh, &format);
+
+       ipipeif_set_default_config(ipipeif);
+
+       return 0;
+}
+
+/*
+ * ipipeif_video_in_queue() - ipipeif video in queue
+ * @vpfe_dev: vpfe device pointer
+ * @addr: buffer address
+ */
+static int
+ipipeif_video_in_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
+{
+       struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
+       void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
+       unsigned int adofs;
+       u32 val;
+
+       if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
+               return -EINVAL;
+
+       switch (ipipeif->formats[IPIPEIF_PAD_SINK].code) {
+       case V4L2_MBUS_FMT_Y8_1X8:
+       case V4L2_MBUS_FMT_UV8_1X8:
+       case V4L2_MBUS_FMT_YDYUYDYV8_1X16:
+               adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width;
+               break;
+
+       default:
+               adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width << 1;
+               break;
+       }
+
+       /* adjust the line len to be a multiple of 32 */
+       adofs += 31;
+       adofs &= ~0x1f;
+       val = (adofs >> 5) & IPIPEIF_ADOFS_LSB_MASK;
+       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADOFS);
+
+       /* lower sixteen bit */
+       val = (addr >> IPIPEIF_ADDRL_SHIFT) & IPIPEIF_ADDRL_MASK;
+       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRL);
+
+       /* upper next seven bit */
+       val = (addr >> IPIPEIF_ADDRU_SHIFT) & IPIPEIF_ADDRU_MASK;
+       ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRU);
+
+       return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops ipipeif_v4l2_core_ops = {
+       .ioctl = ipipeif_ioctl,
+};
+
+static const struct v4l2_ctrl_ops ipipeif_ctrl_ops = {
+       .s_ctrl = ipipeif_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vpfe_ipipeif_dpcm_pred = {
+       .ops = &ipipeif_ctrl_ops,
+       .id = VPFE_CID_DPCM_PREDICTOR,
+       .name = "DPCM Predictor",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = 1,
+       .step = 1,
+       .def = 0,
+};
+
+/* subdev file operations */
+static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = {
+       .open = ipipeif_init_formats,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = {
+       .s_stream = ipipeif_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = {
+       .enum_mbus_code = ipipeif_enum_mbus_code,
+       .enum_frame_size = ipipeif_enum_frame_size,
+       .get_fmt = ipipeif_get_format,
+       .set_fmt = ipipeif_set_format,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops ipipeif_v4l2_ops = {
+       .core = &ipipeif_v4l2_core_ops,
+       .video = &ipipeif_v4l2_video_ops,
+       .pad = &ipipeif_v4l2_pad_ops,
+};
+
+static const struct vpfe_video_operations video_in_ops = {
+       .queue = ipipeif_video_in_queue,
+};
+
+static int
+ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local,
+               const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct vpfe_device *vpfe = to_vpfe_device(ipipeif);
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case IPIPEIF_PAD_SINK | MEDIA_ENT_T_DEVNODE:
+               /* Single shot mode */
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       ipipeif->input = IPIPEIF_INPUT_NONE;
+                       break;
+               }
+               ipipeif->input = IPIPEIF_INPUT_MEMORY;
+               break;
+
+       case IPIPEIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* read from isif */
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       ipipeif->input = IPIPEIF_INPUT_NONE;
+                       break;
+               }
+               if (ipipeif->input != IPIPEIF_INPUT_NONE)
+                       return -EBUSY;
+
+               ipipeif->input = IPIPEIF_INPUT_ISIF;
+               break;
+
+       case IPIPEIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       ipipeif->output = IPIPEIF_OUTPUT_NONE;
+                       break;
+               }
+               if (remote->entity == &vpfe->vpfe_ipipe.subdev.entity)
+                       /* connencted to ipipe */
+                       ipipeif->output = IPIPEIF_OUTPUT_IPIPE;
+               else if (remote->entity == &vpfe->vpfe_resizer.
+                       crop_resizer.subdev.entity)
+                       /* connected to resizer */
+                       ipipeif->output = IPIPEIF_OUTPUT_RESIZER;
+               else
+                       return -EINVAL;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct media_entity_operations ipipeif_media_ops = {
+       .link_setup = ipipeif_link_setup,
+};
+
+/*
+ * vpfe_ipipeif_unregister_entities() - Unregister entity
+ * @ipipeif - pointer to ipipeif subdevice structure.
+ */
+void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif)
+{
+       /* unregister video device */
+       vpfe_video_unregister(&ipipeif->video_in);
+
+       /* cleanup entity */
+       media_entity_cleanup(&ipipeif->subdev.entity);
+       /* unregister subdev */
+       v4l2_device_unregister_subdev(&ipipeif->subdev);
+}
+
+int
+vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
+                              struct v4l2_device *vdev)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
+       unsigned int flags;
+       int ret;
+
+       /* Register the subdev */
+       ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev);
+       if (ret < 0)
+               return ret;
+
+       ret = vpfe_video_register(&ipipeif->video_in, vdev);
+       if (ret) {
+               pr_err("Failed to register ipipeif video-in device\n");
+               goto fail;
+       }
+       ipipeif->video_in.vpfe_dev = vpfe_dev;
+
+       flags = 0;
+       ret = media_entity_create_link(&ipipeif->video_in.video_dev.entity, 0,
+                                       &ipipeif->subdev.entity, 0, flags);
+       if (ret < 0)
+               goto fail;
+
+       return 0;
+fail:
+       v4l2_device_unregister_subdev(&ipipeif->subdev);
+
+       return ret;
+}
+
+#define IPIPEIF_GAIN_HIGH              0x3ff
+#define IPIPEIF_DEFAULT_GAIN           0x200
+
+int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif,
+                     struct platform_device *pdev)
+{
+       struct v4l2_subdev *sd = &ipipeif->subdev;
+       struct media_pad *pads = &ipipeif->pads[0];
+       struct media_entity *me = &sd->entity;
+       static resource_size_t  res_len;
+       struct resource *res;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       if (!res)
+               return -ENOENT;
+
+       res_len = resource_size(res);
+       res = request_mem_region(res->start, res_len, res->name);
+       if (!res)
+               return -EBUSY;
+
+       ipipeif->ipipeif_base_addr = ioremap_nocache(res->start, res_len);
+       if (!ipipeif->ipipeif_base_addr) {
+               ret =  -EBUSY;
+               goto fail;
+       }
+
+       v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
+
+       sd->internal_ops = &ipipeif_v4l2_internal_ops;
+       strlcpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
+
+       v4l2_set_subdevdata(sd, ipipeif);
+
+       sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+       pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[IPIPEIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+       ipipeif->input = IPIPEIF_INPUT_NONE;
+       ipipeif->output = IPIPEIF_OUTPUT_NONE;
+       me->ops = &ipipeif_media_ops;
+
+       ret = media_entity_init(me, IPIPEIF_NUM_PADS, pads, 0);
+       if (ret)
+               goto fail;
+
+       v4l2_ctrl_handler_init(&ipipeif->ctrls, 2);
+       v4l2_ctrl_new_std(&ipipeif->ctrls, &ipipeif_ctrl_ops,
+                         V4L2_CID_GAIN, 0,
+                         IPIPEIF_GAIN_HIGH, 1, IPIPEIF_DEFAULT_GAIN);
+       v4l2_ctrl_new_custom(&ipipeif->ctrls, &vpfe_ipipeif_dpcm_pred, NULL);
+       v4l2_ctrl_handler_setup(&ipipeif->ctrls);
+       sd->ctrl_handler = &ipipeif->ctrls;
+
+       ipipeif->video_in.ops = &video_in_ops;
+       ipipeif->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       ret = vpfe_video_init(&ipipeif->video_in, "IPIPEIF");
+       if (ret) {
+               pr_err("Failed to init IPIPEIF video-in device\n");
+               goto fail;
+       }
+       ipipeif_set_default_config(ipipeif);
+       return 0;
+fail:
+       release_mem_region(res->start, res_len);
+       return ret;
+}
+
+void
+vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif,
+                    struct platform_device *pdev)
+{
+       struct resource *res;
+
+       v4l2_ctrl_handler_free(&ipipeif->ctrls);
+       iounmap(ipipeif->ipipeif_base_addr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       if (res)
+               release_mem_region(res->start,
+                                       res->end - res->start + 1);
+
+}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h
new file mode 100644 (file)
index 0000000..608701f
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_IPIPEIF_H
+#define _DAVINCI_VPFE_DM365_IPIPEIF_H
+
+#include <linux/platform_device.h>
+
+#include <media/davinci/vpss.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "dm365_ipipeif_user.h"
+#include "vpfe_video.h"
+
+/* IPIPE base specific types */
+enum ipipeif_data_shift {
+       IPIPEIF_BITS15_2 = 0,
+       IPIPEIF_BITS14_1 = 1,
+       IPIPEIF_BITS13_0 = 2,
+       IPIPEIF_BITS12_0 = 3,
+       IPIPEIF_BITS11_0 = 4,
+       IPIPEIF_BITS10_0 = 5,
+       IPIPEIF_BITS9_0 = 6,
+};
+
+enum ipipeif_clkdiv {
+       IPIPEIF_DIVIDE_HALF = 0,
+       IPIPEIF_DIVIDE_THIRD = 1,
+       IPIPEIF_DIVIDE_FOURTH = 2,
+       IPIPEIF_DIVIDE_FIFTH = 3,
+       IPIPEIF_DIVIDE_SIXTH = 4,
+       IPIPEIF_DIVIDE_EIGHTH = 5,
+       IPIPEIF_DIVIDE_SIXTEENTH = 6,
+       IPIPEIF_DIVIDE_THIRTY = 7,
+};
+
+enum ipipeif_pack_mode  {
+       IPIPEIF_PACK_16_BIT = 0,
+       IPIPEIF_PACK_8_BIT = 1,
+};
+
+enum ipipeif_5_1_pack_mode  {
+       IPIPEIF_5_1_PACK_16_BIT = 0,
+       IPIPEIF_5_1_PACK_8_BIT = 1,
+       IPIPEIF_5_1_PACK_8_BIT_A_LAW = 2,
+       IPIPEIF_5_1_PACK_12_BIT = 3
+};
+
+enum  ipipeif_input_source {
+       IPIPEIF_CCDC = 0,
+       IPIPEIF_SDRAM_RAW = 1,
+       IPIPEIF_CCDC_DARKFM = 2,
+       IPIPEIF_SDRAM_YUV = 3,
+};
+
+enum ipipeif_ialaw {
+       IPIPEIF_ALAW_OFF = 0,
+       IPIPEIF_ALAW_ON = 1,
+};
+
+enum  ipipeif_input_src1 {
+       IPIPEIF_SRC1_PARALLEL_PORT = 0,
+       IPIPEIF_SRC1_SDRAM_RAW = 1,
+       IPIPEIF_SRC1_ISIF_DARKFM = 2,
+       IPIPEIF_SRC1_SDRAM_YUV = 3,
+};
+
+enum ipipeif_dfs_dir {
+       IPIPEIF_PORT_MINUS_SDRAM = 0,
+       IPIPEIF_SDRAM_MINUS_PORT = 1,
+};
+
+enum ipipeif_chroma_phase {
+       IPIPEIF_CBCR_Y = 0,
+       IPIPEIF_Y_CBCR = 1,
+};
+
+enum ipipeif_dpcm_type {
+       IPIPEIF_DPCM_8BIT_10BIT = 0,
+       IPIPEIF_DPCM_8BIT_12BIT = 1,
+};
+
+/* data shift for IPIPE 5.1 */
+enum ipipeif_5_1_data_shift {
+       IPIPEIF_5_1_BITS11_0 = 0,
+       IPIPEIF_5_1_BITS10_0 = 1,
+       IPIPEIF_5_1_BITS9_0 = 2,
+       IPIPEIF_5_1_BITS8_0 = 3,
+       IPIPEIF_5_1_BITS7_0 = 4,
+       IPIPEIF_5_1_BITS15_4 = 5,
+};
+
+#define IPIPEIF_PAD_SINK      0
+#define IPIPEIF_PAD_SOURCE    1
+
+#define IPIPEIF_NUM_PADS       2
+
+enum ipipeif_input_entity {
+       IPIPEIF_INPUT_NONE = 0,
+       IPIPEIF_INPUT_ISIF = 1,
+       IPIPEIF_INPUT_MEMORY = 2,
+};
+
+enum ipipeif_output_entity {
+       IPIPEIF_OUTPUT_NONE = 0,
+       IPIPEIF_OUTPUT_IPIPE = 1,
+       IPIPEIF_OUTPUT_RESIZER = 2,
+};
+
+struct vpfe_ipipeif_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[IPIPEIF_NUM_PADS];
+       struct v4l2_mbus_framefmt formats[IPIPEIF_NUM_PADS];
+       enum ipipeif_input_entity input;
+       unsigned int output;
+       struct vpfe_video_device video_in;
+       struct v4l2_ctrl_handler ctrls;
+       void *__iomem ipipeif_base_addr;
+       struct ipipeif_params config;
+       int dpcm_predictor;
+       int gain;
+};
+
+/* IPIPEIF Register Offsets from the base address */
+#define IPIPEIF_ENABLE                 0x00
+#define IPIPEIF_CFG1                   0x04
+#define IPIPEIF_PPLN                   0x08
+#define IPIPEIF_LPFR                   0x0c
+#define IPIPEIF_HNUM                   0x10
+#define IPIPEIF_VNUM                   0x14
+#define IPIPEIF_ADDRU                  0x18
+#define IPIPEIF_ADDRL                  0x1c
+#define IPIPEIF_ADOFS                  0x20
+#define IPIPEIF_RSZ                    0x24
+#define IPIPEIF_GAIN                   0x28
+
+/* Below registers are available only on IPIPE 5.1 */
+#define IPIPEIF_DPCM                   0x2c
+#define IPIPEIF_CFG2                   0x30
+#define IPIPEIF_INIRSZ                 0x34
+#define IPIPEIF_OCLIP                  0x38
+#define IPIPEIF_DTUDF                  0x3c
+#define IPIPEIF_CLKDIV                 0x40
+#define IPIPEIF_DPC1                   0x44
+#define IPIPEIF_DPC2                   0x48
+#define IPIPEIF_DFSGVL                 0x4c
+#define IPIPEIF_DFSGTH                 0x50
+#define IPIPEIF_RSZ3A                  0x54
+#define IPIPEIF_INIRSZ3A               0x58
+#define IPIPEIF_RSZ_MIN                        16
+#define IPIPEIF_RSZ_MAX                        112
+#define IPIPEIF_RSZ_CONST              16
+#define SETBIT(reg, bit)   (reg = ((reg) | ((0x00000001)<<(bit))))
+#define RESETBIT(reg, bit) (reg = ((reg) & (~(0x00000001<<(bit)))))
+
+#define IPIPEIF_ADOFS_LSB_MASK         0x1ff
+#define IPIPEIF_ADOFS_LSB_SHIFT                5
+#define IPIPEIF_ADOFS_MSB_MASK         0x200
+#define IPIPEIF_ADDRU_MASK             0x7ff
+#define IPIPEIF_ADDRL_SHIFT            5
+#define IPIPEIF_ADDRL_MASK             0xffff
+#define IPIPEIF_ADDRU_SHIFT            21
+#define IPIPEIF_ADDRMSB_SHIFT          31
+#define IPIPEIF_ADDRMSB_LEFT_SHIFT     10
+
+/* CFG1 Masks and shifts */
+#define ONESHOT_SHIFT                  0
+#define DECIM_SHIFT                    1
+#define INPSRC_SHIFT                   2
+#define CLKDIV_SHIFT                   4
+#define AVGFILT_SHIFT                  7
+#define PACK8IN_SHIFT                  8
+#define IALAW_SHIFT                    9
+#define CLKSEL_SHIFT                   10
+#define DATASFT_SHIFT                  11
+#define INPSRC1_SHIFT                  14
+
+/* DPC2 */
+#define IPIPEIF_DPC2_EN_SHIFT          12
+#define IPIPEIF_DPC2_THR_MASK          0xfff
+/* Applicable for IPIPE 5.1 */
+#define IPIPEIF_DF_GAIN_EN_SHIFT       10
+#define IPIPEIF_DF_GAIN_MASK           0x3ff
+#define IPIPEIF_DF_GAIN_THR_MASK       0xfff
+/* DPCM */
+#define IPIPEIF_DPCM_BITS_SHIFT                2
+#define IPIPEIF_DPCM_PRED_SHIFT                1
+/* CFG2 */
+#define IPIPEIF_CFG2_HDPOL_SHIFT       1
+#define IPIPEIF_CFG2_VDPOL_SHIFT       2
+#define IPIPEIF_CFG2_YUV8_SHIFT                6
+#define IPIPEIF_CFG2_YUV16_SHIFT       3
+#define IPIPEIF_CFG2_YUV8P_SHIFT       7
+
+/* INIRSZ */
+#define IPIPEIF_INIRSZ_ALNSYNC_SHIFT   13
+#define IPIPEIF_INIRSZ_MASK            0x1fff
+
+/* CLKDIV */
+#define IPIPEIF_CLKDIV_M_SHIFT         8
+
+void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev);
+void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif);
+int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev);
+int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev);
+void vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif,
+                         struct platform_device *pdev);
+int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif,
+                     struct platform_device *pdev);
+int vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
+                                  struct v4l2_device *vdev);
+void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif);
+
+#endif         /* _DAVINCI_VPFE_DM365_IPIPEIF_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h b/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h
new file mode 100644 (file)
index 0000000..e2a69b5
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_IPIPEIF_USER_H
+#define _DAVINCI_VPFE_DM365_IPIPEIF_USER_H
+
+/* clockdiv for IPIPE 5.1 */
+struct ipipeif_5_1_clkdiv {
+       unsigned char m;
+       unsigned char n;
+};
+
+enum ipipeif_decimation {
+       IPIPEIF_DECIMATION_OFF,
+       IPIPEIF_DECIMATION_ON
+};
+
+/* DPC at the if for IPIPE 5.1 */
+struct ipipeif_dpc {
+       /* 0 - disable, 1 - enable */
+       unsigned char en;
+       /* threshold */
+       unsigned short thr;
+};
+
+enum ipipeif_clock {
+       IPIPEIF_PIXCEL_CLK,
+       IPIPEIF_SDRAM_CLK
+};
+
+enum  ipipeif_avg_filter {
+       IPIPEIF_AVG_OFF,
+       IPIPEIF_AVG_ON
+};
+
+struct ipipeif_5_1 {
+       struct ipipeif_5_1_clkdiv clk_div;
+       /* Defect pixel correction */
+       struct ipipeif_dpc dpc;
+       /* clipped to this value */
+       unsigned short clip;
+       /* Align HSync and VSync to rsz_start */
+       unsigned char align_sync;
+       /* resizer start position */
+       unsigned int rsz_start;
+       /* DF gain enable */
+       unsigned char df_gain_en;
+       /* DF gain value */
+       unsigned short df_gain;
+       /* DF gain threshold value */
+       unsigned short df_gain_thr;
+};
+
+struct ipipeif_params {
+       enum ipipeif_clock clock_select;
+       unsigned int ppln;
+       unsigned int lpfr;
+       unsigned char rsz;
+       enum ipipeif_decimation decimation;
+       enum ipipeif_avg_filter avg_filter;
+       /* IPIPE 5.1 */
+       struct ipipeif_5_1 if_5_1;
+};
+
+/*
+ * Private IOCTL
+ * VIDIOC_VPFE_IPIPEIF_S_CONFIG: Set IPIEIF configuration
+ * VIDIOC_VPFE_IPIPEIF_G_CONFIG: Get IPIEIF configuration
+ */
+#define VIDIOC_VPFE_IPIPEIF_S_CONFIG \
+       _IOWR('I', BASE_VIDIOC_PRIVATE + 1, struct ipipeif_params)
+#define VIDIOC_VPFE_IPIPEIF_G_CONFIG \
+       _IOWR('I', BASE_VIDIOC_PRIVATE + 2, struct ipipeif_params)
+
+#endif         /* _DAVINCI_VPFE_DM365_IPIPEIF_USER_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
new file mode 100644 (file)
index 0000000..ebeea72
--- /dev/null
@@ -0,0 +1,2104 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#include "dm365_isif.h"
+#include "vpfe_mc_capture.h"
+
+#define MAX_WIDTH      4096
+#define MAX_HEIGHT     4096
+
+static const unsigned int isif_fmts[] = {
+       V4L2_MBUS_FMT_YUYV8_2X8,
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_YUYV8_1X16,
+       V4L2_MBUS_FMT_YUYV10_1X20,
+       V4L2_MBUS_FMT_SGRBG12_1X12,
+       V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
+       V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+};
+
+#define ISIF_COLPTN_R_Ye       0x0
+#define ISIF_COLPTN_Gr_Cy      0x1
+#define ISIF_COLPTN_Gb_G       0x2
+#define ISIF_COLPTN_B_Mg       0x3
+
+#define ISIF_CCOLP_CP01_0      0
+#define ISIF_CCOLP_CP03_2      2
+#define ISIF_CCOLP_CP05_4      4
+#define ISIF_CCOLP_CP07_6      6
+#define ISIF_CCOLP_CP11_0      8
+#define ISIF_CCOLP_CP13_2      10
+#define ISIF_CCOLP_CP15_4      12
+#define ISIF_CCOLP_CP17_6      14
+
+static const u32 isif_sgrbg_pattern =
+       ISIF_COLPTN_Gr_Cy <<  ISIF_CCOLP_CP01_0 |
+       ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP03_2 |
+       ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP05_4 |
+       ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP07_6 |
+       ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP11_0 |
+       ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP13_2 |
+       ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP15_4 |
+       ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP17_6;
+
+static const u32 isif_srggb_pattern =
+       ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP01_0 |
+       ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP03_2 |
+       ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP05_4 |
+       ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP07_6 |
+       ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP11_0 |
+       ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP13_2 |
+       ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP15_4 |
+       ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP17_6;
+
+static inline u32 isif_read(void *__iomem base_addr, u32 offset)
+{
+       return readl(base_addr + offset);
+}
+
+static inline void isif_write(void *__iomem base_addr, u32 val, u32 offset)
+{
+       writel(val, base_addr + offset);
+}
+
+static inline u32 isif_merge(void *__iomem base_addr, u32 mask, u32 val,
+                            u32 offset)
+{
+       u32 new_val = (isif_read(base_addr, offset) & ~mask) | (val & mask);
+
+       isif_write(base_addr, new_val, offset);
+
+       return new_val;
+}
+
+static void isif_enable_output_to_sdram(struct vpfe_isif_device *isif, int en)
+{
+       isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_WEN_MASK,
+                  en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN);
+}
+
+static inline void
+isif_regw_lin_tbl(struct vpfe_isif_device *isif, u32 val, u32 offset, int i)
+{
+       if (!i)
+               writel(val, isif->isif_cfg.linear_tbl0_addr + offset);
+       else
+               writel(val, isif->isif_cfg.linear_tbl1_addr + offset);
+}
+
+static void isif_disable_all_modules(struct vpfe_isif_device *isif)
+{
+       /* disable BC */
+       isif_write(isif->isif_cfg.base_addr, 0, CLAMPCFG);
+       /* disable vdfc */
+       isif_write(isif->isif_cfg.base_addr, 0, DFCCTL);
+       /* disable CSC */
+       isif_write(isif->isif_cfg.base_addr, 0, CSCCTL);
+       /* disable linearization */
+       isif_write(isif->isif_cfg.base_addr, 0, LINCFG0);
+}
+
+static void isif_enable(struct vpfe_isif_device *isif, int en)
+{
+       if (!en)
+               /* Before disable isif, disable all ISIF modules */
+               isif_disable_all_modules(isif);
+
+       /*
+        * wait for next VD. Assume lowest scan rate is 12 Hz. So
+        * 100 msec delay is good enough
+        */
+       msleep(100);
+       isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_VDHDEN_MASK,
+                  en, SYNCEN);
+}
+
+/*
+ * ISIF helper functions
+ */
+
+#define DM365_ISIF_MDFS_OFFSET         15
+#define DM365_ISIF_MDFS_MASK           0x1
+
+/* get field id in isif hardware */
+enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev)
+{
+       struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif;
+       u32 field_status;
+
+       field_status = isif_read(isif->isif_cfg.base_addr, MODESET);
+       field_status = (field_status >> DM365_ISIF_MDFS_OFFSET) &
+                       DM365_ISIF_MDFS_MASK;
+       return field_status;
+}
+
+static int
+isif_set_pixel_format(struct vpfe_isif_device *isif, unsigned int pixfmt)
+{
+       if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12) {
+               if (pixfmt == V4L2_PIX_FMT_SBGGR16)
+                       isif->isif_cfg.data_pack = ISIF_PACK_16BIT;
+               else if ((pixfmt == V4L2_PIX_FMT_SGRBG10DPCM8) ||
+                               (pixfmt == V4L2_PIX_FMT_SGRBG10ALAW8))
+                       isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
+               else
+                       return -EINVAL;
+
+               isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW;
+               isif->isif_cfg.bayer.v4l2_pix_fmt = pixfmt;
+       } else {
+               if (pixfmt == V4L2_PIX_FMT_YUYV)
+                       isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_YCBYCR;
+               else if (pixfmt == V4L2_PIX_FMT_UYVY)
+                       isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY;
+               else
+                       return -EINVAL;
+
+               isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
+               isif->isif_cfg.ycbcr.v4l2_pix_fmt = pixfmt;
+       }
+
+       return 0;
+}
+
+static int
+isif_set_frame_format(struct vpfe_isif_device *isif,
+                     enum isif_frmfmt frm_fmt)
+{
+       if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12)
+               isif->isif_cfg.bayer.frm_fmt = frm_fmt;
+       else
+               isif->isif_cfg.ycbcr.frm_fmt = frm_fmt;
+
+       return 0;
+}
+
+static int isif_set_image_window(struct vpfe_isif_device *isif)
+{
+       struct v4l2_rect *win = &isif->crop;
+
+       if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12) {
+               isif->isif_cfg.bayer.win.top = win->top;
+               isif->isif_cfg.bayer.win.left = win->left;
+               isif->isif_cfg.bayer.win.width = win->width;
+               isif->isif_cfg.bayer.win.height = win->height;
+               return 0;
+       }
+       isif->isif_cfg.ycbcr.win.top = win->top;
+       isif->isif_cfg.ycbcr.win.left = win->left;
+       isif->isif_cfg.ycbcr.win.width = win->width;
+       isif->isif_cfg.ycbcr.win.height = win->height;
+
+       return 0;
+}
+
+static int
+isif_set_buftype(struct vpfe_isif_device *isif, enum isif_buftype buf_type)
+{
+       if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12)
+               isif->isif_cfg.bayer.buf_type = buf_type;
+       else
+               isif->isif_cfg.ycbcr.buf_type = buf_type;
+
+       return 0;
+}
+
+/* configure format in isif hardware */
+static int
+isif_config_format(struct vpfe_device *vpfe_dev, unsigned int pad)
+{
+       struct vpfe_isif_device *vpfe_isif = &vpfe_dev->vpfe_isif;
+       enum isif_frmfmt frm_fmt = ISIF_FRMFMT_INTERLACED;
+       struct v4l2_pix_format format;
+       int ret = 0;
+
+       v4l2_fill_pix_format(&format, &vpfe_dev->vpfe_isif.formats[pad]);
+       mbus_to_pix(&vpfe_dev->vpfe_isif.formats[pad], &format);
+
+       if (isif_set_pixel_format(vpfe_isif, format.pixelformat) < 0) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                        "Failed to set pixel format in isif\n");
+               return -EINVAL;
+       }
+
+       /* call for s_crop will override these values */
+       vpfe_isif->crop.left = 0;
+       vpfe_isif->crop.top = 0;
+       vpfe_isif->crop.width = format.width;
+       vpfe_isif->crop.height = format.height;
+
+       /* configure the image window */
+       isif_set_image_window(vpfe_isif);
+
+       switch (vpfe_dev->vpfe_isif.formats[pad].field) {
+       case V4L2_FIELD_INTERLACED:
+               /* do nothing, since it is default */
+               ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_INTERLEAVED);
+               break;
+
+       case V4L2_FIELD_NONE:
+               frm_fmt = ISIF_FRMFMT_PROGRESSIVE;
+               /* buffer type only applicable for interlaced scan */
+               break;
+
+       case V4L2_FIELD_SEQ_TB:
+               ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_SEPARATED);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* set the frame format */
+       if (!ret)
+               ret = isif_set_frame_format(vpfe_isif, frm_fmt);
+
+       return ret;
+}
+
+/*
+ * isif_try_format() - Try video format on a pad
+ * @isif: VPFE isif device
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ */
+static void
+isif_try_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
+               struct v4l2_subdev_format *fmt)
+{
+       unsigned int width = fmt->format.width;
+       unsigned int height = fmt->format.height;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(isif_fmts); i++) {
+               if (fmt->format.code == isif_fmts[i])
+                       break;
+       }
+
+       /* If not found, use YUYV8_2x8 as default */
+       if (i >= ARRAY_SIZE(isif_fmts))
+               fmt->format.code = V4L2_MBUS_FMT_YUYV8_2X8;
+
+       /* Clamp the size. */
+       fmt->format.width = clamp_t(u32, width, 32, MAX_WIDTH);
+       fmt->format.height = clamp_t(u32, height, 32, MAX_HEIGHT);
+
+       /* The data formatter truncates the number of horizontal output
+        * pixels to a multiple of 16. To avoid clipping data, allow
+        * callers to request an output size bigger than the input size
+        * up to the nearest multiple of 16.
+        */
+       if (fmt->pad == ISIF_PAD_SOURCE)
+               fmt->format.width &= ~15;
+}
+
+/*
+ * vpfe_isif_buffer_isr() - isif module non-progressive buffer scheduling isr
+ * @isif: Pointer to isif subdevice.
+ */
+void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
+       struct vpfe_video_device *video = &isif->video_out;
+       enum v4l2_field field;
+       int fid;
+
+       if (!video->started)
+               return;
+
+       field = video->fmt.fmt.pix.field;
+
+       if (field == V4L2_FIELD_NONE) {
+               /* handle progressive frame capture */
+               if (video->cur_frm != video->next_frm)
+                       vpfe_video_process_buffer_complete(video);
+               return;
+       }
+
+       /* interlaced or TB capture check which field we
+        * are in hardware
+        */
+       fid = vpfe_isif_get_fid(vpfe_dev);
+
+       /* switch the software maintained field id */
+       video->field_id ^= 1;
+       if (fid == video->field_id) {
+               /* we are in-sync here,continue */
+               if (fid == 0) {
+                       /*
+                        * One frame is just being captured. If the
+                        * next frame is available, release the current
+                        * frame and move on
+                        */
+                       if (video->cur_frm != video->next_frm)
+                               vpfe_video_process_buffer_complete(video);
+                       /*
+                        * based on whether the two fields are stored
+                        * interleavely or separately in memory,
+                        * reconfigure the ISIF memory address
+                        */
+                       if (field == V4L2_FIELD_SEQ_TB)
+                               vpfe_video_schedule_bottom_field(video);
+                       return;
+               }
+               /*
+                * if one field is just being captured configure
+                * the next frame get the next frame from the
+                * empty queue if no frame is available hold on
+                * to the current buffer
+                */
+               spin_lock(&video->dma_queue_lock);
+               if (!list_empty(&video->dma_queue) &&
+               video->cur_frm == video->next_frm)
+                       vpfe_video_schedule_next_buffer(video);
+               spin_unlock(&video->dma_queue_lock);
+       } else if (fid == 0) {
+               /*
+                * out of sync. Recover from any hardware out-of-sync.
+                * May loose one frame
+                */
+               video->field_id = fid;
+       }
+}
+
+/*
+ * vpfe_isif_vidint1_isr() - ISIF module progressive buffer scheduling isr
+ * @isif: Pointer to isif subdevice.
+ */
+void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif)
+{
+       struct vpfe_video_device *video = &isif->video_out;
+
+       if (!video->started)
+               return;
+
+       spin_lock(&video->dma_queue_lock);
+       if (video->fmt.fmt.pix.field == V4L2_FIELD_NONE &&
+           !list_empty(&video->dma_queue) && video->cur_frm == video->next_frm)
+               vpfe_video_schedule_next_buffer(video);
+
+       spin_unlock(&video->dma_queue_lock);
+}
+
+/*
+ * VPFE video operations
+ */
+
+static int isif_video_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
+{
+       struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif;
+
+       isif_write(isif->isif_cfg.base_addr, (addr >> 21) &
+               ISIF_CADU_BITS, CADU);
+       isif_write(isif->isif_cfg.base_addr, (addr >> 5) &
+               ISIF_CADL_BITS, CADL);
+
+       return 0;
+}
+
+static const struct vpfe_video_operations isif_video_ops = {
+       .queue = isif_video_queue,
+};
+
+/*
+ * V4L2 subdev operations
+ */
+
+/* Parameter operations */
+static int isif_get_params(struct v4l2_subdev *sd, void *params)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+
+       /* only raw module parameters can be set through the IOCTL */
+       if (isif->formats[ISIF_PAD_SINK].code != V4L2_MBUS_FMT_SGRBG12_1X12)
+               return -EINVAL;
+       memcpy(params, &isif->isif_cfg.bayer.config_params,
+                       sizeof(isif->isif_cfg.bayer.config_params));
+       return 0;
+}
+
+static int isif_validate_df_csc_params(struct vpfe_isif_df_csc *df_csc)
+{
+       struct vpfe_isif_color_space_conv *csc;
+       int err = -EINVAL;
+       int csc_df_en;
+       int i;
+
+       if (!df_csc->df_or_csc) {
+               /* csc configuration */
+               csc = &df_csc->csc;
+               if (csc->en) {
+                       csc_df_en = 1;
+                       for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++)
+                               if (csc->coeff[i].integer >
+                                   ISIF_CSC_COEF_INTEG_MASK ||
+                                   csc->coeff[i].decimal >
+                                   ISIF_CSC_COEF_DECIMAL_MASK) {
+                                       pr_err("Invalid CSC coefficients\n");
+                                       return err;
+                               }
+               }
+       }
+       if (df_csc->start_pix > ISIF_DF_CSC_SPH_MASK) {
+               pr_err("Invalid df_csc start pix value\n");
+               return err;
+       }
+
+       if (df_csc->num_pixels > ISIF_DF_NUMPIX) {
+               pr_err("Invalid df_csc num pixels value\n");
+               return err;
+       }
+
+       if (df_csc->start_line > ISIF_DF_CSC_LNH_MASK) {
+               pr_err("Invalid df_csc start_line value\n");
+               return err;
+       }
+
+       if (df_csc->num_lines > ISIF_DF_NUMLINES) {
+               pr_err("Invalid df_csc num_lines value\n");
+               return err;
+       }
+
+       return 0;
+}
+
+#define DM365_ISIF_MAX_VDFLSFT         4
+#define DM365_ISIF_MAX_VDFSLV          4095
+#define DM365_ISIF_MAX_DFCMEM0         0x1fff
+#define DM365_ISIF_MAX_DFCMEM1         0x1fff
+
+static int isif_validate_dfc_params(struct vpfe_isif_dfc *dfc)
+{
+       int err = -EINVAL;
+       int i;
+
+       if (!dfc->en)
+               return 0;
+
+       if (dfc->corr_whole_line > 1) {
+               pr_err("Invalid corr_whole_line value\n");
+               return err;
+       }
+
+       if (dfc->def_level_shift > DM365_ISIF_MAX_VDFLSFT) {
+               pr_err("Invalid def_level_shift value\n");
+               return err;
+       }
+
+       if (dfc->def_sat_level > DM365_ISIF_MAX_VDFSLV) {
+               pr_err("Invalid def_sat_level value\n");
+               return err;
+       }
+
+       if (!dfc->num_vdefects ||
+           dfc->num_vdefects > VPFE_ISIF_VDFC_TABLE_SIZE) {
+               pr_err("Invalid num_vdefects value\n");
+               return err;
+       }
+
+       for (i = 0; i < VPFE_ISIF_VDFC_TABLE_SIZE; i++) {
+               if (dfc->table[i].pos_vert > DM365_ISIF_MAX_DFCMEM0) {
+                       pr_err("Invalid pos_vert value\n");
+                       return err;
+               }
+               if (dfc->table[i].pos_horz > DM365_ISIF_MAX_DFCMEM1) {
+                       pr_err("Invalid pos_horz value\n");
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+#define DM365_ISIF_MAX_CLVRV                   0xfff
+#define DM365_ISIF_MAX_CLDC                    0x1fff
+#define DM365_ISIF_MAX_CLHSH                   0x1fff
+#define DM365_ISIF_MAX_CLHSV                   0x1fff
+#define DM365_ISIF_MAX_CLVSH                   0x1fff
+#define DM365_ISIF_MAX_CLVSV                   0x1fff
+#define DM365_ISIF_MAX_HEIGHT_BLACK_REGION     0x1fff
+
+static int isif_validate_bclamp_params(struct vpfe_isif_black_clamp *bclamp)
+{
+       int err = -EINVAL;
+
+       if (bclamp->dc_offset > DM365_ISIF_MAX_CLDC) {
+               pr_err("Invalid bclamp dc_offset value\n");
+               return err;
+       }
+       if (!bclamp->en)
+               return 0;
+       if (bclamp->horz.clamp_pix_limit > 1) {
+               pr_err("Invalid bclamp horz clamp_pix_limit value\n");
+               return err;
+       }
+       if (bclamp->horz.win_count_calc < 1 ||
+                       bclamp->horz.win_count_calc > 32) {
+               pr_err("Invalid bclamp horz win_count_calc value\n");
+               return err;
+       }
+       if (bclamp->horz.win_start_h_calc > DM365_ISIF_MAX_CLHSH) {
+               pr_err("Invalid bclamp win_start_v_calc value\n");
+               return err;
+       }
+
+       if (bclamp->horz.win_start_v_calc > DM365_ISIF_MAX_CLHSV) {
+               pr_err("Invalid bclamp win_start_v_calc value\n");
+               return err;
+       }
+       if (bclamp->vert.reset_clamp_val > DM365_ISIF_MAX_CLVRV) {
+               pr_err("Invalid bclamp reset_clamp_val value\n");
+               return err;
+       }
+       if (bclamp->vert.ob_v_sz_calc > DM365_ISIF_MAX_HEIGHT_BLACK_REGION) {
+               pr_err("Invalid bclamp ob_v_sz_calc value\n");
+               return err;
+       }
+       if (bclamp->vert.ob_start_h > DM365_ISIF_MAX_CLVSH) {
+               pr_err("Invalid bclamp ob_start_h value\n");
+               return err;
+       }
+       if (bclamp->vert.ob_start_v > DM365_ISIF_MAX_CLVSV) {
+               pr_err("Invalid bclamp ob_start_h value\n");
+               return err;
+       }
+       return 0;
+}
+
+static int
+isif_validate_raw_params(struct vpfe_isif_raw_config *params)
+{
+       int ret;
+
+       ret = isif_validate_df_csc_params(&params->df_csc);
+       if (ret)
+               return ret;
+       ret = isif_validate_dfc_params(&params->dfc);
+       if (ret)
+               return ret;
+       ret = isif_validate_bclamp_params(&params->bclamp);
+       return ret;
+}
+
+static int isif_set_params(struct v4l2_subdev *sd, void *params)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+       struct vpfe_isif_raw_config isif_raw_params;
+       int ret = -EINVAL;
+
+       /* only raw module parameters can be set through the IOCTL */
+       if (isif->formats[ISIF_PAD_SINK].code != V4L2_MBUS_FMT_SGRBG12_1X12)
+               return ret;
+
+       memcpy(&isif_raw_params, params, sizeof(isif_raw_params));
+       if (!isif_validate_raw_params(&isif_raw_params)) {
+               memcpy(&isif->isif_cfg.bayer.config_params, &isif_raw_params,
+                       sizeof(isif_raw_params));
+               ret = 0;
+       }
+       return ret;
+}
+/*
+ * isif_ioctl() - isif module private ioctl's
+ * @sd: VPFE isif V4L2 subdevice
+ * @cmd: ioctl command
+ * @arg: ioctl argument
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static long isif_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+       int ret;
+
+       switch (cmd) {
+       case VIDIOC_VPFE_ISIF_S_RAW_PARAMS:
+               ret = isif_set_params(sd, arg);
+               break;
+
+       case VIDIOC_VPFE_ISIF_G_RAW_PARAMS:
+               ret = isif_get_params(sd, arg);
+               break;
+
+       default:
+               ret = -ENOIOCTLCMD;
+       }
+       return ret;
+}
+
+static void isif_config_gain_offset(struct vpfe_isif_device *isif)
+{
+       struct vpfe_isif_gain_offsets_adj *gain_off_ptr =
+               &isif->isif_cfg.bayer.config_params.gain_offset;
+       void *__iomem base = isif->isif_cfg.base_addr;
+       u32 val;
+
+       val = ((gain_off_ptr->gain_sdram_en & 1) << GAIN_SDRAM_EN_SHIFT) |
+             ((gain_off_ptr->gain_ipipe_en & 1) << GAIN_IPIPE_EN_SHIFT) |
+             ((gain_off_ptr->gain_h3a_en & 1) << GAIN_H3A_EN_SHIFT) |
+             ((gain_off_ptr->offset_sdram_en & 1) << OFST_SDRAM_EN_SHIFT) |
+             ((gain_off_ptr->offset_ipipe_en & 1) << OFST_IPIPE_EN_SHIFT) |
+             ((gain_off_ptr->offset_h3a_en & 1) << OFST_H3A_EN_SHIFT);
+       isif_merge(base, GAIN_OFFSET_EN_MASK, val, CGAMMAWD);
+
+       isif_write(base, isif->isif_cfg.isif_gain_params.cr_gain, CRGAIN);
+       isif_write(base, isif->isif_cfg.isif_gain_params.cgr_gain, CGRGAIN);
+       isif_write(base, isif->isif_cfg.isif_gain_params.cgb_gain, CGBGAIN);
+       isif_write(base, isif->isif_cfg.isif_gain_params.cb_gain, CBGAIN);
+       isif_write(base, isif->isif_cfg.isif_gain_params.offset & OFFSET_MASK,
+                  COFSTA);
+
+}
+
+static void isif_config_bclamp(struct vpfe_isif_device *isif,
+                  struct vpfe_isif_black_clamp *bc)
+{
+       u32 val;
+
+       /**
+        * DC Offset is always added to image data irrespective of bc enable
+        * status
+        */
+       val = bc->dc_offset & ISIF_BC_DCOFFSET_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, CLDCOFST);
+
+       if (!bc->en)
+               return;
+
+       val = (bc->bc_mode_color & ISIF_BC_MODE_COLOR_MASK) <<
+               ISIF_BC_MODE_COLOR_SHIFT;
+
+       /* Enable BC and horizontal clamp caculation paramaters */
+       val = val | 1 | ((bc->horz.mode & ISIF_HORZ_BC_MODE_MASK) <<
+             ISIF_HORZ_BC_MODE_SHIFT);
+
+       isif_write(isif->isif_cfg.base_addr, val, CLAMPCFG);
+
+       if (bc->horz.mode != VPFE_ISIF_HORZ_BC_DISABLE) {
+               /*
+                * Window count for calculation
+                * Base window selection
+                * pixel limit
+                * Horizontal size of window
+                * vertical size of the window
+                * Horizontal start position of the window
+                * Vertical start position of the window
+                */
+               val = (bc->horz.win_count_calc & ISIF_HORZ_BC_WIN_COUNT_MASK) |
+                     ((bc->horz.base_win_sel_calc & 1) <<
+                     ISIF_HORZ_BC_WIN_SEL_SHIFT) |
+                     ((bc->horz.clamp_pix_limit & 1) <<
+                     ISIF_HORZ_BC_PIX_LIMIT_SHIFT) |
+                     ((bc->horz.win_h_sz_calc &
+                     ISIF_HORZ_BC_WIN_H_SIZE_MASK) <<
+                     ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) |
+                     ((bc->horz.win_v_sz_calc &
+                     ISIF_HORZ_BC_WIN_V_SIZE_MASK) <<
+                     ISIF_HORZ_BC_WIN_V_SIZE_SHIFT);
+
+               isif_write(isif->isif_cfg.base_addr, val, CLHWIN0);
+
+               val = bc->horz.win_start_h_calc & ISIF_HORZ_BC_WIN_START_H_MASK;
+               isif_write(isif->isif_cfg.base_addr, val, CLHWIN1);
+
+               val = bc->horz.win_start_v_calc & ISIF_HORZ_BC_WIN_START_V_MASK;
+               isif_write(isif->isif_cfg.base_addr, val, CLHWIN2);
+       }
+
+       /* vertical clamp caculation paramaters */
+       /* OB H Valid */
+       val = bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK;
+
+       /* Reset clamp value sel for previous line */
+       val |= (bc->vert.reset_val_sel & ISIF_VERT_BC_RST_VAL_SEL_MASK) <<
+                               ISIF_VERT_BC_RST_VAL_SEL_SHIFT;
+
+       /* Line average coefficient */
+       val |= bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT;
+       isif_write(isif->isif_cfg.base_addr, val, CLVWIN0);
+
+       /* Configured reset value */
+       if (bc->vert.reset_val_sel == VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL) {
+               val = bc->vert.reset_clamp_val & ISIF_VERT_BC_RST_VAL_MASK;
+               isif_write(isif->isif_cfg.base_addr, val, CLVRV);
+       }
+
+       /* Optical Black horizontal start position */
+       val = bc->vert.ob_start_h & ISIF_VERT_BC_OB_START_HORZ_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, CLVWIN1);
+
+       /* Optical Black vertical start position */
+       val = bc->vert.ob_start_v & ISIF_VERT_BC_OB_START_VERT_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, CLVWIN2);
+
+       val = bc->vert.ob_v_sz_calc & ISIF_VERT_BC_OB_VERT_SZ_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, CLVWIN3);
+
+       /* Vertical start position for BC subtraction */
+       val = bc->vert_start_sub & ISIF_BC_VERT_START_SUB_V_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, CLSV);
+}
+
+/* This function will configure the window size to be capture in ISIF reg */
+static void
+isif_setwin(struct vpfe_isif_device *isif, struct v4l2_rect *image_win,
+           enum isif_frmfmt frm_fmt, int ppc, int mode)
+{
+       int horz_nr_pixels;
+       int vert_nr_lines;
+       int horz_start;
+       int vert_start;
+       int mid_img;
+
+       /*
+        * ppc - per pixel count. indicates how many pixels per cell
+        * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
+        * raw capture this is 1
+        */
+       horz_start = image_win->left << (ppc - 1);
+       horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
+
+       /* Writing the horizontal info into the registers */
+       isif_write(isif->isif_cfg.base_addr,
+                  horz_start & START_PX_HOR_MASK, SPH);
+       isif_write(isif->isif_cfg.base_addr,
+                  horz_nr_pixels & NUM_PX_HOR_MASK, LNH);
+       vert_start = image_win->top;
+
+       if (frm_fmt == ISIF_FRMFMT_INTERLACED) {
+               vert_nr_lines = (image_win->height >> 1) - 1;
+               vert_start >>= 1;
+               /* To account for VD since line 0 doesn't have any data */
+               vert_start += 1;
+       } else {
+               /* To account for VD since line 0 doesn't have any data */
+               vert_start += 1;
+               vert_nr_lines = image_win->height - 1;
+               /* configure VDINT0 and VDINT1 */
+               mid_img = vert_start + (image_win->height / 2);
+               isif_write(isif->isif_cfg.base_addr, mid_img, VDINT1);
+       }
+
+       if (!mode)
+               isif_write(isif->isif_cfg.base_addr, 0, VDINT0);
+       else
+               isif_write(isif->isif_cfg.base_addr, vert_nr_lines, VDINT0);
+       isif_write(isif->isif_cfg.base_addr,
+                  vert_start & START_VER_ONE_MASK, SLV0);
+       isif_write(isif->isif_cfg.base_addr,
+                  vert_start & START_VER_TWO_MASK, SLV1);
+       isif_write(isif->isif_cfg.base_addr,
+                  vert_nr_lines & NUM_LINES_VER, LNV);
+}
+
+#define DM365_ISIF_DFCMWR_MEMORY_WRITE         1
+#define DM365_ISIF_DFCMRD_MEMORY_READ          0x2
+
+static void
+isif_config_dfc(struct vpfe_isif_device *isif, struct vpfe_isif_dfc *vdfc)
+{
+#define DFC_WRITE_WAIT_COUNT   1000
+       u32 count = DFC_WRITE_WAIT_COUNT;
+       u32 val;
+       int i;
+
+       if (!vdfc->en)
+               return;
+
+       /* Correction mode */
+       val = (vdfc->corr_mode & ISIF_VDFC_CORR_MOD_MASK) <<
+              ISIF_VDFC_CORR_MOD_SHIFT;
+
+       /* Correct whole line or partial */
+       if (vdfc->corr_whole_line)
+               val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT;
+
+       /* level shift value */
+       val |= (vdfc->def_level_shift & ISIF_VDFC_LEVEL_SHFT_MASK) <<
+               ISIF_VDFC_LEVEL_SHFT_SHIFT;
+
+       isif_write(isif->isif_cfg.base_addr, val, DFCCTL);
+
+       /* Defect saturation level */
+       val = vdfc->def_sat_level & ISIF_VDFC_SAT_LEVEL_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, VDFSATLV);
+
+       isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_vert &
+                  ISIF_VDFC_POS_MASK, DFCMEM0);
+       isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_horz &
+                  ISIF_VDFC_POS_MASK, DFCMEM1);
+       if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL ||
+           vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
+               isif_write(isif->isif_cfg.base_addr,
+                          vdfc->table[0].level_at_pos, DFCMEM2);
+               isif_write(isif->isif_cfg.base_addr,
+                          vdfc->table[0].level_up_pixels, DFCMEM3);
+               isif_write(isif->isif_cfg.base_addr,
+                          vdfc->table[0].level_low_pixels, DFCMEM4);
+       }
+
+       val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+       /* set DFCMARST and set DFCMWR */
+       val |= 1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT;
+       val |= 1;
+       isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL);
+
+       while (count && (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x01))
+               count--;
+
+       val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+       if (!count) {
+               pr_debug("defect table write timeout !!\n");
+               return;
+       }
+
+       for (i = 1; i < vdfc->num_vdefects; i++) {
+               isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_vert &
+                       ISIF_VDFC_POS_MASK, DFCMEM0);
+
+               isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_horz &
+                       ISIF_VDFC_POS_MASK, DFCMEM1);
+
+               if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL ||
+                   vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
+                       isif_write(isif->isif_cfg.base_addr,
+                                  vdfc->table[i].level_at_pos, DFCMEM2);
+                       isif_write(isif->isif_cfg.base_addr,
+                                  vdfc->table[i].level_up_pixels, DFCMEM3);
+                       isif_write(isif->isif_cfg.base_addr,
+                                  vdfc->table[i].level_low_pixels, DFCMEM4);
+               }
+               val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+               /* clear DFCMARST and set DFCMWR */
+               val &= ~(1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT);
+               val |= 1;
+               isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL);
+
+               count = DFC_WRITE_WAIT_COUNT;
+               while (count && (isif_read(isif->isif_cfg.base_addr,
+                       DFCMEMCTL) & 0x01))
+                       count--;
+
+               val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+               if (!count) {
+                       pr_debug("defect table write timeout !!\n");
+                       return;
+               }
+       }
+       if (vdfc->num_vdefects < VPFE_ISIF_VDFC_TABLE_SIZE) {
+               /* Extra cycle needed */
+               isif_write(isif->isif_cfg.base_addr, 0, DFCMEM0);
+               isif_write(isif->isif_cfg.base_addr,
+                          DM365_ISIF_MAX_DFCMEM1, DFCMEM1);
+               isif_write(isif->isif_cfg.base_addr,
+                          DM365_ISIF_DFCMWR_MEMORY_WRITE, DFCMEMCTL);
+       }
+       /* enable VDFC */
+       isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT),
+                  (1 << ISIF_VDFC_EN_SHIFT), DFCCTL);
+
+       isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT),
+                  (0 << ISIF_VDFC_EN_SHIFT), DFCCTL);
+
+       isif_write(isif->isif_cfg.base_addr, 0x6, DFCMEMCTL);
+       for (i = 0 ; i < vdfc->num_vdefects; i++) {
+               count = DFC_WRITE_WAIT_COUNT;
+               while (count &&
+                       (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x2))
+                       count--;
+               val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+               if (!count) {
+                       pr_debug("defect table write timeout !!\n");
+                       return;
+               }
+               isif_write(isif->isif_cfg.base_addr,
+                          DM365_ISIF_DFCMRD_MEMORY_READ, DFCMEMCTL);
+       }
+}
+
+static void
+isif_config_csc(struct vpfe_isif_device *isif, struct vpfe_isif_df_csc *df_csc)
+{
+       u32 val1;
+       u32 val2;
+       u32 i;
+
+       if (!df_csc->csc.en) {
+               isif_write(isif->isif_cfg.base_addr, 0, CSCCTL);
+               return;
+       }
+       /* initialize all bits to 0 */
+       val1 = 0;
+       for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) {
+               if ((i % 2) == 0) {
+                       /* CSCM - LSB */
+                       val1 = ((df_csc->csc.coeff[i].integer &
+                               ISIF_CSC_COEF_INTEG_MASK) <<
+                               ISIF_CSC_COEF_INTEG_SHIFT) |
+                               ((df_csc->csc.coeff[i].decimal &
+                               ISIF_CSC_COEF_DECIMAL_MASK));
+               } else {
+
+                       /* CSCM - MSB */
+                       val2 = ((df_csc->csc.coeff[i].integer &
+                               ISIF_CSC_COEF_INTEG_MASK) <<
+                               ISIF_CSC_COEF_INTEG_SHIFT) |
+                               ((df_csc->csc.coeff[i].decimal &
+                               ISIF_CSC_COEF_DECIMAL_MASK));
+                       val2 <<= ISIF_CSCM_MSB_SHIFT;
+                       val2 |= val1;
+                       isif_write(isif->isif_cfg.base_addr, val2,
+                                  (CSCM0 + ((i-1) << 1)));
+               }
+       }
+       /* program the active area */
+       isif_write(isif->isif_cfg.base_addr, df_csc->start_pix &
+               ISIF_DF_CSC_SPH_MASK, FMTSPH);
+       /*
+        * one extra pixel as required for CSC. Actually number of
+        * pixel - 1 should be configured in this register. So we
+        * need to subtract 1 before writing to FMTSPH, but we will
+        * not do this since csc requires one extra pixel
+        */
+       isif_write(isif->isif_cfg.base_addr, df_csc->num_pixels &
+               ISIF_DF_CSC_SPH_MASK, FMTLNH);
+       isif_write(isif->isif_cfg.base_addr, df_csc->start_line &
+               ISIF_DF_CSC_SPH_MASK, FMTSLV);
+       /*
+        * one extra line as required for CSC. See reason documented for
+        * num_pixels
+        */
+       isif_write(isif->isif_cfg.base_addr, df_csc->num_lines &
+               ISIF_DF_CSC_SPH_MASK, FMTLNV);
+       /* Enable CSC */
+       isif_write(isif->isif_cfg.base_addr, 1, CSCCTL);
+}
+
+static void
+isif_config_linearization(struct vpfe_isif_device *isif,
+                         struct vpfe_isif_linearize *linearize)
+{
+       u32 val;
+       u32 i;
+
+       if (!linearize->en) {
+               isif_write(isif->isif_cfg.base_addr, 0, LINCFG0);
+               return;
+       }
+       /* shift value for correction */
+       val = (linearize->corr_shft & ISIF_LIN_CORRSFT_MASK) <<
+             ISIF_LIN_CORRSFT_SHIFT;
+       /* enable */
+       val |= 1;
+       isif_write(isif->isif_cfg.base_addr, val, LINCFG0);
+       /* Scale factor */
+       val = (linearize->scale_fact.integer & 1) <<
+             ISIF_LIN_SCALE_FACT_INTEG_SHIFT;
+       val |= linearize->scale_fact.decimal & ISIF_LIN_SCALE_FACT_DECIMAL_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, LINCFG1);
+
+       for (i = 0; i < VPFE_ISIF_LINEAR_TAB_SIZE; i++) {
+               val = linearize->table[i] & ISIF_LIN_ENTRY_MASK;
+               if (i%2)
+                       isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 1);
+               else
+                       isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 0);
+       }
+}
+
+static void
+isif_config_culling(struct vpfe_isif_device *isif, struct vpfe_isif_cul *cul)
+{
+       u32 val;
+
+       /* Horizontal pattern */
+       val = cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT;
+       val |= cul->hcpat_odd;
+       isif_write(isif->isif_cfg.base_addr, val, CULH);
+       /* vertical pattern */
+       isif_write(isif->isif_cfg.base_addr, cul->vcpat, CULV);
+       /* LPF */
+       isif_merge(isif->isif_cfg.base_addr, ISIF_LPF_MASK << ISIF_LPF_SHIFT,
+                  cul->en_lpf << ISIF_LPF_SHIFT, MODESET);
+}
+
+static int isif_get_pix_fmt(u32 mbus_code)
+{
+       switch (mbus_code) {
+       case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               return ISIF_PIXFMT_RAW;
+
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+       case V4L2_MBUS_FMT_YUYV10_2X10:
+       case V4L2_MBUS_FMT_Y8_1X8:
+               return ISIF_PIXFMT_YCBCR_8BIT;
+
+       case V4L2_MBUS_FMT_YUYV8_1X16:
+       case V4L2_MBUS_FMT_YUYV10_1X20:
+               return ISIF_PIXFMT_YCBCR_16BIT;
+
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
+#define ISIF_INTERLACE_INVERSE_MODE            0x4b6d
+#define ISIF_INTERLACE_NON_INVERSE_MODE                0x0b6d
+#define ISIF_PROGRESSIVE_INVERSE_MODE          0x4000
+#define ISIF_PROGRESSIVE_NON_INVERSE_MODE      0x0000
+
+static int isif_config_raw(struct v4l2_subdev *sd, int mode)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+       struct isif_params_raw *params = &isif->isif_cfg.bayer;
+       struct vpfe_isif_raw_config *module_params =
+                               &isif->isif_cfg.bayer.config_params;
+       struct v4l2_mbus_framefmt *format;
+       int pix_fmt;
+       u32 val;
+
+       format = &isif->formats[ISIF_PAD_SINK];
+
+       /* In case of user has set BT656IF earlier, it should be reset
+        * when configuring for raw input.
+        */
+       isif_write(isif->isif_cfg.base_addr, 0, REC656IF);
+       /* Configure CCDCFG register
+        * Set CCD Not to swap input since input is RAW data
+        * Set FID detection function to Latch at V-Sync
+        * Set WENLOG - isif valid area
+        * Set TRGSEL
+        * Set EXTRG
+        * Packed to 8 or 16 bits
+        */
+       val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC |
+             ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN |
+             ISIF_CCDCFG_EXTRG_DISABLE | (isif->isif_cfg.data_pack &
+             ISIF_DATA_PACK_MASK);
+       isif_write(isif->isif_cfg.base_addr, val, CCDCFG);
+
+       pix_fmt = isif_get_pix_fmt(format->code);
+       if (pix_fmt < 0) {
+               pr_debug("Invalid pix_fmt(input mode)\n");
+               return -EINVAL;
+       }
+       /*
+        * Configure the vertical sync polarity(MODESET.VDPOL)
+        * Configure the horizontal sync polarity (MODESET.HDPOL)
+        * Configure frame id polarity (MODESET.FLDPOL)
+        * Configure data polarity
+        * Configure External WEN Selection
+        * Configure frame format(progressive or interlace)
+        * Configure pixel format (Input mode)
+        * Configure the data shift
+        */
+       val = ISIF_VDHDOUT_INPUT | ((params->vd_pol & ISIF_VD_POL_MASK) <<
+             ISIF_VD_POL_SHIFT) | ((params->hd_pol & ISIF_HD_POL_MASK) <<
+             ISIF_HD_POL_SHIFT) | ((params->fid_pol & ISIF_FID_POL_MASK) <<
+             ISIF_FID_POL_SHIFT) | ((ISIF_DATAPOL_NORMAL &
+             ISIF_DATAPOL_MASK) << ISIF_DATAPOL_SHIFT) | ((ISIF_EXWEN_DISABLE &
+             ISIF_EXWEN_MASK) << ISIF_EXWEN_SHIFT) | ((params->frm_fmt &
+             ISIF_FRM_FMT_MASK) << ISIF_FRM_FMT_SHIFT) | ((pix_fmt &
+             ISIF_INPUT_MASK) << ISIF_INPUT_SHIFT);
+
+       /* currently only V4L2_MBUS_FMT_SGRBG12_1X12 is
+        * supported. shift appropriately depending on
+        * different MBUS fmt's added
+        */
+       if (format->code == V4L2_MBUS_FMT_SGRBG12_1X12)
+               val |= ((VPFE_ISIF_NO_SHIFT &
+                       ISIF_DATASFT_MASK) << ISIF_DATASFT_SHIFT);
+
+       isif_write(isif->isif_cfg.base_addr, val, MODESET);
+       /*
+        * Configure GAMMAWD register
+        * CFA pattern setting
+        */
+       val = (params->cfa_pat & ISIF_GAMMAWD_CFA_MASK) <<
+               ISIF_GAMMAWD_CFA_SHIFT;
+       /* Gamma msb */
+       if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10ALAW8)
+               val = val | ISIF_ALAW_ENABLE;
+
+       val = val | ((params->data_msb & ISIF_ALAW_GAMA_WD_MASK) <<
+                       ISIF_ALAW_GAMA_WD_SHIFT);
+
+       isif_write(isif->isif_cfg.base_addr, val, CGAMMAWD);
+       /* Configure DPCM compression settings */
+       if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10DPCM8) {
+               val =  1 << ISIF_DPCM_EN_SHIFT;
+               val |= (params->dpcm_predictor &
+                       ISIF_DPCM_PREDICTOR_MASK) << ISIF_DPCM_PREDICTOR_SHIFT;
+       }
+       isif_write(isif->isif_cfg.base_addr, val, MISC);
+       /* Configure Gain & Offset */
+       isif_config_gain_offset(isif);
+       /* Configure Color pattern */
+       if (format->code == V4L2_MBUS_FMT_SGRBG12_1X12)
+               val = isif_sgrbg_pattern;
+       else
+               /* default set to rggb */
+               val = isif_srggb_pattern;
+
+       isif_write(isif->isif_cfg.base_addr, val, CCOLP);
+
+       /* Configure HSIZE register  */
+       val = (params->horz_flip_en & ISIF_HSIZE_FLIP_MASK) <<
+             ISIF_HSIZE_FLIP_SHIFT;
+
+       /* calculate line offset in 32 bytes based on pack value */
+       if (isif->isif_cfg.data_pack == ISIF_PACK_8BIT)
+               val |= ((params->win.width + 31) >> 5) & ISIF_LINEOFST_MASK;
+       else if (isif->isif_cfg.data_pack == ISIF_PACK_12BIT)
+               val |= ((((params->win.width + (params->win.width >> 2)) +
+                       31) >> 5) & ISIF_LINEOFST_MASK);
+       else
+               val |= (((params->win.width * 2) + 31) >> 5) &
+                       ISIF_LINEOFST_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, HSIZE);
+       /* Configure SDOFST register  */
+       if (params->frm_fmt == ISIF_FRMFMT_INTERLACED) {
+               if (params->image_invert_en)
+                       /* For interlace inverse mode */
+                       isif_write(isif->isif_cfg.base_addr,
+                                  ISIF_INTERLACE_INVERSE_MODE, SDOFST);
+               else
+                       /* For interlace non inverse mode */
+                       isif_write(isif->isif_cfg.base_addr,
+                                  ISIF_INTERLACE_NON_INVERSE_MODE, SDOFST);
+       } else if (params->frm_fmt == ISIF_FRMFMT_PROGRESSIVE) {
+               if (params->image_invert_en)
+                       isif_write(isif->isif_cfg.base_addr,
+                                  ISIF_PROGRESSIVE_INVERSE_MODE, SDOFST);
+               else
+                       /* For progessive non inverse mode */
+                       isif_write(isif->isif_cfg.base_addr,
+                                  ISIF_PROGRESSIVE_NON_INVERSE_MODE, SDOFST);
+       }
+       /* Configure video window */
+       isif_setwin(isif, &params->win, params->frm_fmt, 1, mode);
+       /* Configure Black Clamp */
+       isif_config_bclamp(isif, &module_params->bclamp);
+       /* Configure Vertical Defection Pixel Correction */
+       isif_config_dfc(isif, &module_params->dfc);
+       if (!module_params->df_csc.df_or_csc)
+               /* Configure Color Space Conversion */
+               isif_config_csc(isif, &module_params->df_csc);
+
+       isif_config_linearization(isif, &module_params->linearize);
+       /* Configure Culling */
+       isif_config_culling(isif, &module_params->culling);
+       /* Configure Horizontal and vertical offsets(DFC,LSC,Gain) */
+       val = module_params->horz_offset & ISIF_DATA_H_OFFSET_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, DATAHOFST);
+
+       val = module_params->vert_offset & ISIF_DATA_V_OFFSET_MASK;
+       isif_write(isif->isif_cfg.base_addr, val, DATAVOFST);
+
+       return 0;
+}
+
+#define DM365_ISIF_HSIZE_MASK          0xffffffe0
+#define DM365_ISIF_SDOFST_2_LINES      0x00000249
+
+/* This function will configure ISIF for YCbCr parameters. */
+static int isif_config_ycbcr(struct v4l2_subdev *sd, int mode)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+       struct isif_ycbcr_config *params = &isif->isif_cfg.ycbcr;
+       struct v4l2_mbus_framefmt *format;
+       int pix_fmt;
+       u32 modeset;
+       u32 ccdcfg;
+
+       format = &isif->formats[ISIF_PAD_SINK];
+       /*
+        * first reset the ISIF
+        * all registers have default values after reset
+        * This is important since we assume default values to be set in
+        * a lot of registers that we didn't touch
+        */
+       /* start with all bits zero */
+       ccdcfg = modeset = 0;
+       pix_fmt = isif_get_pix_fmt(format->code);
+       if (pix_fmt < 0) {
+               pr_debug("Invalid pix_fmt(input mode)\n");
+               return -EINVAL;
+       }
+       /* configure pixel format or input mode */
+       modeset = modeset | ((pix_fmt & ISIF_INPUT_MASK) <<
+                 ISIF_INPUT_SHIFT) | ((params->frm_fmt & ISIF_FRM_FMT_MASK) <<
+                 ISIF_FRM_FMT_SHIFT) | (((params->fid_pol &
+                 ISIF_FID_POL_MASK) << ISIF_FID_POL_SHIFT)) |
+                 (((params->hd_pol & ISIF_HD_POL_MASK) << ISIF_HD_POL_SHIFT)) |
+                 (((params->vd_pol & ISIF_VD_POL_MASK) << ISIF_VD_POL_SHIFT));
+       /* pack the data to 8-bit CCDCCFG */
+       switch (format->code) {
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+               if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
+                       pr_debug("Invalid pix_fmt(input mode)\n");
+                       return -EINVAL;
+               }
+               modeset |= ((VPFE_PINPOL_NEGATIVE & ISIF_VD_POL_MASK) <<
+                               ISIF_VD_POL_SHIFT);
+               isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
+               ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR;
+               break;
+
+       case V4L2_MBUS_FMT_YUYV10_2X10:
+               if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
+                       pr_debug("Invalid pix_fmt(input mode)\n");
+                       return -EINVAL;
+               }
+               /* setup BT.656, embedded sync  */
+               isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
+               /* enable 10 bit mode in ccdcfg */
+               ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR |
+                       ISIF_BW656_ENABLE;
+               break;
+
+       case V4L2_MBUS_FMT_YUYV10_1X20:
+               if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) {
+                       pr_debug("Invalid pix_fmt(input mode)\n");
+                       return -EINVAL;
+               }
+               isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
+               break;
+
+       case V4L2_MBUS_FMT_Y8_1X8:
+               ccdcfg |= ISIF_PACK_8BIT;
+               ccdcfg |= ISIF_YCINSWP_YCBCR;
+               if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
+                       pr_debug("Invalid pix_fmt(input mode)\n");
+                       return -EINVAL;
+               }
+               break;
+
+       case V4L2_MBUS_FMT_YUYV8_1X16:
+               if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) {
+                       pr_debug("Invalid pix_fmt(input mode)\n");
+                       return -EINVAL;
+               }
+               break;
+
+       default:
+               /* should never come here */
+               pr_debug("Invalid interface type\n");
+               return -EINVAL;
+       }
+       isif_write(isif->isif_cfg.base_addr, modeset, MODESET);
+       /* Set up pix order */
+       ccdcfg |= (params->pix_order & ISIF_PIX_ORDER_MASK) <<
+               ISIF_PIX_ORDER_SHIFT;
+       isif_write(isif->isif_cfg.base_addr, ccdcfg, CCDCFG);
+       /* configure video window */
+       if (format->code == V4L2_MBUS_FMT_YUYV10_1X20 ||
+                       format->code == V4L2_MBUS_FMT_YUYV8_1X16)
+               isif_setwin(isif, &params->win, params->frm_fmt, 1, mode);
+       else
+               isif_setwin(isif, &params->win, params->frm_fmt, 2, mode);
+
+       /*
+        * configure the horizontal line offset
+        * this is done by rounding up width to a multiple of 16 pixels
+        * and multiply by two to account for y:cb:cr 4:2:2 data
+        */
+       isif_write(isif->isif_cfg.base_addr,
+                  ((((params->win.width * 2) + 31) &
+                  DM365_ISIF_HSIZE_MASK) >> 5), HSIZE);
+
+       /* configure the memory line offset */
+       if (params->frm_fmt == ISIF_FRMFMT_INTERLACED &&
+           params->buf_type == ISIF_BUFTYPE_FLD_INTERLEAVED)
+               /* two fields are interleaved in memory */
+               isif_write(isif->isif_cfg.base_addr,
+                          DM365_ISIF_SDOFST_2_LINES, SDOFST);
+       return 0;
+}
+
+static int isif_configure(struct v4l2_subdev *sd, int mode)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = &isif->formats[ISIF_PAD_SINK];
+
+       switch (format->code) {
+       case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               return isif_config_raw(sd, mode);
+
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+       case V4L2_MBUS_FMT_YUYV10_2X10:
+       case V4L2_MBUS_FMT_Y8_1X8:
+       case V4L2_MBUS_FMT_YUYV8_1X16:
+       case V4L2_MBUS_FMT_YUYV10_1X20:
+               return isif_config_ycbcr(sd, mode);
+
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
+/*
+ * isif_set_stream() - Enable/Disable streaming on the ISIF module
+ * @sd: VPFE ISIF V4L2 subdevice
+ * @enable: Enable/disable stream
+ */
+static int isif_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+       int ret;
+
+       if (enable) {
+               ret = isif_configure(sd,
+                       (isif->output == ISIF_OUTPUT_MEMORY) ? 0 : 1);
+               if (ret)
+                       return ret;
+               if (isif->output == ISIF_OUTPUT_MEMORY)
+                       isif_enable_output_to_sdram(isif, 1);
+               isif_enable(isif, 1);
+       } else {
+               isif_enable(isif, 0);
+               isif_enable_output_to_sdram(isif, 0);
+       }
+
+       return 0;
+}
+
+/*
+ * __isif_get_format() - helper function for getting isif format
+ * @isif: pointer to isif private structure.
+ * @pad: pad number.
+ * @fh: V4L2 subdev file handle.
+ * @which: wanted subdev format.
+ */
+static struct v4l2_mbus_framefmt *
+__isif_get_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY) {
+               struct v4l2_subdev_format fmt;
+
+               fmt.pad = pad;
+               fmt.which = which;
+
+               return v4l2_subdev_get_try_format(fh, pad);
+       }
+       return &isif->formats[pad];
+}
+
+/*
+* isif_set_format() - set format on pad
+* @sd    : VPFE ISIF device
+* @fh    : V4L2 subdev file handle
+* @fmt   : pointer to v4l2 subdev format structure
+*
+* Return 0 on success or -EINVAL if format or pad is invalid
+*/
+static int
+isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+               struct v4l2_subdev_format *fmt)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+       struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __isif_get_format(isif, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       isif_try_format(isif, fh, fmt);
+       memcpy(format, &fmt->format, sizeof(*format));
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       if (fmt->pad == ISIF_PAD_SOURCE)
+               return isif_config_format(vpfe_dev, fmt->pad);
+
+       return 0;
+}
+
+/*
+ * isif_get_format() - Retrieve the video format on a pad
+ * @sd: VPFE ISIF V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int
+isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+               struct v4l2_subdev_format *fmt)
+{
+       struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __isif_get_format(vpfe_isif, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       memcpy(&fmt->format, format, sizeof(fmt->format));
+
+       return 0;
+}
+
+/*
+ * isif_enum_frame_size() - enum frame sizes on pads
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_frame_size_enum structure
+ */
+static int
+isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                    struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+       struct v4l2_subdev_format format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.pad = fse->pad;
+       format.format.code = fse->code;
+       format.format.width = 1;
+       format.format.height = 1;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
+       isif_try_format(isif, fh, &format);
+       fse->min_width = format.format.width;
+       fse->min_height = format.format.height;
+
+       if (format.format.code != fse->code)
+               return -EINVAL;
+
+       format.pad = fse->pad;
+       format.format.code = fse->code;
+       format.format.width = -1;
+       format.format.height = -1;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
+       isif_try_format(isif, fh, &format);
+       fse->max_width = format.format.width;
+       fse->max_height = format.format.height;
+
+       return 0;
+}
+
+/*
+ * isif_enum_mbus_code() - enum mbus codes for pads
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ */
+static int
+isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                   struct v4l2_subdev_mbus_code_enum *code)
+{
+       switch (code->pad) {
+       case ISIF_PAD_SINK:
+       case ISIF_PAD_SOURCE:
+               if (code->index >= ARRAY_SIZE(isif_fmts))
+                       return -EINVAL;
+               code->code = isif_fmts[code->index];
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * isif_pad_set_crop() - set crop rectangle on pad
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Return 0 on success, -EINVAL if pad is invalid
+ */
+static int
+isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                 struct v4l2_subdev_crop *crop)
+{
+       struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       /* check wether its a valid pad */
+       if (crop->pad != ISIF_PAD_SINK)
+               return -EINVAL;
+
+       format = __isif_get_format(vpfe_isif, fh, crop->pad, crop->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       /* check wether crop rect is within limits */
+       if (crop->rect.top < 0 || crop->rect.left < 0 ||
+               (crop->rect.left + crop->rect.width >
+               vpfe_isif->formats[ISIF_PAD_SINK].width) ||
+               (crop->rect.top + crop->rect.height >
+                       vpfe_isif->formats[ISIF_PAD_SINK].height)) {
+               crop->rect.left = 0;
+               crop->rect.top = 0;
+               crop->rect.width = format->width;
+               crop->rect.height = format->height;
+       }
+       /* adjust the width to 16 pixel boundry */
+       crop->rect.width = ((crop->rect.width + 15) & ~0xf);
+       vpfe_isif->crop = crop->rect;
+       if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+               isif_set_image_window(vpfe_isif);
+       } else {
+               struct v4l2_rect *rect;
+
+               rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
+               memcpy(rect, &vpfe_isif->crop, sizeof(*rect));
+       }
+       return 0;
+}
+
+/*
+ * isif_pad_get_crop() - get crop rectangle on pad
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Return 0 on success, -EINVAL if pad is invalid
+ */
+static int
+isif_pad_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                 struct v4l2_subdev_crop *crop)
+{
+       struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
+
+       /* check wether its a valid pad */
+       if (crop->pad != ISIF_PAD_SINK)
+               return -EINVAL;
+
+       if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+               struct v4l2_rect *rect;
+               rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
+               memcpy(&crop->rect, rect, sizeof(*rect));
+       } else {
+               crop->rect = vpfe_isif->crop;
+       }
+
+       return 0;
+}
+
+/*
+ * isif_init_formats() - Initialize formats on all pads
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int
+isif_init_formats(struct v4l2_subdev *sd,
+                 struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_subdev_format format;
+       struct v4l2_subdev_crop crop;
+
+       memset(&format, 0, sizeof(format));
+       format.pad = ISIF_PAD_SINK;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+       format.format.width = MAX_WIDTH;
+       format.format.height = MAX_HEIGHT;
+       isif_set_format(sd, fh, &format);
+
+       memset(&format, 0, sizeof(format));
+       format.pad = ISIF_PAD_SOURCE;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+       format.format.width = MAX_WIDTH;
+       format.format.height = MAX_HEIGHT;
+       isif_set_format(sd, fh, &format);
+
+       memset(&crop, 0, sizeof(crop));
+       crop.pad = ISIF_PAD_SINK;
+       crop.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       crop.rect.width = MAX_WIDTH;
+       crop.rect.height = MAX_HEIGHT;
+       isif_pad_set_crop(sd, fh, &crop);
+
+       return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops isif_v4l2_core_ops = {
+       .ioctl = isif_ioctl,
+};
+
+/* subdev file operations */
+static const struct v4l2_subdev_internal_ops isif_v4l2_internal_ops = {
+       .open = isif_init_formats,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops isif_v4l2_video_ops = {
+       .s_stream = isif_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops = {
+       .enum_mbus_code = isif_enum_mbus_code,
+       .enum_frame_size = isif_enum_frame_size,
+       .get_fmt = isif_get_format,
+       .set_fmt = isif_set_format,
+       .set_crop = isif_pad_set_crop,
+       .get_crop = isif_pad_get_crop,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops isif_v4l2_ops = {
+       .core = &isif_v4l2_core_ops,
+       .video = &isif_v4l2_video_ops,
+       .pad = &isif_v4l2_pad_ops,
+};
+
+/*
+ * Media entity operations
+ */
+
+/*
+ * isif_link_setup() - Setup isif connections
+ * @entity: isif media entity
+ * @local: Pad at the local end of the link
+ * @remote: Pad at the remote end of the link
+ * @flags: Link flags
+ *
+ * return -EINVAL or zero on success
+ */
+static int
+isif_link_setup(struct media_entity *entity, const struct media_pad *local,
+               const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case ISIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* read from decoder/sensor */
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       isif->input = ISIF_INPUT_NONE;
+                       break;
+               }
+               if (isif->input != ISIF_INPUT_NONE)
+                       return -EBUSY;
+               isif->input = ISIF_INPUT_PARALLEL;
+               break;
+
+       case ISIF_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+               /* write to memory */
+               if (flags & MEDIA_LNK_FL_ENABLED)
+                       isif->output = ISIF_OUTPUT_MEMORY;
+               else
+                       isif->output = ISIF_OUTPUT_NONE;
+               break;
+
+       case ISIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+               if (flags & MEDIA_LNK_FL_ENABLED)
+                       isif->output = ISIF_OUTPUT_IPIPEIF;
+               else
+                       isif->output = ISIF_OUTPUT_NONE;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+static const struct media_entity_operations isif_media_ops = {
+       .link_setup = isif_link_setup,
+};
+
+/*
+ * vpfe_isif_unregister_entities() - isif unregister entity
+ * @isif - pointer to isif subdevice structure.
+ */
+void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif)
+{
+       vpfe_video_unregister(&isif->video_out);
+       /* cleanup entity */
+       media_entity_cleanup(&isif->subdev.entity);
+       /* unregister subdev */
+       v4l2_device_unregister_subdev(&isif->subdev);
+}
+
+static void isif_restore_defaults(struct vpfe_isif_device *isif)
+{
+       enum vpss_ccdc_source_sel source = VPSS_CCDCIN;
+       int i;
+
+       memset(&isif->isif_cfg.bayer.config_params, 0,
+              sizeof(struct vpfe_isif_raw_config));
+
+       isif->isif_cfg.bayer.config_params.linearize.corr_shft =
+                                       VPFE_ISIF_NO_SHIFT;
+       isif->isif_cfg.bayer.config_params.linearize.scale_fact.integer = 1;
+       isif->isif_cfg.bayer.config_params.culling.hcpat_odd =
+                       ISIF_CULLING_HCAPT_ODD;
+       isif->isif_cfg.bayer.config_params.culling.hcpat_even =
+                       ISIF_CULLING_HCAPT_EVEN;
+       isif->isif_cfg.bayer.config_params.culling.vcpat = ISIF_CULLING_VCAPT;
+       /* Enable clock to ISIF, IPIPEIF and BL */
+       vpss_enable_clock(VPSS_CCDC_CLOCK, 1);
+       vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
+       vpss_enable_clock(VPSS_BL_CLOCK, 1);
+
+       /* set all registers to default value */
+       for (i = 0; i <= 0x1f8; i += 4)
+               isif_write(isif->isif_cfg.base_addr, 0, i);
+       /* no culling support */
+       isif_write(isif->isif_cfg.base_addr, 0xffff, CULH);
+       isif_write(isif->isif_cfg.base_addr, 0xff, CULV);
+
+       /* Set default offset and gain */
+       isif_config_gain_offset(isif);
+       vpss_select_ccdc_source(source);
+}
+
+/*
+ * vpfe_isif_register_entities() - isif register entity
+ * @isif - pointer to isif subdevice structure.
+ * @vdev: pointer to v4l2 device structure.
+ */
+int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
+                           struct v4l2_device *vdev)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
+       unsigned int flags;
+       int ret;
+
+       /* Register the subdev */
+       ret = v4l2_device_register_subdev(vdev, &isif->subdev);
+       if (ret < 0)
+               return ret;
+
+       isif_restore_defaults(isif);
+       ret = vpfe_video_register(&isif->video_out, vdev);
+       if (ret) {
+               pr_err("Failed to register isif video out device\n");
+               goto out_video_register;
+       }
+       isif->video_out.vpfe_dev = vpfe_dev;
+       flags = 0;
+       /* connect isif to video node */
+       ret = media_entity_create_link(&isif->subdev.entity, 1,
+                                      &isif->video_out.video_dev.entity,
+                                      0, flags);
+       if (ret < 0)
+               goto out_create_link;
+       return 0;
+out_create_link:
+       vpfe_video_unregister(&isif->video_out);
+out_video_register:
+       v4l2_device_unregister_subdev(&isif->subdev);
+       return ret;
+}
+
+/* -------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+static int vpfe_isif_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vpfe_isif_device *isif =
+            container_of(ctrl->handler, struct vpfe_isif_device, ctrls);
+       struct isif_oper_config *config = &isif->isif_cfg;
+
+       switch (ctrl->id) {
+       case VPFE_CID_DPCM_PREDICTOR:
+               config->bayer.dpcm_predictor = ctrl->val;
+               break;
+
+       case VPFE_ISIF_CID_CRGAIN:
+               config->isif_gain_params.cr_gain = ctrl->val;
+               break;
+
+       case VPFE_ISIF_CID_CGRGAIN:
+               config->isif_gain_params.cgr_gain = ctrl->val;
+               break;
+
+       case VPFE_ISIF_CID_CGBGAIN:
+               config->isif_gain_params.cgb_gain = ctrl->val;
+               break;
+
+       case VPFE_ISIF_CID_CBGAIN:
+               config->isif_gain_params.cb_gain = ctrl->val;
+               break;
+
+       case VPFE_ISIF_CID_GAIN_OFFSET:
+               config->isif_gain_params.offset = ctrl->val;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops vpfe_isif_ctrl_ops = {
+       .s_ctrl = vpfe_isif_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_dpcm_pred = {
+       .ops = &vpfe_isif_ctrl_ops,
+       .id = VPFE_CID_DPCM_PREDICTOR,
+       .name = "DPCM Predictor",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = 1,
+       .step = 1,
+       .def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_crgain = {
+       .ops = &vpfe_isif_ctrl_ops,
+       .id = VPFE_ISIF_CID_CRGAIN,
+       .name = "CRGAIN",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = (1 << 12) - 1,
+       .step = 1,
+       .def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_cgrgain = {
+       .ops = &vpfe_isif_ctrl_ops,
+       .id = VPFE_ISIF_CID_CGRGAIN,
+       .name = "CGRGAIN",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = (1 << 12) - 1,
+       .step = 1,
+       .def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_cgbgain = {
+       .ops = &vpfe_isif_ctrl_ops,
+       .id = VPFE_ISIF_CID_CGBGAIN,
+       .name = "CGBGAIN",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = (1 << 12) - 1,
+       .step = 1,
+       .def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_cbgain = {
+       .ops = &vpfe_isif_ctrl_ops,
+       .id = VPFE_ISIF_CID_CBGAIN,
+       .name = "CBGAIN",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = (1 << 12) - 1,
+       .step = 1,
+       .def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_gain_offset = {
+       .ops = &vpfe_isif_ctrl_ops,
+       .id = VPFE_ISIF_CID_GAIN_OFFSET,
+       .name = "Gain Offset",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = (1 << 12) - 1,
+       .step = 1,
+       .def = 0,
+};
+
+static void isif_remove(struct vpfe_isif_device *isif,
+                       struct platform_device *pdev)
+{
+       struct resource *res;
+       int i = 0;
+
+       iounmap(isif->isif_cfg.base_addr);
+       iounmap(isif->isif_cfg.linear_tbl0_addr);
+       iounmap(isif->isif_cfg.linear_tbl1_addr);
+
+       while (i < 3) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               if (res)
+                       release_mem_region(res->start,
+                                          res->end - res->start + 1);
+               i++;
+       }
+}
+
+static void isif_config_defaults(struct vpfe_isif_device *isif)
+{
+       isif->isif_cfg.ycbcr.v4l2_pix_fmt = V4L2_PIX_FMT_UYVY;
+       isif->isif_cfg.ycbcr.pix_fmt = ISIF_PIXFMT_YCBCR_8BIT;
+       isif->isif_cfg.ycbcr.frm_fmt = ISIF_FRMFMT_INTERLACED;
+       isif->isif_cfg.ycbcr.fid_pol = VPFE_PINPOL_POSITIVE;
+       isif->isif_cfg.ycbcr.vd_pol = VPFE_PINPOL_POSITIVE;
+       isif->isif_cfg.ycbcr.hd_pol = VPFE_PINPOL_POSITIVE;
+       isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY;
+       isif->isif_cfg.ycbcr.buf_type = ISIF_BUFTYPE_FLD_INTERLEAVED;
+
+       isif->isif_cfg.bayer.v4l2_pix_fmt = V4L2_PIX_FMT_SGRBG10ALAW8;
+       isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW;
+       isif->isif_cfg.bayer.frm_fmt = ISIF_FRMFMT_PROGRESSIVE;
+       isif->isif_cfg.bayer.fid_pol = VPFE_PINPOL_POSITIVE;
+       isif->isif_cfg.bayer.vd_pol = VPFE_PINPOL_POSITIVE;
+       isif->isif_cfg.bayer.hd_pol = VPFE_PINPOL_POSITIVE;
+       isif->isif_cfg.bayer.cfa_pat = ISIF_CFA_PAT_MOSAIC;
+       isif->isif_cfg.bayer.data_msb = ISIF_BIT_MSB_11;
+       isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
+}
+/*
+ * vpfe_isif_init() - Initialize V4L2 subdev and media entity
+ * @isif: VPFE isif module
+ * @pdev: Pointer to platform device structure.
+ * Return 0 on success and a negative error code on failure.
+ */
+int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev)
+{
+       struct v4l2_subdev *sd = &isif->subdev;
+       struct media_pad *pads = &isif->pads[0];
+       struct media_entity *me = &sd->entity;
+       static resource_size_t res_len;
+       struct resource *res;
+       void *__iomem addr;
+       int status;
+       int i = 0;
+
+       /* Get the ISIF base address, linearization table0 and table1 addr. */
+       while (i < 3) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               if (!res) {
+                       status = -ENOENT;
+                       goto fail_nobase_res;
+               }
+               res_len = res->end - res->start + 1;
+               res = request_mem_region(res->start, res_len, res->name);
+               if (!res) {
+                       status = -EBUSY;
+                       goto fail_nobase_res;
+               }
+               addr = ioremap_nocache(res->start, res_len);
+               if (!addr) {
+                       status = -EBUSY;
+                       goto fail_base_iomap;
+               }
+               switch (i) {
+               case 0:
+                       /* ISIF base address */
+                       isif->isif_cfg.base_addr = addr;
+                       break;
+               case 1:
+                       /* ISIF linear tbl0 address */
+                       isif->isif_cfg.linear_tbl0_addr = addr;
+                       break;
+               default:
+                       /* ISIF linear tbl0 address */
+                       isif->isif_cfg.linear_tbl1_addr = addr;
+                       break;
+               }
+               i++;
+       }
+       davinci_cfg_reg(DM365_VIN_CAM_WEN);
+       davinci_cfg_reg(DM365_VIN_CAM_VD);
+       davinci_cfg_reg(DM365_VIN_CAM_HD);
+       davinci_cfg_reg(DM365_VIN_YIN4_7_EN);
+       davinci_cfg_reg(DM365_VIN_YIN0_3_EN);
+
+       /* queue ops */
+       isif->video_out.ops = &isif_video_ops;
+       v4l2_subdev_init(sd, &isif_v4l2_ops);
+       sd->internal_ops = &isif_v4l2_internal_ops;
+       strlcpy(sd->name, "DAVINCI ISIF", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
+       v4l2_set_subdevdata(sd, isif);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+       pads[ISIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[ISIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+       isif->input = ISIF_INPUT_NONE;
+       isif->output = ISIF_OUTPUT_NONE;
+       me->ops = &isif_media_ops;
+       status = media_entity_init(me, ISIF_PADS_NUM, pads, 0);
+       if (status)
+               goto isif_fail;
+       isif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       status = vpfe_video_init(&isif->video_out, "ISIF");
+       if (status) {
+               pr_err("Failed to init isif-out video device\n");
+               goto isif_fail;
+       }
+       v4l2_ctrl_handler_init(&isif->ctrls, 6);
+       v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_crgain, NULL);
+       v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgrgain, NULL);
+       v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgbgain, NULL);
+       v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cbgain, NULL);
+       v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_gain_offset, NULL);
+       v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_dpcm_pred, NULL);
+
+       v4l2_ctrl_handler_setup(&isif->ctrls);
+       sd->ctrl_handler = &isif->ctrls;
+       isif_config_defaults(isif);
+       return 0;
+fail_base_iomap:
+       release_mem_region(res->start, res_len);
+       i--;
+fail_nobase_res:
+       if (isif->isif_cfg.base_addr)
+               iounmap(isif->isif_cfg.base_addr);
+       if (isif->isif_cfg.linear_tbl0_addr)
+               iounmap(isif->isif_cfg.linear_tbl0_addr);
+
+       while (i >= 0) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               release_mem_region(res->start, res_len);
+               i--;
+       }
+       return status;
+isif_fail:
+       v4l2_ctrl_handler_free(&isif->ctrls);
+       isif_remove(isif, pdev);
+       return status;
+}
+
+/*
+ * vpfe_isif_cleanup - isif module cleanup
+ * @isif: pointer to isif subdevice
+ * @dev: pointer to platform device structure
+ */
+void
+vpfe_isif_cleanup(struct vpfe_isif_device *isif, struct platform_device *pdev)
+{
+       isif_remove(isif, pdev);
+}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.h b/drivers/staging/media/davinci_vpfe/dm365_isif.h
new file mode 100644 (file)
index 0000000..473fd2c
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_ISIF_H
+#define _DAVINCI_VPFE_DM365_ISIF_H
+
+#include <linux/platform_device.h>
+
+#include <mach/mux.h>
+
+#include <media/davinci/vpfe_types.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#include "davinci_vpfe_user.h"
+#include "dm365_isif_regs.h"
+#include "vpfe_video.h"
+
+#define ISIF_CULLING_HCAPT_ODD         0xff
+#define ISIF_CULLING_HCAPT_EVEN                0xff
+#define ISIF_CULLING_VCAPT             0xff
+
+#define ISIF_CADU_BITS                 0x07ff
+#define ISIF_CADL_BITS                 0x0ffff
+
+enum isif_pixfmt {
+       ISIF_PIXFMT_RAW = 0,
+       ISIF_PIXFMT_YCBCR_16BIT = 1,
+       ISIF_PIXFMT_YCBCR_8BIT = 2,
+};
+
+enum isif_frmfmt {
+       ISIF_FRMFMT_PROGRESSIVE = 0,
+       ISIF_FRMFMT_INTERLACED = 1,
+};
+
+/* PIXEL ORDER IN MEMORY from LSB to MSB */
+/* only applicable for 8-bit input mode  */
+enum isif_pixorder {
+       ISIF_PIXORDER_YCBYCR = 0,
+       ISIF_PIXORDER_CBYCRY = 1,
+};
+
+enum isif_buftype {
+       ISIF_BUFTYPE_FLD_INTERLEAVED = 0,
+       ISIF_BUFTYPE_FLD_SEPARATED = 1,
+};
+
+struct isif_ycbcr_config {
+       /* v4l2 pixel format */
+       unsigned long v4l2_pix_fmt;
+       /* isif pixel format */
+       enum isif_pixfmt pix_fmt;
+       /* isif frame format */
+       enum isif_frmfmt frm_fmt;
+       /* isif crop window */
+       struct v4l2_rect win;
+       /* field polarity */
+       enum vpfe_pin_pol fid_pol;
+       /* interface VD polarity */
+       enum vpfe_pin_pol vd_pol;
+       /* interface HD polarity */
+       enum vpfe_pin_pol hd_pol;
+       /* isif pix order. Only used for ycbcr capture */
+       enum isif_pixorder pix_order;
+       /* isif buffer type. Only used for ycbcr capture */
+       enum isif_buftype buf_type;
+};
+
+enum isif_cfa_pattern {
+       ISIF_CFA_PAT_MOSAIC = 0,
+       ISIF_CFA_PAT_STRIPE = 1,
+};
+
+enum isif_data_msb {
+       /* MSB b15 */
+       ISIF_BIT_MSB_15 = 0,
+       /* MSB b14 */
+       ISIF_BIT_MSB_14 = 1,
+       /* MSB b13 */
+       ISIF_BIT_MSB_13 = 2,
+       /* MSB b12 */
+       ISIF_BIT_MSB_12 = 3,
+       /* MSB b11 */
+       ISIF_BIT_MSB_11 = 4,
+       /* MSB b10 */
+       ISIF_BIT_MSB_10 = 5,
+       /* MSB b9 */
+       ISIF_BIT_MSB_9 = 6,
+       /* MSB b8 */
+       ISIF_BIT_MSB_8 = 7,
+       /* MSB b7 */
+       ISIF_BIT_MSB_7 = 8,
+};
+
+struct isif_params_raw {
+       /* v4l2 pixel format */
+       unsigned long v4l2_pix_fmt;
+       /* isif pixel format */
+       enum isif_pixfmt pix_fmt;
+       /* isif frame format */
+       enum isif_frmfmt frm_fmt;
+       /* video window */
+       struct v4l2_rect win;
+       /* field polarity */
+       enum vpfe_pin_pol fid_pol;
+       /* interface VD polarity */
+       enum vpfe_pin_pol vd_pol;
+       /* interface HD polarity */
+       enum vpfe_pin_pol hd_pol;
+       /* buffer type. Applicable for interlaced mode */
+       enum isif_buftype buf_type;
+       /* cfa pattern */
+       enum isif_cfa_pattern cfa_pat;
+       /* Data MSB position */
+       enum isif_data_msb data_msb;
+       /* Enable horizontal flip */
+       unsigned char horz_flip_en;
+       /* Enable image invert vertically */
+       unsigned char image_invert_en;
+       unsigned char dpcm_predictor;
+       struct vpfe_isif_raw_config config_params;
+};
+
+enum isif_data_pack {
+       ISIF_PACK_16BIT = 0,
+       ISIF_PACK_12BIT = 1,
+       ISIF_PACK_8BIT = 2,
+};
+
+struct isif_gain_values {
+       unsigned int cr_gain;
+       unsigned int cgr_gain;
+       unsigned int cgb_gain;
+       unsigned int cb_gain;
+       unsigned int offset;
+};
+
+struct isif_oper_config {
+       struct isif_ycbcr_config ycbcr;
+       struct isif_params_raw bayer;
+       enum isif_data_pack data_pack;
+       struct isif_gain_values isif_gain_params;
+       void *__iomem base_addr;
+       void *__iomem linear_tbl0_addr;
+       void *__iomem linear_tbl1_addr;
+};
+
+#define ISIF_PAD_SINK      0
+#define ISIF_PAD_SOURCE    1
+
+#define ISIF_PADS_NUM      2
+
+enum isif_input_entity {
+       ISIF_INPUT_NONE = 0,
+       ISIF_INPUT_PARALLEL = 1,
+};
+
+#define ISIF_OUTPUT_NONE       (0)
+#define ISIF_OUTPUT_MEMORY     (1 << 0)
+#define ISIF_OUTPUT_IPIPEIF    (1 << 1)
+
+struct vpfe_isif_device {
+       struct v4l2_subdev              subdev;
+       struct media_pad                pads[ISIF_PADS_NUM];
+       struct v4l2_mbus_framefmt       formats[ISIF_PADS_NUM];
+       enum isif_input_entity          input;
+       unsigned int                    output;
+       struct v4l2_ctrl_handler        ctrls;
+       struct v4l2_rect                crop;
+       struct isif_oper_config         isif_cfg;
+       struct vpfe_video_device        video_out;
+};
+
+enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev);
+void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif);
+int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
+                               struct v4l2_device *dev);
+int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev);
+void vpfe_isif_cleanup(struct vpfe_isif_device *vpfe_isif,
+                      struct platform_device *pdev);
+void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif);
+void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif);
+
+#endif         /* _DAVINCI_VPFE_DM365_ISIF_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h b/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h
new file mode 100644 (file)
index 0000000..8aceabb
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_ISIF_REGS_H
+#define _DAVINCI_VPFE_DM365_ISIF_REGS_H
+
+/* ISIF registers relative offsets */
+#define SYNCEN                                 0x00
+#define MODESET                                        0x04
+#define HDW                                    0x08
+#define VDW                                    0x0c
+#define PPLN                                   0x10
+#define LPFR                                   0x14
+#define SPH                                    0x18
+#define LNH                                    0x1c
+#define SLV0                                   0x20
+#define SLV1                                   0x24
+#define LNV                                    0x28
+#define CULH                                   0x2c
+#define CULV                                   0x30
+#define HSIZE                                  0x34
+#define SDOFST                                 0x38
+#define CADU                                   0x3c
+#define CADL                                   0x40
+#define LINCFG0                                        0x44
+#define LINCFG1                                        0x48
+#define CCOLP                                  0x4c
+#define CRGAIN                                 0x50
+#define CGRGAIN                                        0x54
+#define CGBGAIN                                        0x58
+#define CBGAIN                                 0x5c
+#define COFSTA                                 0x60
+#define FLSHCFG0                               0x64
+#define FLSHCFG1                               0x68
+#define FLSHCFG2                               0x6c
+#define VDINT0                                 0x70
+#define VDINT1                                 0x74
+#define VDINT2                                 0x78
+#define MISC                                   0x7c
+#define CGAMMAWD                               0x80
+#define REC656IF                               0x84
+#define CCDCFG                                 0x88
+/*****************************************************
+* Defect Correction registers
+*****************************************************/
+#define DFCCTL                                 0x8c
+#define VDFSATLV                               0x90
+#define DFCMEMCTL                              0x94
+#define DFCMEM0                                        0x98
+#define DFCMEM1                                        0x9c
+#define DFCMEM2                                        0xa0
+#define DFCMEM3                                        0xa4
+#define DFCMEM4                                        0xa8
+/****************************************************
+* Black Clamp registers
+****************************************************/
+#define CLAMPCFG                               0xac
+#define CLDCOFST                               0xb0
+#define CLSV                                   0xb4
+#define CLHWIN0                                        0xb8
+#define CLHWIN1                                        0xbc
+#define CLHWIN2                                        0xc0
+#define CLVRV                                  0xc4
+#define CLVWIN0                                        0xc8
+#define CLVWIN1                                        0xcc
+#define CLVWIN2                                        0xd0
+#define CLVWIN3                                        0xd4
+/****************************************************
+* Lense Shading Correction
+****************************************************/
+#define DATAHOFST                              0xd8
+#define DATAVOFST                              0xdc
+#define LSCHVAL                                        0xe0
+#define LSCVVAL                                        0xe4
+#define TWODLSCCFG                             0xe8
+#define TWODLSCOFST                            0xec
+#define TWODLSCINI                             0xf0
+#define TWODLSCGRBU                            0xf4
+#define TWODLSCGRBL                            0xf8
+#define TWODLSCGROF                            0xfc
+#define TWODLSCORBU                            0x100
+#define TWODLSCORBL                            0x104
+#define TWODLSCOROF                            0x108
+#define TWODLSCIRQEN                           0x10c
+#define TWODLSCIRQST                           0x110
+/****************************************************
+* Data formatter
+****************************************************/
+#define FMTCFG                                 0x114
+#define FMTPLEN                                        0x118
+#define FMTSPH                                 0x11c
+#define FMTLNH                                 0x120
+#define FMTSLV                                 0x124
+#define FMTLNV                                 0x128
+#define FMTRLEN                                        0x12c
+#define FMTHCNT                                        0x130
+#define FMTAPTR_BASE                           0x134
+/* Below macro for addresses FMTAPTR0 - FMTAPTR15 */
+#define FMTAPTR(i)                     (FMTAPTR_BASE + (i * 4))
+#define FMTPGMVF0                              0x174
+#define FMTPGMVF1                              0x178
+#define FMTPGMAPU0                             0x17c
+#define FMTPGMAPU1                             0x180
+#define FMTPGMAPS0                             0x184
+#define FMTPGMAPS1                             0x188
+#define FMTPGMAPS2                             0x18c
+#define FMTPGMAPS3                             0x190
+#define FMTPGMAPS4                             0x194
+#define FMTPGMAPS5                             0x198
+#define FMTPGMAPS6                             0x19c
+#define FMTPGMAPS7                             0x1a0
+/************************************************
+* Color Space Converter
+************************************************/
+#define CSCCTL                                 0x1a4
+#define CSCM0                                  0x1a8
+#define CSCM1                                  0x1ac
+#define CSCM2                                  0x1b0
+#define CSCM3                                  0x1b4
+#define CSCM4                                  0x1b8
+#define CSCM5                                  0x1bc
+#define CSCM6                                  0x1c0
+#define CSCM7                                  0x1c4
+#define OBWIN0                                 0x1c8
+#define OBWIN1                                 0x1cc
+#define OBWIN2                                 0x1d0
+#define OBWIN3                                 0x1d4
+#define OBVAL0                                 0x1d8
+#define OBVAL1                                 0x1dc
+#define OBVAL2                                 0x1e0
+#define OBVAL3                                 0x1e4
+#define OBVAL4                                 0x1e8
+#define OBVAL5                                 0x1ec
+#define OBVAL6                                 0x1f0
+#define OBVAL7                                 0x1f4
+#define CLKCTL                                 0x1f8
+
+/* Masks & Shifts below */
+#define START_PX_HOR_MASK                      0x7fff
+#define NUM_PX_HOR_MASK                                0x7fff
+#define START_VER_ONE_MASK                     0x7fff
+#define START_VER_TWO_MASK                     0x7fff
+#define NUM_LINES_VER                          0x7fff
+
+/* gain - offset masks */
+#define OFFSET_MASK                            0xfff
+#define GAIN_SDRAM_EN_SHIFT                    12
+#define GAIN_IPIPE_EN_SHIFT                    13
+#define GAIN_H3A_EN_SHIFT                      14
+#define OFST_SDRAM_EN_SHIFT                    8
+#define OFST_IPIPE_EN_SHIFT                    9
+#define OFST_H3A_EN_SHIFT                      10
+#define GAIN_OFFSET_EN_MASK                    0x7700
+
+/* Culling */
+#define CULL_PAT_EVEN_LINE_SHIFT               8
+
+/* CCDCFG register */
+#define ISIF_YCINSWP_RAW                       (0x00 << 4)
+#define ISIF_YCINSWP_YCBCR                     (0x01 << 4)
+#define ISIF_CCDCFG_FIDMD_LATCH_VSYNC          (0x00 << 6)
+#define ISIF_CCDCFG_WENLOG_AND                 (0x00 << 8)
+#define ISIF_CCDCFG_TRGSEL_WEN                 (0x00 << 9)
+#define ISIF_CCDCFG_EXTRG_DISABLE              (0x00 << 10)
+#define ISIF_LATCH_ON_VSYNC_DISABLE            (0x01 << 15)
+#define ISIF_LATCH_ON_VSYNC_ENABLE             (0x00 << 15)
+#define ISIF_DATA_PACK_MASK                    0x03
+#define ISIF_PIX_ORDER_SHIFT                   11
+#define ISIF_PIX_ORDER_MASK                    0x01
+#define ISIF_BW656_ENABLE                      (0x01 << 5)
+
+/* MODESET registers */
+#define ISIF_VDHDOUT_INPUT                     (0x00 << 0)
+#define ISIF_INPUT_MASK                                0x03
+#define ISIF_INPUT_SHIFT                       12
+#define ISIF_FID_POL_MASK                      0x01
+#define ISIF_FID_POL_SHIFT                     4
+#define ISIF_HD_POL_MASK                       0x01
+#define ISIF_HD_POL_SHIFT                      3
+#define ISIF_VD_POL_MASK                       0x01
+#define ISIF_VD_POL_SHIFT                      2
+#define ISIF_DATAPOL_NORMAL                    0x00
+#define ISIF_DATAPOL_MASK                      0x01
+#define ISIF_DATAPOL_SHIFT                     6
+#define ISIF_EXWEN_DISABLE                     0x00
+#define ISIF_EXWEN_MASK                                0x01
+#define ISIF_EXWEN_SHIFT                       5
+#define ISIF_FRM_FMT_MASK                      0x01
+#define ISIF_FRM_FMT_SHIFT                     7
+#define ISIF_DATASFT_MASK                      0x07
+#define ISIF_DATASFT_SHIFT                     8
+#define ISIF_LPF_SHIFT                         14
+#define ISIF_LPF_MASK                          0x1
+
+/* GAMMAWD registers */
+#define ISIF_ALAW_GAMA_WD_MASK                 0xf
+#define ISIF_ALAW_GAMA_WD_SHIFT                        1
+#define ISIF_ALAW_ENABLE                       0x01
+#define ISIF_GAMMAWD_CFA_MASK                  0x01
+#define ISIF_GAMMAWD_CFA_SHIFT                 5
+
+/* HSIZE registers */
+#define ISIF_HSIZE_FLIP_MASK                   0x01
+#define ISIF_HSIZE_FLIP_SHIFT                  12
+#define ISIF_LINEOFST_MASK                     0xfff
+
+/* MISC registers */
+#define ISIF_DPCM_EN_SHIFT                     12
+#define ISIF_DPCM_PREDICTOR_SHIFT              13
+#define ISIF_DPCM_PREDICTOR_MASK               1
+
+/* Black clamp related */
+#define ISIF_BC_DCOFFSET_MASK                  0x1fff
+#define ISIF_BC_MODE_COLOR_MASK                        1
+#define ISIF_BC_MODE_COLOR_SHIFT               4
+#define ISIF_HORZ_BC_MODE_MASK                 3
+#define ISIF_HORZ_BC_MODE_SHIFT                        1
+#define ISIF_HORZ_BC_WIN_COUNT_MASK            0x1f
+#define ISIF_HORZ_BC_WIN_SEL_SHIFT             5
+#define ISIF_HORZ_BC_PIX_LIMIT_SHIFT           6
+#define ISIF_HORZ_BC_WIN_H_SIZE_MASK           3
+#define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT          8
+#define ISIF_HORZ_BC_WIN_V_SIZE_MASK           3
+#define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT          12
+#define ISIF_HORZ_BC_WIN_START_H_MASK          0x1fff
+#define ISIF_HORZ_BC_WIN_START_V_MASK          0x1fff
+#define ISIF_VERT_BC_OB_H_SZ_MASK              7
+#define ISIF_VERT_BC_RST_VAL_SEL_MASK          3
+#define ISIF_VERT_BC_RST_VAL_SEL_SHIFT         4
+#define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT       8
+#define ISIF_VERT_BC_OB_START_HORZ_MASK                0x1fff
+#define ISIF_VERT_BC_OB_START_VERT_MASK                0x1fff
+#define ISIF_VERT_BC_OB_VERT_SZ_MASK           0x1fff
+#define ISIF_VERT_BC_RST_VAL_MASK              0xfff
+#define ISIF_BC_VERT_START_SUB_V_MASK          0x1fff
+
+/* VDFC registers */
+#define ISIF_VDFC_EN_SHIFT                     4
+#define ISIF_VDFC_CORR_MOD_MASK                        3
+#define ISIF_VDFC_CORR_MOD_SHIFT               5
+#define ISIF_VDFC_CORR_WHOLE_LN_SHIFT          7
+#define ISIF_VDFC_LEVEL_SHFT_MASK              7
+#define ISIF_VDFC_LEVEL_SHFT_SHIFT             8
+#define ISIF_VDFC_SAT_LEVEL_MASK               0xfff
+#define ISIF_VDFC_POS_MASK                     0x1fff
+#define ISIF_DFCMEMCTL_DFCMARST_SHIFT          2
+
+/* CSC registers */
+#define ISIF_CSC_COEF_INTEG_MASK               7
+#define ISIF_CSC_COEF_DECIMAL_MASK             0x1f
+#define ISIF_CSC_COEF_INTEG_SHIFT              5
+#define ISIF_CSCM_MSB_SHIFT                    8
+#define ISIF_DF_CSC_SPH_MASK                   0x1fff
+#define ISIF_DF_CSC_LNH_MASK                   0x1fff
+#define ISIF_DF_CSC_SLV_MASK                   0x1fff
+#define ISIF_DF_CSC_LNV_MASK                   0x1fff
+#define ISIF_DF_NUMLINES                       0x7fff
+#define ISIF_DF_NUMPIX                         0x1fff
+
+/* Offsets for LSC/DFC/Gain */
+#define ISIF_DATA_H_OFFSET_MASK                        0x1fff
+#define ISIF_DATA_V_OFFSET_MASK                        0x1fff
+
+/* Linearization */
+#define ISIF_LIN_CORRSFT_MASK                  7
+#define ISIF_LIN_CORRSFT_SHIFT                 4
+#define ISIF_LIN_SCALE_FACT_INTEG_SHIFT                10
+#define ISIF_LIN_SCALE_FACT_DECIMAL_MASK       0x3ff
+#define ISIF_LIN_ENTRY_MASK                    0x3ff
+
+/* masks and shifts*/
+#define ISIF_SYNCEN_VDHDEN_MASK                        (1 << 0)
+#define ISIF_SYNCEN_WEN_MASK                   (1 << 1)
+#define ISIF_SYNCEN_WEN_SHIFT                  1
+
+#endif         /* _DAVINCI_VPFE_DM365_ISIF_REGS_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
new file mode 100644 (file)
index 0000000..9cb0262
--- /dev/null
@@ -0,0 +1,1999 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ *
+ *
+ * Resizer allows upscaling or downscaling a image to a desired
+ * resolution. There are 2 resizer modules. both operating on the
+ * same input image, but can have different output resolution.
+ */
+
+#include "dm365_ipipe_hw.h"
+#include "dm365_resizer.h"
+
+#define MIN_IN_WIDTH           32
+#define MIN_IN_HEIGHT          32
+#define MAX_IN_WIDTH           4095
+#define MAX_IN_HEIGHT          4095
+#define MIN_OUT_WIDTH          16
+#define MIN_OUT_HEIGHT         2
+
+static const unsigned int resizer_input_formats[] = {
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_Y8_1X8,
+       V4L2_MBUS_FMT_UV8_1X8,
+       V4L2_MBUS_FMT_SGRBG12_1X12,
+};
+
+static const unsigned int resizer_output_formats[] = {
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_Y8_1X8,
+       V4L2_MBUS_FMT_UV8_1X8,
+       V4L2_MBUS_FMT_YDYUYDYV8_1X16,
+       V4L2_MBUS_FMT_SGRBG12_1X12,
+};
+
+/* resizer_calculate_line_length() - This function calculates the line length of
+ *                                  various image planes at the input and
+ *                                  output.
+ */
+static void
+resizer_calculate_line_length(enum v4l2_mbus_pixelcode pix, int width,
+                     int height, int *line_len, int *line_len_c)
+{
+       *line_len = 0;
+       *line_len_c = 0;
+
+       if (pix == V4L2_MBUS_FMT_UYVY8_2X8 ||
+           pix == V4L2_MBUS_FMT_SGRBG12_1X12) {
+               *line_len = width << 1;
+       } else if (pix == V4L2_MBUS_FMT_Y8_1X8 ||
+                  pix == V4L2_MBUS_FMT_UV8_1X8) {
+               *line_len = width;
+               *line_len_c = width;
+       } else {
+               /* YUV 420 */
+               /* round width to upper 32 byte boundary */
+               *line_len = width;
+               *line_len_c = width;
+       }
+       /* adjust the line len to be a multiple of 32 */
+       *line_len += 31;
+       *line_len &= ~0x1f;
+       *line_len_c += 31;
+       *line_len_c &= ~0x1f;
+}
+
+static inline int
+resizer_validate_output_image_format(struct device *dev,
+                                    struct v4l2_mbus_framefmt *format,
+                                    int *in_line_len, int *in_line_len_c)
+{
+       if (format->code != V4L2_MBUS_FMT_UYVY8_2X8 &&
+           format->code != V4L2_MBUS_FMT_Y8_1X8 &&
+           format->code != V4L2_MBUS_FMT_UV8_1X8 &&
+           format->code != V4L2_MBUS_FMT_YDYUYDYV8_1X16 &&
+           format->code != V4L2_MBUS_FMT_SGRBG12_1X12) {
+               dev_err(dev, "Invalid Mbus format, %d\n", format->code);
+               return -EINVAL;
+       }
+       if (!format->width || !format->height) {
+               dev_err(dev, "invalid width or height\n");
+               return -EINVAL;
+       }
+       resizer_calculate_line_length(format->code, format->width,
+               format->height, in_line_len, in_line_len_c);
+       return 0;
+}
+
+static void
+resizer_configure_passthru(struct vpfe_resizer_device *resizer, int bypass)
+{
+       struct resizer_params *param = &resizer->config;
+
+       param->rsz_rsc_param[RSZ_A].cen = DISABLE;
+       param->rsz_rsc_param[RSZ_A].yen = DISABLE;
+       param->rsz_rsc_param[RSZ_A].v_phs_y = 0;
+       param->rsz_rsc_param[RSZ_A].v_phs_c = 0;
+       param->rsz_rsc_param[RSZ_A].v_dif = 256;
+       param->rsz_rsc_param[RSZ_A].v_lpf_int_y = 0;
+       param->rsz_rsc_param[RSZ_A].v_lpf_int_c = 0;
+       param->rsz_rsc_param[RSZ_A].h_phs = 0;
+       param->rsz_rsc_param[RSZ_A].h_dif = 256;
+       param->rsz_rsc_param[RSZ_A].h_lpf_int_y = 0;
+       param->rsz_rsc_param[RSZ_A].h_lpf_int_c = 0;
+       param->rsz_rsc_param[RSZ_A].dscale_en = DISABLE;
+       param->rsz2rgb[RSZ_A].rgb_en = DISABLE;
+       param->rsz_en[RSZ_A] = ENABLE;
+       param->rsz_en[RSZ_B] = DISABLE;
+       if (bypass) {
+               param->rsz_rsc_param[RSZ_A].i_vps = 0;
+               param->rsz_rsc_param[RSZ_A].i_hps = 0;
+               /* Raw Bypass */
+               param->rsz_common.passthrough = BYPASS_ON;
+       }
+}
+
+static void
+configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index,
+                            void *output_spec, unsigned char partial,
+                            unsigned flag)
+{
+       struct resizer_params *param = &resizer->config;
+       struct v4l2_mbus_framefmt *outformat;
+       struct vpfe_rsz_output_spec *output;
+
+       if (index == RSZ_A &&
+           resizer->resizer_a.output == RESIZER_OUTPUT_NONE) {
+               param->rsz_en[index] = DISABLE;
+               return;
+       }
+       if (index == RSZ_B &&
+           resizer->resizer_b.output == RESIZER_OUTPUT_NONE) {
+               param->rsz_en[index] = DISABLE;
+               return;
+       }
+       output = (struct vpfe_rsz_output_spec *)output_spec;
+       param->rsz_en[index] = ENABLE;
+       if (partial) {
+               param->rsz_rsc_param[index].h_flip = output->h_flip;
+               param->rsz_rsc_param[index].v_flip = output->v_flip;
+               param->rsz_rsc_param[index].v_typ_y = output->v_typ_y;
+               param->rsz_rsc_param[index].v_typ_c = output->v_typ_c;
+               param->rsz_rsc_param[index].v_lpf_int_y =
+                                               output->v_lpf_int_y;
+               param->rsz_rsc_param[index].v_lpf_int_c =
+                                               output->v_lpf_int_c;
+               param->rsz_rsc_param[index].h_typ_y = output->h_typ_y;
+               param->rsz_rsc_param[index].h_typ_c = output->h_typ_c;
+               param->rsz_rsc_param[index].h_lpf_int_y =
+                                               output->h_lpf_int_y;
+               param->rsz_rsc_param[index].h_lpf_int_c =
+                                               output->h_lpf_int_c;
+               param->rsz_rsc_param[index].dscale_en =
+                                               output->en_down_scale;
+               param->rsz_rsc_param[index].h_dscale_ave_sz =
+                                               output->h_dscale_ave_sz;
+               param->rsz_rsc_param[index].v_dscale_ave_sz =
+                                               output->v_dscale_ave_sz;
+               param->ext_mem_param[index].user_y_ofst =
+                                   (output->user_y_ofst + 31) & ~0x1f;
+               param->ext_mem_param[index].user_c_ofst =
+                                   (output->user_c_ofst + 31) & ~0x1f;
+               return;
+       }
+
+       if (index == RSZ_A)
+               outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
+       else
+               outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
+       param->rsz_rsc_param[index].o_vsz = outformat->height - 1;
+       param->rsz_rsc_param[index].o_hsz = outformat->width - 1;
+       param->ext_mem_param[index].rsz_sdr_ptr_s_y = output->vst_y;
+       param->ext_mem_param[index].rsz_sdr_ptr_e_y = outformat->height;
+       param->ext_mem_param[index].rsz_sdr_ptr_s_c = output->vst_c;
+       param->ext_mem_param[index].rsz_sdr_ptr_e_c = outformat->height;
+
+       if (!flag)
+               return;
+       /* update common parameters */
+       param->rsz_rsc_param[index].h_flip = output->h_flip;
+       param->rsz_rsc_param[index].v_flip = output->v_flip;
+       param->rsz_rsc_param[index].v_typ_y = output->v_typ_y;
+       param->rsz_rsc_param[index].v_typ_c = output->v_typ_c;
+       param->rsz_rsc_param[index].v_lpf_int_y = output->v_lpf_int_y;
+       param->rsz_rsc_param[index].v_lpf_int_c = output->v_lpf_int_c;
+       param->rsz_rsc_param[index].h_typ_y = output->h_typ_y;
+       param->rsz_rsc_param[index].h_typ_c = output->h_typ_c;
+       param->rsz_rsc_param[index].h_lpf_int_y = output->h_lpf_int_y;
+       param->rsz_rsc_param[index].h_lpf_int_c = output->h_lpf_int_c;
+       param->rsz_rsc_param[index].dscale_en = output->en_down_scale;
+       param->rsz_rsc_param[index].h_dscale_ave_sz = output->h_dscale_ave_sz;
+       param->rsz_rsc_param[index].v_dscale_ave_sz = output->h_dscale_ave_sz;
+       param->ext_mem_param[index].user_y_ofst =
+                                       (output->user_y_ofst + 31) & ~0x1f;
+       param->ext_mem_param[index].user_c_ofst =
+                                       (output->user_c_ofst + 31) & ~0x1f;
+}
+
+/*
+ * resizer_calculate_resize_ratios() - Calculates resize ratio for resizer
+ *                                   A or B. This is called after setting
+ *                                  the input size or output size.
+ * @resizer: Pointer to VPFE resizer subdevice.
+ * @index: index RSZ_A-resizer-A RSZ_B-resizer-B.
+ */
+void
+resizer_calculate_resize_ratios(struct vpfe_resizer_device *resizer, int index)
+{
+       struct resizer_params *param = &resizer->config;
+       struct v4l2_mbus_framefmt *informat, *outformat;
+
+       informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK];
+
+       if (index == RSZ_A)
+               outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
+       else
+               outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
+
+       if (outformat->field != V4L2_FIELD_INTERLACED)
+               param->rsz_rsc_param[index].v_dif =
+                       ((informat->height) * 256) / (outformat->height);
+       else
+               param->rsz_rsc_param[index].v_dif =
+                       ((informat->height >> 1) * 256) / (outformat->height);
+       param->rsz_rsc_param[index].h_dif =
+                       ((informat->width) * 256) / (outformat->width);
+}
+
+void
+static resizer_enable_422_420_conversion(struct resizer_params *param,
+                                        int index, bool en)
+{
+       param->rsz_rsc_param[index].cen = en;
+       param->rsz_rsc_param[index].yen = en;
+}
+
+/* resizer_calculate_sdram_offsets() - This function calculates the offsets from
+ *                                    start of buffer for the C plane when
+ *                                    output format is YUV420SP. It also
+ *                                    calculates the offsets from the start of
+ *                                    the buffer when the image is flipped
+ *                                    vertically or horizontally for ycbcr/y/c
+ *                                    planes.
+ * @resizer: Pointer to resizer subdevice.
+ * @index: index RSZ_A-resizer-A RSZ_B-resizer-B.
+ */
+static int
+resizer_calculate_sdram_offsets(struct vpfe_resizer_device *resizer, int index)
+{
+       struct resizer_params *param = &resizer->config;
+       struct v4l2_mbus_framefmt *outformat;
+       int bytesperpixel = 2;
+       int image_height;
+       int image_width;
+       int yuv_420 = 0;
+       int offset = 0;
+
+       if (index == RSZ_A)
+               outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
+       else
+               outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
+
+       image_height = outformat->height + 1;
+       image_width = outformat->width + 1;
+       param->ext_mem_param[index].c_offset = 0;
+       param->ext_mem_param[index].flip_ofst_y = 0;
+       param->ext_mem_param[index].flip_ofst_c = 0;
+       if (outformat->code == V4L2_MBUS_FMT_YDYUYDYV8_1X16) {
+               /* YUV 420 */
+               yuv_420 = 1;
+               bytesperpixel = 1;
+       }
+
+       if (param->rsz_rsc_param[index].h_flip)
+               /* width * bytesperpixel - 1 */
+               offset = (image_width * bytesperpixel) - 1;
+       if (param->rsz_rsc_param[index].v_flip)
+               offset += (image_height - 1) *
+                       param->ext_mem_param[index].rsz_sdr_oft_y;
+       param->ext_mem_param[index].flip_ofst_y = offset;
+       if (!yuv_420)
+               return 0;
+       offset = 0;
+       /* half height for c-plane */
+       if (param->rsz_rsc_param[index].h_flip)
+               /* width * bytesperpixel - 1 */
+               offset = image_width - 1;
+       if (param->rsz_rsc_param[index].v_flip)
+               offset += (((image_height >> 1) - 1) *
+                          param->ext_mem_param[index].rsz_sdr_oft_c);
+       param->ext_mem_param[index].flip_ofst_c = offset;
+       param->ext_mem_param[index].c_offset =
+                     param->ext_mem_param[index].rsz_sdr_oft_y * image_height;
+       return 0;
+}
+
+int resizer_configure_output_win(struct vpfe_resizer_device *resizer)
+{
+       struct resizer_params *param = &resizer->config;
+       struct vpfe_rsz_output_spec output_specs;
+       struct v4l2_mbus_framefmt *outformat;
+       int line_len_c;
+       int line_len;
+       int ret;
+
+       outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
+
+       output_specs.vst_y = param->user_config.vst;
+       if (outformat->code == V4L2_MBUS_FMT_YDYUYDYV8_1X16)
+               output_specs.vst_c = param->user_config.vst;
+
+       configure_resizer_out_params(resizer, RSZ_A, &output_specs, 0, 0);
+       resizer_calculate_line_length(outformat->code,
+                                     param->rsz_rsc_param[0].o_hsz + 1,
+                                     param->rsz_rsc_param[0].o_vsz + 1,
+                                     &line_len, &line_len_c);
+       param->ext_mem_param[0].rsz_sdr_oft_y = line_len;
+       param->ext_mem_param[0].rsz_sdr_oft_c = line_len_c;
+       resizer_calculate_resize_ratios(resizer, RSZ_A);
+       if (param->rsz_en[RSZ_B])
+               resizer_calculate_resize_ratios(resizer, RSZ_B);
+
+       if (outformat->code == V4L2_MBUS_FMT_YDYUYDYV8_1X16)
+               resizer_enable_422_420_conversion(param, RSZ_A, ENABLE);
+       else
+               resizer_enable_422_420_conversion(param, RSZ_A, DISABLE);
+
+       ret = resizer_calculate_sdram_offsets(resizer, RSZ_A);
+       if (!ret && param->rsz_en[RSZ_B])
+               ret = resizer_calculate_sdram_offsets(resizer, RSZ_B);
+
+       if (ret)
+               pr_err("Error in calculating sdram offsets\n");
+       return ret;
+}
+
+static int
+resizer_calculate_down_scale_f_div_param(struct device *dev,
+                                        int input_width, int output_width,
+                                        struct resizer_scale_param *param)
+{
+       /* rsz = R, input_width = H, output width = h in the equation */
+       unsigned int two_power;
+       unsigned int upper_h1;
+       unsigned int upper_h2;
+       unsigned int val1;
+       unsigned int val;
+       unsigned int rsz;
+       unsigned int h1;
+       unsigned int h2;
+       unsigned int o;
+       unsigned int n;
+
+       upper_h1 = input_width >> 1;
+       n = param->h_dscale_ave_sz;
+       /* 2 ^ (scale+1) */
+       two_power = 1 << (n + 1);
+       upper_h1 = (upper_h1 >> (n + 1)) << (n + 1);
+       upper_h2 = input_width - upper_h1;
+       if (upper_h2 % two_power) {
+               dev_err(dev, "frame halves to be a multiple of 2 power n+1\n");
+               return -EINVAL;
+       }
+       two_power = 1 << n;
+       rsz = (input_width << 8) / output_width;
+       val = rsz * two_power;
+       val = ((upper_h1 << 8) / val) + 1;
+       if (!(val % 2)) {
+               h1 = val;
+       } else {
+               val = upper_h1 << 8;
+               val >>= n + 1;
+               val -= rsz >> 1;
+               val /= rsz << 1;
+               val <<= 1;
+               val += 2;
+               h1 = val;
+       }
+       o = 10 + (two_power << 2);
+       if (((input_width << 7) / rsz) % 2)
+               o += (((CEIL(rsz, 1024)) << 1) << n);
+       h2 = output_width - h1;
+       /* phi */
+       val = (h1 * rsz) - (((upper_h1 - (o - 10)) / two_power) << 8);
+       /* skip */
+       val1 = ((val - 1024) >> 9) << 1;
+       param->f_div.num_passes = MAX_PASSES;
+       param->f_div.pass[0].o_hsz = h1 - 1;
+       param->f_div.pass[0].i_hps = 0;
+       param->f_div.pass[0].h_phs = 0;
+       param->f_div.pass[0].src_hps = 0;
+       param->f_div.pass[0].src_hsz = upper_h1 + o;
+       param->f_div.pass[1].o_hsz = h2 - 1;
+       param->f_div.pass[1].i_hps = 10 + (val1 * two_power);
+       param->f_div.pass[1].h_phs = (val - (val1 << 8));
+       param->f_div.pass[1].src_hps = upper_h1 - o;
+       param->f_div.pass[1].src_hsz = upper_h2 + o;
+
+       return 0;
+}
+
+static int
+resizer_configure_common_in_params(struct vpfe_resizer_device *resizer)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       struct resizer_params *param = &resizer->config;
+       struct vpfe_rsz_config_params *user_config;
+       struct v4l2_mbus_framefmt *informat;
+
+       informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK];
+       user_config = &resizer->config.user_config;
+       param->rsz_common.vps = param->user_config.vst;
+       param->rsz_common.hps = param->user_config.hst;
+
+       if (vpfe_ipipeif_decimation_enabled(vpfe_dev))
+               param->rsz_common.hsz = (((informat->width - 1) *
+                       IPIPEIF_RSZ_CONST) / vpfe_ipipeif_get_rsz(vpfe_dev));
+       else
+               param->rsz_common.hsz = informat->width - 1;
+
+       if (informat->field == V4L2_FIELD_INTERLACED)
+               param->rsz_common.vsz  = (informat->height - 1) >> 1;
+       else
+               param->rsz_common.vsz  = informat->height - 1;
+
+       param->rsz_common.raw_flip = 0;
+
+       if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF)
+               param->rsz_common.source = IPIPEIF_DATA;
+       else
+               param->rsz_common.source = IPIPE_DATA;
+
+       switch (informat->code) {
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+               param->rsz_common.src_img_fmt = RSZ_IMG_422;
+               param->rsz_common.raw_flip = 0;
+               break;
+
+       case V4L2_MBUS_FMT_Y8_1X8:
+               param->rsz_common.src_img_fmt = RSZ_IMG_420;
+               /* Select y */
+               param->rsz_common.y_c = 0;
+               param->rsz_common.raw_flip = 0;
+               break;
+
+       case V4L2_MBUS_FMT_UV8_1X8:
+               param->rsz_common.src_img_fmt = RSZ_IMG_420;
+               /* Select y */
+               param->rsz_common.y_c = 1;
+               param->rsz_common.raw_flip = 0;
+               break;
+
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               param->rsz_common.raw_flip = 1;
+               break;
+
+       default:
+               param->rsz_common.src_img_fmt = RSZ_IMG_422;
+               param->rsz_common.source = IPIPE_DATA;
+       }
+
+       param->rsz_common.yuv_y_min = user_config->yuv_y_min;
+       param->rsz_common.yuv_y_max = user_config->yuv_y_max;
+       param->rsz_common.yuv_c_min = user_config->yuv_c_min;
+       param->rsz_common.yuv_c_max = user_config->yuv_c_max;
+       param->rsz_common.out_chr_pos = user_config->out_chr_pos;
+       param->rsz_common.rsz_seq_crv = user_config->chroma_sample_even;
+
+       return 0;
+}
+static int
+resizer_configure_in_continious_mode(struct vpfe_resizer_device *resizer)
+{
+       struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
+       struct resizer_params *param = &resizer->config;
+       struct vpfe_rsz_config_params *cont_config;
+       int line_len_c;
+       int line_len;
+       int ret;
+
+       if (resizer->resizer_a.output != RESIZER_OUPUT_MEMORY) {
+               dev_err(dev, "enable resizer - Resizer-A\n");
+               return -EINVAL;
+       }
+
+       cont_config = &resizer->config.user_config;
+       param->rsz_en[RSZ_A] = ENABLE;
+       configure_resizer_out_params(resizer, RSZ_A,
+                                    &cont_config->output1, 1, 0);
+       param->rsz_en[RSZ_B] = DISABLE;
+       param->oper_mode = RESIZER_MODE_CONTINIOUS;
+
+       if (resizer->resizer_b.output == RESIZER_OUPUT_MEMORY) {
+               struct v4l2_mbus_framefmt *outformat2;
+
+               param->rsz_en[RSZ_B] = ENABLE;
+               outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
+               ret = resizer_validate_output_image_format(dev, outformat2,
+                               &line_len, &line_len_c);
+               if (ret)
+                       return ret;
+               param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
+               param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
+               configure_resizer_out_params(resizer, RSZ_B,
+                                               &cont_config->output2, 0, 1);
+               if (outformat2->code == V4L2_MBUS_FMT_YDYUYDYV8_1X16)
+                       resizer_enable_422_420_conversion(param,
+                                                         RSZ_B, ENABLE);
+               else
+                       resizer_enable_422_420_conversion(param,
+                                                         RSZ_B, DISABLE);
+       }
+       resizer_configure_common_in_params(resizer);
+       ret = resizer_configure_output_win(resizer);
+       if (ret)
+               return ret;
+
+       param->rsz_common.passthrough = cont_config->bypass;
+       if (cont_config->bypass)
+               resizer_configure_passthru(resizer, 1);
+
+       return 0;
+}
+
+static inline int
+resizer_validate_input_image_format(struct device *dev,
+                                   enum v4l2_mbus_pixelcode pix,
+                                   int width, int height, int *line_len)
+{
+       int val;
+
+       if (pix != V4L2_MBUS_FMT_UYVY8_2X8 &&
+           pix != V4L2_MBUS_FMT_Y8_1X8 &&
+           pix != V4L2_MBUS_FMT_UV8_1X8 &&
+           pix != V4L2_MBUS_FMT_SGRBG12_1X12) {
+               dev_err(dev,
+               "resizer validate output: pix format not supported, %d\n", pix);
+               return -EINVAL;
+       }
+
+       if (!width || !height) {
+               dev_err(dev,
+                       "resizer validate input: invalid width or height\n");
+               return -EINVAL;
+       }
+
+       if (pix == V4L2_MBUS_FMT_UV8_1X8)
+               resizer_calculate_line_length(pix, width,
+                                             height, &val, line_len);
+       else
+               resizer_calculate_line_length(pix, width,
+                                             height, line_len, &val);
+
+       return 0;
+}
+
+static int
+resizer_validate_decimation(struct device *dev, enum ipipeif_decimation dec_en,
+                           unsigned char rsz, unsigned char frame_div_mode_en,
+                           int width)
+{
+       if (dec_en && frame_div_mode_en) {
+               dev_err(dev,
+                "dec_en & frame_div_mode_en can not enabled simultaneously\n");
+               return -EINVAL;
+       }
+
+       if (frame_div_mode_en) {
+               dev_err(dev, "frame_div_mode mode not supported\n");
+               return -EINVAL;
+       }
+
+       if (!dec_en)
+               return 0;
+
+       if (width <= VPFE_IPIPE_MAX_INPUT_WIDTH) {
+               dev_err(dev,
+                       "image width to be more than %d for decimation\n",
+                       VPFE_IPIPE_MAX_INPUT_WIDTH);
+               return -EINVAL;
+       }
+
+       if (rsz < IPIPEIF_RSZ_MIN || rsz > IPIPEIF_RSZ_MAX) {
+               dev_err(dev, "rsz range is %d to %d\n",
+                       IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* resizer_calculate_normal_f_div_param() - Algorithm to calculate the frame
+ *                                         division parameters for resizer.
+ *                                         in normal mode.
+ */
+static int
+resizer_calculate_normal_f_div_param(struct device *dev, int input_width,
+               int output_width, struct resizer_scale_param *param)
+{
+       /* rsz = R, input_width = H, output width = h in the equation */
+       unsigned int val1;
+       unsigned int rsz;
+       unsigned int val;
+       unsigned int h1;
+       unsigned int h2;
+       unsigned int o;
+
+       if (output_width > input_width) {
+               dev_err(dev, "frame div mode is used for scale down only\n");
+               return -EINVAL;
+       }
+
+       rsz = (input_width << 8) / output_width;
+       val = rsz << 1;
+       val = ((input_width << 8) / val) + 1;
+       o = 14;
+       if (!(val % 2)) {
+               h1 = val;
+       } else {
+               val = (input_width << 7);
+               val -= rsz >> 1;
+               val /= rsz << 1;
+               val <<= 1;
+               val += 2;
+               o += ((CEIL(rsz, 1024)) << 1);
+               h1 = val;
+       }
+       h2 = output_width - h1;
+       /* phi */
+       val = (h1 * rsz) - (((input_width >> 1) - o) << 8);
+       /* skip */
+       val1 = ((val - 1024) >> 9) << 1;
+       param->f_div.num_passes = MAX_PASSES;
+       param->f_div.pass[0].o_hsz = h1 - 1;
+       param->f_div.pass[0].i_hps = 0;
+       param->f_div.pass[0].h_phs = 0;
+       param->f_div.pass[0].src_hps = 0;
+       param->f_div.pass[0].src_hsz = (input_width >> 2) + o;
+       param->f_div.pass[1].o_hsz = h2 - 1;
+       param->f_div.pass[1].i_hps = val1;
+       param->f_div.pass[1].h_phs = (val - (val1 << 8));
+       param->f_div.pass[1].src_hps = (input_width >> 2) - o;
+       param->f_div.pass[1].src_hsz = (input_width >> 2) + o;
+
+       return 0;
+}
+
+static int
+resizer_configure_in_single_shot_mode(struct vpfe_resizer_device *resizer)
+{
+       struct vpfe_rsz_config_params *config = &resizer->config.user_config;
+       struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       struct v4l2_mbus_framefmt *outformat1, *outformat2;
+       struct resizer_params *param = &resizer->config;
+       struct v4l2_mbus_framefmt *informat;
+       int decimation;
+       int line_len_c;
+       int line_len;
+       int rsz;
+       int ret;
+
+       informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK];
+       outformat1 = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
+       outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
+
+       decimation = vpfe_ipipeif_decimation_enabled(vpfe_dev);
+       rsz = vpfe_ipipeif_get_rsz(vpfe_dev);
+       if (decimation && param->user_config.frame_div_mode_en) {
+               dev_err(dev,
+               "dec_en & frame_div_mode_en cannot enabled simultaneously\n");
+               return -EINVAL;
+       }
+
+       ret = resizer_validate_decimation(dev, decimation, rsz,
+             param->user_config.frame_div_mode_en, informat->width);
+       if (ret)
+               return -EINVAL;
+
+       ret = resizer_validate_input_image_format(dev, informat->code,
+               informat->width, informat->height, &line_len);
+       if (ret)
+               return -EINVAL;
+
+       if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) {
+               param->rsz_en[RSZ_A] = ENABLE;
+               ret = resizer_validate_output_image_format(dev, outformat1,
+                                       &line_len, &line_len_c);
+               if (ret)
+                       return ret;
+               param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
+               param->ext_mem_param[RSZ_A].rsz_sdr_oft_c = line_len_c;
+               configure_resizer_out_params(resizer, RSZ_A,
+                                       &param->user_config.output1, 0, 1);
+
+               if (outformat1->code == V4L2_MBUS_FMT_SGRBG12_1X12)
+                       param->rsz_common.raw_flip = 1;
+               else
+                       param->rsz_common.raw_flip = 0;
+
+               if (outformat1->code == V4L2_MBUS_FMT_YDYUYDYV8_1X16)
+                       resizer_enable_422_420_conversion(param,
+                                                         RSZ_A, ENABLE);
+               else
+                       resizer_enable_422_420_conversion(param,
+                                                         RSZ_A, DISABLE);
+       }
+
+       if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) {
+               param->rsz_en[RSZ_B] = ENABLE;
+               ret = resizer_validate_output_image_format(dev, outformat2,
+                               &line_len, &line_len_c);
+               if (ret)
+                       return ret;
+               param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
+               param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
+               configure_resizer_out_params(resizer, RSZ_B,
+                                       &param->user_config.output2, 0, 1);
+               if (outformat2->code == V4L2_MBUS_FMT_YDYUYDYV8_1X16)
+                       resizer_enable_422_420_conversion(param,
+                                                         RSZ_B, ENABLE);
+               else
+                       resizer_enable_422_420_conversion(param,
+                                                         RSZ_B, DISABLE);
+       }
+
+       resizer_configure_common_in_params(resizer);
+       if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) {
+               resizer_calculate_resize_ratios(resizer, RSZ_A);
+               resizer_calculate_sdram_offsets(resizer, RSZ_A);
+               /* Overriding resize ratio calculation */
+               if (informat->code == V4L2_MBUS_FMT_UV8_1X8) {
+                       param->rsz_rsc_param[RSZ_A].v_dif =
+                               (((informat->height + 1) * 2) * 256) /
+                               (param->rsz_rsc_param[RSZ_A].o_vsz + 1);
+               }
+       }
+
+       if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) {
+               resizer_calculate_resize_ratios(resizer, RSZ_B);
+               resizer_calculate_sdram_offsets(resizer, RSZ_B);
+               /* Overriding resize ratio calculation */
+               if (informat->code == V4L2_MBUS_FMT_UV8_1X8) {
+                       param->rsz_rsc_param[RSZ_B].v_dif =
+                               (((informat->height + 1) * 2) * 256) /
+                               (param->rsz_rsc_param[RSZ_B].o_vsz + 1);
+               }
+       }
+       if (param->user_config.frame_div_mode_en &&
+               param->rsz_en[RSZ_A]) {
+               if (!param->rsz_rsc_param[RSZ_A].dscale_en)
+                       ret = resizer_calculate_normal_f_div_param(dev,
+                             informat->width,
+                             param->rsz_rsc_param[RSZ_A].o_vsz + 1,
+                             &param->rsz_rsc_param[RSZ_A]);
+               else
+                       ret = resizer_calculate_down_scale_f_div_param(dev,
+                             informat->width,
+                             param->rsz_rsc_param[RSZ_A].o_vsz + 1,
+                             &param->rsz_rsc_param[RSZ_A]);
+               if (ret)
+                       return -EINVAL;
+       }
+       if (param->user_config.frame_div_mode_en &&
+               param->rsz_en[RSZ_B]) {
+               if (!param->rsz_rsc_param[RSZ_B].dscale_en)
+                       ret = resizer_calculate_normal_f_div_param(dev,
+                             informat->width,
+                             param->rsz_rsc_param[RSZ_B].o_vsz + 1,
+                             &param->rsz_rsc_param[RSZ_B]);
+               else
+                       ret = resizer_calculate_down_scale_f_div_param(dev,
+                             informat->width,
+                             param->rsz_rsc_param[RSZ_B].o_vsz + 1,
+                             &param->rsz_rsc_param[RSZ_B]);
+               if (ret)
+                       return -EINVAL;
+       }
+       param->rsz_common.passthrough = config->bypass;
+       if (config->bypass)
+               resizer_configure_passthru(resizer, 1);
+       return 0;
+}
+
+static void
+resizer_set_defualt_configuration(struct vpfe_resizer_device *resizer)
+{
+#define  WIDTH_I 640
+#define  HEIGHT_I 480
+#define  WIDTH_O 640
+#define  HEIGHT_O 480
+       const struct resizer_params rsz_default_config = {
+               .oper_mode = RESIZER_MODE_ONE_SHOT,
+               .rsz_common = {
+                       .vsz = HEIGHT_I - 1,
+                       .hsz = WIDTH_I - 1,
+                       .src_img_fmt = RSZ_IMG_422,
+                       .raw_flip = 1,  /* flip preserve Raw format */
+                       .source = IPIPE_DATA,
+                       .passthrough = BYPASS_OFF,
+                       .yuv_y_max = 255,
+                       .yuv_c_max = 255,
+                       .rsz_seq_crv = DISABLE,
+                       .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE,
+               },
+               .rsz_rsc_param = {
+                       {
+                               .h_flip = DISABLE,
+                               .v_flip = DISABLE,
+                               .cen = DISABLE,
+                               .yen = DISABLE,
+                               .o_vsz = HEIGHT_O - 1,
+                               .o_hsz = WIDTH_O - 1,
+                               .v_dif = 256,
+                               .v_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_dif = 256,
+                               .h_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                               .v_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                       },
+                       {
+                               .h_flip = DISABLE,
+                               .v_flip = DISABLE,
+                               .cen = DISABLE,
+                               .yen = DISABLE,
+                               .o_vsz = HEIGHT_O - 1,
+                               .o_hsz = WIDTH_O - 1,
+                               .v_dif = 256,
+                               .v_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_dif = 256,
+                               .h_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                               .v_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                       },
+               },
+               .rsz2rgb = {
+                       {
+                               .rgb_en = DISABLE
+                       },
+                       {
+                               .rgb_en = DISABLE
+                       }
+               },
+               .ext_mem_param = {
+                       {
+                               .rsz_sdr_oft_y = WIDTH_O << 1,
+                               .rsz_sdr_ptr_e_y = HEIGHT_O,
+                               .rsz_sdr_oft_c = WIDTH_O,
+                               .rsz_sdr_ptr_e_c = HEIGHT_O >> 1,
+                       },
+                       {
+                               .rsz_sdr_oft_y = WIDTH_O << 1,
+                               .rsz_sdr_ptr_e_y = HEIGHT_O,
+                               .rsz_sdr_oft_c = WIDTH_O,
+                               .rsz_sdr_ptr_e_c = HEIGHT_O,
+                       },
+               },
+               .rsz_en[0] = ENABLE,
+               .rsz_en[1] = DISABLE,
+               .user_config = {
+                       .output1 = {
+                               .v_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .v_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                               .v_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                       },
+                       .output2 = {
+                               .v_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .v_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_y = VPFE_RSZ_INTP_CUBIC,
+                               .h_typ_c = VPFE_RSZ_INTP_CUBIC,
+                               .h_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                               .v_dscale_ave_sz =
+                                       VPFE_IPIPE_DWN_SCALE_1_OVER_2,
+                       },
+                       .yuv_y_max = 255,
+                       .yuv_c_max = 255,
+                       .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE,
+               },
+       };
+       memset(&resizer->config, 0, sizeof(struct resizer_params));
+       memcpy(&resizer->config, &rsz_default_config,
+              sizeof(struct resizer_params));
+}
+
+/*
+ * resizer_set_configuration() - set resizer config
+ * @resizer: vpfe resizer device pointer.
+ * @chan_config: resizer channel configuration.
+ */
+static int
+resizer_set_configuration(struct vpfe_resizer_device *resizer,
+                         struct vpfe_rsz_config *chan_config)
+{
+       if (!chan_config->config)
+               resizer_set_defualt_configuration(resizer);
+       else
+               if (copy_from_user(&resizer->config.user_config,
+                   chan_config->config, sizeof(struct vpfe_rsz_config_params)))
+                       return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * resizer_get_configuration() - get resizer config
+ * @resizer: vpfe resizer device pointer.
+ * @channel: image processor logical channel.
+ * @chan_config: resizer channel configuration.
+ */
+static int
+resizer_get_configuration(struct vpfe_resizer_device *resizer,
+                  struct vpfe_rsz_config *chan_config)
+{
+       struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
+
+       if (!chan_config->config) {
+               dev_err(dev, "Resizer channel invalid pointer\n");
+               return -EINVAL;
+       }
+
+       if (copy_to_user((void *)chan_config->config,
+          (void *)&resizer->config.user_config,
+          sizeof(struct vpfe_rsz_config_params))) {
+               dev_err(dev, "resizer_get_configuration: Error in copy to user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/*
+ * VPFE video operations
+ */
+
+/*
+ * resizer_a_video_out_queue() - RESIZER-A video out queue
+ * @vpfe_dev: vpfe device pointer.
+ * @addr: buffer address.
+ */
+static int resizer_a_video_out_queue(struct vpfe_device *vpfe_dev,
+                                    unsigned long addr)
+{
+       struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer;
+
+       return resizer_set_outaddr(resizer->base_addr,
+                                     &resizer->config, RSZ_A, addr);
+}
+
+/*
+ * resizer_b_video_out_queue() - RESIZER-B video out queue
+ * @vpfe_dev: vpfe device pointer.
+ * @addr: buffer address.
+ */
+static int resizer_b_video_out_queue(struct vpfe_device *vpfe_dev,
+                                    unsigned long addr)
+{
+       struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer;
+
+       return resizer_set_outaddr(resizer->base_addr,
+                                  &resizer->config, RSZ_B, addr);
+}
+
+static const struct vpfe_video_operations resizer_a_video_ops = {
+       .queue = resizer_a_video_out_queue,
+};
+
+static const struct vpfe_video_operations resizer_b_video_ops = {
+       .queue = resizer_b_video_out_queue,
+};
+
+static void resizer_enable(struct vpfe_resizer_device *resizer, int en)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
+       unsigned char val;
+
+       if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE)
+               return;
+
+       if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF &&
+          ipipeif_sink == IPIPEIF_INPUT_MEMORY) {
+               do {
+                       val = regr_rsz(resizer->base_addr, RSZ_SRC_EN);
+               } while (val);
+
+               if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) {
+                       do {
+                               val = regr_rsz(resizer->base_addr, RSZ_A);
+                       } while (val);
+               }
+               if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) {
+                       do {
+                               val = regr_rsz(resizer->base_addr, RSZ_B);
+                       } while (val);
+               }
+       }
+       if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE)
+               rsz_enable(resizer->base_addr, RSZ_A, en);
+
+       if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE)
+               rsz_enable(resizer->base_addr, RSZ_B, en);
+}
+
+
+/*
+ * resizer_ss_isr() - resizer module single-shot buffer scheduling isr
+ * @resizer: vpfe resizer device pointer.
+ */
+static void resizer_ss_isr(struct vpfe_resizer_device *resizer)
+{
+       struct vpfe_video_device *video_out = &resizer->resizer_a.video_out;
+       struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out;
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       struct vpfe_pipeline *pipe = &video_out->pipe;
+       u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
+       u32 val;
+
+       if (ipipeif_sink != IPIPEIF_INPUT_MEMORY)
+               return;
+
+       if (resizer->resizer_a.output == RESIZER_OUPUT_MEMORY) {
+               val = vpss_dma_complete_interrupt();
+               if (val != 0 && val != 2)
+                       return;
+       }
+
+       if (resizer->resizer_a.output == RESIZER_OUPUT_MEMORY) {
+               spin_lock(&video_out->dma_queue_lock);
+               vpfe_video_process_buffer_complete(video_out);
+               video_out->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
+               vpfe_video_schedule_next_buffer(video_out);
+               spin_unlock(&video_out->dma_queue_lock);
+       }
+
+       /* If resizer B is enabled */
+       if (pipe->output_num > 1 && resizer->resizer_b.output ==
+           RESIZER_OUPUT_MEMORY) {
+               spin_lock(&video_out->dma_queue_lock);
+               vpfe_video_process_buffer_complete(video_out2);
+               video_out2->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
+               vpfe_video_schedule_next_buffer(video_out2);
+               spin_unlock(&video_out2->dma_queue_lock);
+       }
+
+       /* start HW if buffers are queued */
+       if (vpfe_video_is_pipe_ready(pipe) &&
+           resizer->resizer_a.output == RESIZER_OUPUT_MEMORY) {
+               resizer_enable(resizer, 1);
+               vpfe_ipipe_enable(vpfe_dev, 1);
+               vpfe_ipipeif_enable(vpfe_dev);
+       }
+}
+
+/*
+ * vpfe_resizer_buffer_isr() - resizer module buffer scheduling isr
+ * @resizer: vpfe resizer device pointer.
+ */
+void vpfe_resizer_buffer_isr(struct vpfe_resizer_device *resizer)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       struct vpfe_video_device *video_out = &resizer->resizer_a.video_out;
+       struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out;
+       struct vpfe_pipeline *pipe = &resizer->resizer_a.video_out.pipe;
+       enum v4l2_field field;
+       int fid;
+
+       if (!video_out->started)
+               return;
+
+       if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE)
+               return;
+
+       field = video_out->fmt.fmt.pix.field;
+       if (field == V4L2_FIELD_NONE) {
+               /* handle progressive frame capture */
+               if (video_out->cur_frm != video_out->next_frm) {
+                       vpfe_video_process_buffer_complete(video_out);
+                       if (pipe->output_num > 1)
+                               vpfe_video_process_buffer_complete(video_out2);
+               }
+
+               video_out->skip_frame_count--;
+               if (!video_out->skip_frame_count) {
+                       video_out->skip_frame_count =
+                               video_out->skip_frame_count_init;
+                       rsz_src_enable(resizer->base_addr, 1);
+               } else {
+                       rsz_src_enable(resizer->base_addr, 0);
+               }
+               return;
+       }
+
+       /* handle interlaced frame capture */
+       fid = vpfe_isif_get_fid(vpfe_dev);
+
+       /* switch the software maintained field id */
+       video_out->field_id ^= 1;
+       if (fid == video_out->field_id) {
+               /*
+                * we are in-sync here,continue.
+                * One frame is just being captured. If the
+                * next frame is available, release the current
+                * frame and move on
+                */
+               if (fid == 0 && video_out->cur_frm != video_out->next_frm) {
+                       vpfe_video_process_buffer_complete(video_out);
+                       if (pipe->output_num > 1)
+                               vpfe_video_process_buffer_complete(video_out2);
+               }
+       } else if (fid == 0) {
+               /*
+               * out of sync. Recover from any hardware out-of-sync.
+               * May loose one frame
+               */
+               video_out->field_id = fid;
+       }
+}
+
+/*
+ * vpfe_resizer_dma_isr() - resizer module dma isr
+ * @resizer: vpfe resizer device pointer.
+ */
+void vpfe_resizer_dma_isr(struct vpfe_resizer_device *resizer)
+{
+       struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out;
+       struct vpfe_video_device *video_out = &resizer->resizer_a.video_out;
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       struct vpfe_pipeline *pipe = &video_out->pipe;
+       int schedule_capture = 0;
+       enum v4l2_field field;
+       int fid;
+
+       if (!video_out->started)
+               return;
+
+       if (pipe->state == VPFE_PIPELINE_STREAM_SINGLESHOT) {
+               resizer_ss_isr(resizer);
+               return;
+       }
+
+       field = video_out->fmt.fmt.pix.field;
+       if (field == V4L2_FIELD_NONE) {
+               if (!list_empty(&video_out->dma_queue) &&
+                       video_out->cur_frm == video_out->next_frm)
+                       schedule_capture = 1;
+       } else {
+               fid = vpfe_isif_get_fid(vpfe_dev);
+               if (fid == video_out->field_id) {
+                       /* we are in-sync here,continue */
+                       if (fid == 1 && !list_empty(&video_out->dma_queue) &&
+                           video_out->cur_frm == video_out->next_frm)
+                               schedule_capture = 1;
+               }
+       }
+
+       if (!schedule_capture)
+               return;
+
+       spin_lock(&video_out->dma_queue_lock);
+       vpfe_video_schedule_next_buffer(video_out);
+       spin_unlock(&video_out->dma_queue_lock);
+       if (pipe->output_num > 1) {
+               spin_lock(&video_out2->dma_queue_lock);
+               vpfe_video_schedule_next_buffer(video_out2);
+               spin_unlock(&video_out2->dma_queue_lock);
+       }
+}
+
+/*
+ * V4L2 subdev operations
+ */
+
+/*
+ * resizer_ioctl() - Handle resizer module private ioctl's
+ * @sd: pointer to v4l2 subdev structure
+ * @cmd: configuration command
+ * @arg: configuration argument
+ */
+static long resizer_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+       struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
+       struct vpfe_rsz_config *user_config;
+       int ret = -ENOIOCTLCMD;
+
+       if (&resizer->crop_resizer.subdev != sd)
+               return ret;
+
+       switch (cmd) {
+       case VIDIOC_VPFE_RSZ_S_CONFIG:
+               user_config = (struct vpfe_rsz_config *)arg;
+               ret = resizer_set_configuration(resizer, user_config);
+               break;
+
+       case VIDIOC_VPFE_RSZ_G_CONFIG:
+               user_config = (struct vpfe_rsz_config *)arg;
+               if (!user_config->config) {
+                       dev_err(dev, "error in VIDIOC_VPFE_RSZ_G_CONFIG\n");
+                       return -EINVAL;
+               }
+               ret = resizer_get_configuration(resizer, user_config);
+               break;
+       }
+       return ret;
+}
+
+static int resizer_do_hw_setup(struct vpfe_resizer_device *resizer)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
+       u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output;
+       struct resizer_params *param = &resizer->config;
+       int ret = 0;
+
+       if (resizer->resizer_a.output == RESIZER_OUPUT_MEMORY ||
+           resizer->resizer_b.output == RESIZER_OUPUT_MEMORY) {
+               if (ipipeif_sink == IPIPEIF_INPUT_MEMORY &&
+                   ipipeif_source == IPIPEIF_OUTPUT_RESIZER)
+                       ret = resizer_configure_in_single_shot_mode(resizer);
+               else
+                       ret =  resizer_configure_in_continious_mode(resizer);
+               if (ret)
+                       return ret;
+               ret = config_rsz_hw(resizer, param);
+       }
+       return ret;
+}
+
+/*
+ * resizer_set_stream() - Enable/Disable streaming on resizer subdev
+ * @sd: pointer to v4l2 subdev structure
+ * @enable: 1 == Enable, 0 == Disable
+ */
+static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
+
+       if (&resizer->crop_resizer.subdev != sd)
+               return 0;
+
+       if (resizer->resizer_a.output != RESIZER_OUPUT_MEMORY)
+               return 0;
+
+       switch (enable) {
+       case 1:
+               if (resizer_do_hw_setup(resizer) < 0)
+                       return -EINVAL;
+               resizer_enable(resizer, enable);
+               break;
+
+       case 0:
+               resizer_enable(resizer, enable);
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * __resizer_get_format() - helper function for getting resizer format
+ * @sd: pointer to subdev.
+ * @fh: V4L2 subdev file handle.
+ * @pad: pad number.
+ * @which: wanted subdev format.
+ * Retun wanted mbus frame format.
+ */
+static struct v4l2_mbus_framefmt *
+__resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                    unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+       struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
+
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+       if (&resizer->crop_resizer.subdev == sd)
+               return &resizer->crop_resizer.formats[pad];
+       if (&resizer->resizer_a.subdev == sd)
+               return &resizer->resizer_a.formats[pad];
+       if (&resizer->resizer_b.subdev == sd)
+               return &resizer->resizer_b.formats[pad];
+       return NULL;
+}
+
+/*
+ * resizer_try_format() - Handle try format by pad subdev method
+ * @sd: pointer to subdev.
+ * @fh: V4L2 subdev file handle.
+ * @pad: pad num.
+ * @fmt: pointer to v4l2 format structure.
+ * @which: wanted subdev format.
+ */
+static void
+resizer_try_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+       unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+       enum v4l2_subdev_format_whence which)
+{
+       struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       unsigned int max_out_height;
+       unsigned int max_out_width;
+       unsigned int i;
+
+       if ((&resizer->resizer_a.subdev == sd && pad == RESIZER_PAD_SINK) ||
+           (&resizer->resizer_b.subdev == sd && pad == RESIZER_PAD_SINK) ||
+           (&resizer->crop_resizer.subdev == sd &&
+           (pad == RESIZER_CROP_PAD_SOURCE ||
+           pad == RESIZER_CROP_PAD_SOURCE2 || pad == RESIZER_CROP_PAD_SINK))) {
+               for (i = 0; i < ARRAY_SIZE(resizer_input_formats); i++) {
+                       if (fmt->code == resizer_input_formats[i])
+                               break;
+               }
+               /* If not found, use UYVY as default */
+               if (i >= ARRAY_SIZE(resizer_input_formats))
+                       fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+               fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
+                                       MAX_IN_WIDTH);
+               fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT,
+                               MAX_IN_HEIGHT);
+       } else if (&resizer->resizer_a.subdev == sd &&
+                  pad == RESIZER_PAD_SOURCE) {
+               max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
+               max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+
+               for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) {
+                       if (fmt->code == resizer_output_formats[i])
+                               break;
+               }
+               /* If not found, use UYVY as default */
+               if (i >= ARRAY_SIZE(resizer_output_formats))
+                       fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+               fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH,
+                                       max_out_width);
+               fmt->width &= ~15;
+               fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT,
+                               max_out_height);
+       } else if (&resizer->resizer_b.subdev == sd &&
+                  pad == RESIZER_PAD_SOURCE) {
+               max_out_width = IPIPE_MAX_OUTPUT_WIDTH_B;
+               max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_B;
+
+               for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) {
+                       if (fmt->code == resizer_output_formats[i])
+                               break;
+               }
+               /* If not found, use UYVY as default */
+               if (i >= ARRAY_SIZE(resizer_output_formats))
+                       fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+               fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH,
+                                       max_out_width);
+               fmt->width &= ~15;
+               fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT,
+                               max_out_height);
+       }
+}
+
+/*
+ * resizer_set_format() - Handle set format by pads subdev method
+ * @sd: pointer to v4l2 subdev structure
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __resizer_get_format(sd, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       resizer_try_format(sd, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       if (&resizer->crop_resizer.subdev == sd) {
+               if (fmt->pad == RESIZER_CROP_PAD_SINK) {
+                       resizer->crop_resizer.formats[fmt->pad] = fmt->format;
+               } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE &&
+                               resizer->crop_resizer.output == RESIZER_A) {
+                       resizer->crop_resizer.formats[fmt->pad] = fmt->format;
+                       resizer->crop_resizer.
+                       formats[RESIZER_CROP_PAD_SOURCE2] = fmt->format;
+               } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE2 &&
+                       resizer->crop_resizer.output2 == RESIZER_B) {
+                       resizer->crop_resizer.formats[fmt->pad] = fmt->format;
+                       resizer->crop_resizer.
+                       formats[RESIZER_CROP_PAD_SOURCE] = fmt->format;
+               } else {
+                       return -EINVAL;
+               }
+       } else if (&resizer->resizer_a.subdev == sd) {
+               if (fmt->pad == RESIZER_PAD_SINK)
+                       resizer->resizer_a.formats[fmt->pad] = fmt->format;
+               else if (fmt->pad == RESIZER_PAD_SOURCE)
+                       resizer->resizer_a.formats[fmt->pad] = fmt->format;
+               else
+                       return -EINVAL;
+       } else if (&resizer->resizer_b.subdev == sd) {
+               if (fmt->pad == RESIZER_PAD_SINK)
+                       resizer->resizer_b.formats[fmt->pad] = fmt->format;
+               else if (fmt->pad == RESIZER_PAD_SOURCE)
+                       resizer->resizer_b.formats[fmt->pad] = fmt->format;
+               else
+                       return -EINVAL;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * resizer_get_format() - Retrieve the video format on a pad
+ * @sd: pointer to v4l2 subdev structure.
+ * @fh: V4L2 subdev file handle.
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct v4l2_mbus_framefmt *format;
+
+       format = __resizer_get_format(sd, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       fmt->format = *format;
+
+       return 0;
+}
+
+/*
+ * resizer_enum_frame_size() - enum frame sizes on pads
+ * @sd: Pointer to subdevice.
+ * @fh: V4L2 subdev file handle.
+ * @code: pointer to v4l2_subdev_frame_size_enum structure.
+ */
+static int resizer_enum_frame_size(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       resizer_try_format(sd, fh, fse->pad, &format,
+                           V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       resizer_try_format(sd, fh, fse->pad, &format,
+                          V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * resizer_enum_mbus_code() - enum mbus codes for pads
+ * @sd: Pointer to subdevice.
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ */
+static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->pad == RESIZER_PAD_SINK) {
+               if (code->index >= ARRAY_SIZE(resizer_input_formats))
+                       return -EINVAL;
+
+               code->code = resizer_input_formats[code->index];
+       } else if (code->pad == RESIZER_PAD_SOURCE) {
+               if (code->index >= ARRAY_SIZE(resizer_output_formats))
+                       return -EINVAL;
+
+               code->code = resizer_output_formats[code->index];
+       }
+
+       return 0;
+}
+
+/*
+ * resizer_init_formats() - Initialize formats on all pads
+ * @sd: Pointer to subdevice.
+ * @fh: V4L2 subdev file handle.
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int resizer_init_formats(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_fh *fh)
+{
+       __u32 which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct v4l2_subdev_format format;
+
+       if (&resizer->crop_resizer.subdev == sd) {
+               memset(&format, 0, sizeof(format));
+               format.pad = RESIZER_CROP_PAD_SINK;
+               format.which = which;
+               format.format.code = V4L2_MBUS_FMT_YUYV8_2X8;
+               format.format.width = MAX_IN_WIDTH;
+               format.format.height = MAX_IN_HEIGHT;
+               resizer_set_format(sd, fh, &format);
+
+               memset(&format, 0, sizeof(format));
+               format.pad = RESIZER_CROP_PAD_SOURCE;
+               format.which = which;
+               format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
+               format.format.width = MAX_IN_WIDTH;
+               format.format.height = MAX_IN_WIDTH;
+               resizer_set_format(sd, fh, &format);
+
+               memset(&format, 0, sizeof(format));
+               format.pad = RESIZER_CROP_PAD_SOURCE2;
+               format.which = which;
+               format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
+               format.format.width = MAX_IN_WIDTH;
+               format.format.height = MAX_IN_WIDTH;
+               resizer_set_format(sd, fh, &format);
+       } else if (&resizer->resizer_a.subdev == sd) {
+               memset(&format, 0, sizeof(format));
+               format.pad = RESIZER_PAD_SINK;
+               format.which = which;
+               format.format.code = V4L2_MBUS_FMT_YUYV8_2X8;
+               format.format.width = MAX_IN_WIDTH;
+               format.format.height = MAX_IN_HEIGHT;
+               resizer_set_format(sd, fh, &format);
+
+               memset(&format, 0, sizeof(format));
+               format.pad = RESIZER_PAD_SOURCE;
+               format.which = which;
+               format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
+               format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
+               format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
+               resizer_set_format(sd, fh, &format);
+       } else if (&resizer->resizer_b.subdev == sd) {
+               memset(&format, 0, sizeof(format));
+               format.pad = RESIZER_PAD_SINK;
+               format.which = which;
+               format.format.code = V4L2_MBUS_FMT_YUYV8_2X8;
+               format.format.width = MAX_IN_WIDTH;
+               format.format.height = MAX_IN_HEIGHT;
+               resizer_set_format(sd, fh, &format);
+
+               memset(&format, 0, sizeof(format));
+               format.pad = RESIZER_PAD_SOURCE;
+               format.which = which;
+               format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
+               format.format.width = IPIPE_MAX_OUTPUT_WIDTH_B;
+               format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_B;
+               resizer_set_format(sd, fh, &format);
+       }
+
+       return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops resizer_v4l2_core_ops = {
+       .ioctl = resizer_ioctl,
+};
+
+/* subdev internal operations */
+static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
+       .open = resizer_init_formats,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
+       .s_stream = resizer_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
+       .enum_mbus_code = resizer_enum_mbus_code,
+       .enum_frame_size = resizer_enum_frame_size,
+       .get_fmt = resizer_get_format,
+       .set_fmt = resizer_set_format,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops resizer_v4l2_ops = {
+       .core = &resizer_v4l2_core_ops,
+       .video = &resizer_v4l2_video_ops,
+       .pad = &resizer_v4l2_pad_ops,
+};
+
+/*
+ * Media entity operations
+ */
+
+/*
+ * resizer_link_setup() - Setup resizer connections
+ * @entity: Pointer to media entity structure
+ * @local: Pointer to local pad array
+ * @remote: Pointer to remote pad array
+ * @flags: Link flags
+ * return -EINVAL or zero on success
+ */
+static int resizer_link_setup(struct media_entity *entity,
+                          const struct media_pad *local,
+                          const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output;
+       u16 ipipe_source = vpfe_dev->vpfe_ipipe.output;
+
+       if (&resizer->crop_resizer.subdev == sd) {
+               switch (local->index | media_entity_type(remote->entity)) {
+               case RESIZER_CROP_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+                       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                               resizer->crop_resizer.input =
+                                       RESIZER_CROP_INPUT_NONE;
+                               break;
+                       }
+
+                       if (resizer->crop_resizer.input !=
+                          RESIZER_CROP_INPUT_NONE)
+                               return -EBUSY;
+                       if (ipipeif_source == IPIPEIF_OUTPUT_RESIZER)
+                               resizer->crop_resizer.input =
+                                               RESIZER_CROP_INPUT_IPIPEIF;
+                       else if (ipipe_source == IPIPE_OUTPUT_RESIZER)
+                                       resizer->crop_resizer.input =
+                                               RESIZER_CROP_INPUT_IPIPE;
+                       else
+                               return -EINVAL;
+                       break;
+
+               case RESIZER_CROP_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+                       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                               resizer->crop_resizer.output =
+                               RESIZER_CROP_OUTPUT_NONE;
+                               break;
+                       }
+                       if (resizer->crop_resizer.output !=
+                           RESIZER_CROP_OUTPUT_NONE)
+                               return -EBUSY;
+                       resizer->crop_resizer.output = RESIZER_A;
+                       break;
+
+               case RESIZER_CROP_PAD_SOURCE2 | MEDIA_ENT_T_V4L2_SUBDEV:
+                       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                               resizer->crop_resizer.output2 =
+                                       RESIZER_CROP_OUTPUT_NONE;
+                               break;
+                       }
+                       if (resizer->crop_resizer.output2 !=
+                           RESIZER_CROP_OUTPUT_NONE)
+                               return -EBUSY;
+                       resizer->crop_resizer.output2 = RESIZER_B;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+       } else if (&resizer->resizer_a.subdev == sd) {
+               switch (local->index | media_entity_type(remote->entity)) {
+               case RESIZER_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+                       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                               resizer->resizer_a.input = RESIZER_INPUT_NONE;
+                               break;
+                       }
+                       if (resizer->resizer_a.input != RESIZER_INPUT_NONE)
+                               return -EBUSY;
+                       resizer->resizer_a.input = RESIZER_INPUT_CROP_RESIZER;
+                       break;
+
+               case RESIZER_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+                       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                               resizer->resizer_a.output = RESIZER_OUTPUT_NONE;
+                               break;
+                       }
+                       if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE)
+                               return -EBUSY;
+                       resizer->resizer_a.output = RESIZER_OUPUT_MEMORY;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+       } else if (&resizer->resizer_b.subdev == sd) {
+               switch (local->index | media_entity_type(remote->entity)) {
+               case RESIZER_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+                       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                               resizer->resizer_b.input = RESIZER_INPUT_NONE;
+                               break;
+                       }
+                       if (resizer->resizer_b.input != RESIZER_INPUT_NONE)
+                               return -EBUSY;
+                       resizer->resizer_b.input = RESIZER_INPUT_CROP_RESIZER;
+                       break;
+
+               case RESIZER_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+                       if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                               resizer->resizer_b.output = RESIZER_OUTPUT_NONE;
+                               break;
+                       }
+                       if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE)
+                               return -EBUSY;
+                       resizer->resizer_b.output = RESIZER_OUPUT_MEMORY;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct media_entity_operations resizer_media_ops = {
+       .link_setup = resizer_link_setup,
+};
+
+/*
+ * vpfe_resizer_unregister_entities() - Unregister entity
+ * @vpfe_rsz - pointer to resizer subdevice structure.
+ */
+void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz)
+{
+       /* unregister video devices */
+       vpfe_video_unregister(&vpfe_rsz->resizer_a.video_out);
+       vpfe_video_unregister(&vpfe_rsz->resizer_b.video_out);
+
+       /* cleanup entity */
+       media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity);
+       media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity);
+       media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity);
+       /* unregister subdev */
+       v4l2_device_unregister_subdev(&vpfe_rsz->crop_resizer.subdev);
+       v4l2_device_unregister_subdev(&vpfe_rsz->resizer_a.subdev);
+       v4l2_device_unregister_subdev(&vpfe_rsz->resizer_b.subdev);
+}
+
+/*
+ * vpfe_resizer_register_entities() - Register entity
+ * @resizer - pointer to resizer devive.
+ * @vdev: pointer to v4l2 device structure.
+ */
+int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
+                                  struct v4l2_device *vdev)
+{
+       struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
+       unsigned int flags = 0;
+       int ret;
+
+       /* Register the crop resizer subdev */
+       ret = v4l2_device_register_subdev(vdev, &resizer->crop_resizer.subdev);
+       if (ret < 0) {
+               pr_err("Failed to register crop resizer as v4l2-subdev\n");
+               return ret;
+       }
+       /* Register Resizer-A subdev */
+       ret = v4l2_device_register_subdev(vdev, &resizer->resizer_a.subdev);
+       if (ret < 0) {
+               pr_err("Failed to register resizer-a as v4l2-subdev\n");
+               return ret;
+       }
+       /* Register Resizer-B subdev */
+       ret = v4l2_device_register_subdev(vdev, &resizer->resizer_b.subdev);
+       if (ret < 0) {
+               pr_err("Failed to register resizer-b as v4l2-subdev\n");
+               return ret;
+       }
+       /* Register video-out device for resizer-a */
+       ret = vpfe_video_register(&resizer->resizer_a.video_out, vdev);
+       if (ret) {
+               pr_err("Failed to register RSZ-A video-out device\n");
+               goto out_video_out2_register;
+       }
+       resizer->resizer_a.video_out.vpfe_dev = vpfe_dev;
+
+       /* Register video-out device for resizer-b */
+       ret = vpfe_video_register(&resizer->resizer_b.video_out, vdev);
+       if (ret) {
+               pr_err("Failed to register RSZ-B video-out device\n");
+               goto out_video_out2_register;
+       }
+       resizer->resizer_b.video_out.vpfe_dev = vpfe_dev;
+
+       /* create link between Resizer Crop----> Resizer A*/
+       ret = media_entity_create_link(&resizer->crop_resizer.subdev.entity, 1,
+                               &resizer->resizer_a.subdev.entity,
+                               0, flags);
+       if (ret < 0)
+               goto out_create_link;
+
+       /* create link between Resizer Crop----> Resizer B*/
+       ret = media_entity_create_link(&resizer->crop_resizer.subdev.entity, 2,
+                               &resizer->resizer_b.subdev.entity,
+                               0, flags);
+       if (ret < 0)
+               goto out_create_link;
+
+       /* create link between Resizer A ----> video out */
+       ret = media_entity_create_link(&resizer->resizer_a.subdev.entity, 1,
+               &resizer->resizer_a.video_out.video_dev.entity, 0, flags);
+       if (ret < 0)
+               goto out_create_link;
+
+       /* create link between Resizer B ----> video out */
+       ret = media_entity_create_link(&resizer->resizer_b.subdev.entity, 1,
+               &resizer->resizer_b.video_out.video_dev.entity, 0, flags);
+       if (ret < 0)
+               goto out_create_link;
+
+       return 0;
+
+out_create_link:
+       vpfe_video_unregister(&resizer->resizer_b.video_out);
+out_video_out2_register:
+       vpfe_video_unregister(&resizer->resizer_a.video_out);
+       media_entity_cleanup(&resizer->crop_resizer.subdev.entity);
+       media_entity_cleanup(&resizer->resizer_a.subdev.entity);
+       media_entity_cleanup(&resizer->resizer_b.subdev.entity);
+       v4l2_device_unregister_subdev(&resizer->crop_resizer.subdev);
+       v4l2_device_unregister_subdev(&resizer->resizer_a.subdev);
+       v4l2_device_unregister_subdev(&resizer->resizer_b.subdev);
+       return ret;
+}
+
+/*
+ * vpfe_resizer_init() - resizer device initialization.
+ * @vpfe_rsz - pointer to resizer device
+ * @pdev: platform device pointer.
+ */
+int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz,
+                     struct platform_device *pdev)
+{
+       struct v4l2_subdev *sd = &vpfe_rsz->crop_resizer.subdev;
+       struct media_pad *pads = &vpfe_rsz->crop_resizer.pads[0];
+       struct media_entity *me = &sd->entity;
+       static resource_size_t  res_len;
+       struct resource *res;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 5);
+       if (!res)
+               return -ENOENT;
+
+       res_len = resource_size(res);
+       res = request_mem_region(res->start, res_len, res->name);
+       if (!res)
+               return -EBUSY;
+
+       vpfe_rsz->base_addr = ioremap_nocache(res->start, res_len);
+       if (!vpfe_rsz->base_addr)
+               return -EBUSY;
+
+       v4l2_subdev_init(sd, &resizer_v4l2_ops);
+       sd->internal_ops = &resizer_v4l2_internal_ops;
+       strlcpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
+       v4l2_set_subdevdata(sd, vpfe_rsz);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[RESIZER_CROP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[RESIZER_CROP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+       pads[RESIZER_CROP_PAD_SOURCE2].flags = MEDIA_PAD_FL_SOURCE;
+
+       vpfe_rsz->crop_resizer.input = RESIZER_CROP_INPUT_NONE;
+       vpfe_rsz->crop_resizer.output = RESIZER_CROP_OUTPUT_NONE;
+       vpfe_rsz->crop_resizer.output2 = RESIZER_CROP_OUTPUT_NONE;
+       vpfe_rsz->crop_resizer.rsz_device = vpfe_rsz;
+       me->ops = &resizer_media_ops;
+       ret = media_entity_init(me, RESIZER_CROP_PADS_NUM, pads, 0);
+       if (ret)
+               return ret;
+
+       sd = &vpfe_rsz->resizer_a.subdev;
+       pads = &vpfe_rsz->resizer_a.pads[0];
+       me = &sd->entity;
+
+       v4l2_subdev_init(sd, &resizer_v4l2_ops);
+       sd->internal_ops = &resizer_v4l2_internal_ops;
+       strlcpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
+       v4l2_set_subdevdata(sd, vpfe_rsz);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+       vpfe_rsz->resizer_a.input = RESIZER_INPUT_NONE;
+       vpfe_rsz->resizer_a.output = RESIZER_OUTPUT_NONE;
+       vpfe_rsz->resizer_a.rsz_device = vpfe_rsz;
+       me->ops = &resizer_media_ops;
+       ret = media_entity_init(me, RESIZER_PADS_NUM, pads, 0);
+       if (ret)
+               return ret;
+
+       sd = &vpfe_rsz->resizer_b.subdev;
+       pads = &vpfe_rsz->resizer_b.pads[0];
+       me = &sd->entity;
+
+       v4l2_subdev_init(sd, &resizer_v4l2_ops);
+       sd->internal_ops = &resizer_v4l2_internal_ops;
+       strlcpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
+       v4l2_set_subdevdata(sd, vpfe_rsz);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+       vpfe_rsz->resizer_b.input = RESIZER_INPUT_NONE;
+       vpfe_rsz->resizer_b.output = RESIZER_OUTPUT_NONE;
+       vpfe_rsz->resizer_b.rsz_device = vpfe_rsz;
+       me->ops = &resizer_media_ops;
+       ret = media_entity_init(me, RESIZER_PADS_NUM, pads, 0);
+       if (ret)
+               return ret;
+
+       vpfe_rsz->resizer_a.video_out.ops = &resizer_a_video_ops;
+       vpfe_rsz->resizer_a.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       ret = vpfe_video_init(&vpfe_rsz->resizer_a.video_out, "RSZ-A");
+       if (ret) {
+               pr_err("Failed to init RSZ video-out device\n");
+               return ret;
+       }
+       vpfe_rsz->resizer_b.video_out.ops = &resizer_b_video_ops;
+       vpfe_rsz->resizer_b.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       ret = vpfe_video_init(&vpfe_rsz->resizer_b.video_out, "RSZ-B");
+       if (ret) {
+               pr_err("Failed to init RSZ video-out2 device\n");
+               return ret;
+       }
+       memset(&vpfe_rsz->config, 0, sizeof(struct resizer_params));
+
+       return 0;
+}
+
+void
+vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz,
+                    struct platform_device *pdev)
+{
+       struct resource *res;
+
+       iounmap(vpfe_rsz->base_addr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 5);
+       if (res)
+               release_mem_region(res->start,
+                                       res->end - res->start + 1);
+}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.h b/drivers/staging/media/davinci_vpfe/dm365_resizer.h
new file mode 100644 (file)
index 0000000..59a7942
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_RESIZER_H
+#define _DAVINCI_VPFE_DM365_RESIZER_H
+
+enum resizer_oper_mode {
+       RESIZER_MODE_CONTINIOUS = 0,
+       RESIZER_MODE_ONE_SHOT = 1,
+};
+
+struct f_div_pass {
+       unsigned int o_hsz;
+       unsigned int i_hps;
+       unsigned int h_phs;
+       unsigned int src_hps;
+       unsigned int src_hsz;
+};
+
+#define MAX_PASSES             2
+
+struct f_div_param {
+       unsigned char en;
+       unsigned int num_passes;
+       struct f_div_pass pass[MAX_PASSES];
+};
+
+/* Resizer Rescale Parameters*/
+struct resizer_scale_param {
+       bool h_flip;
+       bool v_flip;
+       bool cen;
+       bool yen;
+       unsigned short i_vps;
+       unsigned short i_hps;
+       unsigned short o_vsz;
+       unsigned short o_hsz;
+       unsigned short v_phs_y;
+       unsigned short v_phs_c;
+       unsigned short v_dif;
+       /* resize method - Luminance */
+       enum vpfe_rsz_intp_t v_typ_y;
+       /* resize method - Chrominance */
+       enum vpfe_rsz_intp_t v_typ_c;
+       /* vertical lpf intensity - Luminance */
+       unsigned char v_lpf_int_y;
+       /* vertical lpf intensity - Chrominance */
+       unsigned char v_lpf_int_c;
+       unsigned short h_phs;
+       unsigned short h_dif;
+       /* resize method - Luminance */
+       enum vpfe_rsz_intp_t h_typ_y;
+       /* resize method - Chrominance */
+       enum vpfe_rsz_intp_t h_typ_c;
+       /* horizontal lpf intensity - Luminance */
+       unsigned char h_lpf_int_y;
+       /* horizontal lpf intensity - Chrominance */
+       unsigned char h_lpf_int_c;
+       bool dscale_en;
+       enum vpfe_rsz_down_scale_ave_sz h_dscale_ave_sz;
+       enum vpfe_rsz_down_scale_ave_sz v_dscale_ave_sz;
+       /* store the calculated frame division parameter */
+       struct f_div_param f_div;
+};
+
+enum resizer_rgb_t {
+       OUTPUT_32BIT,
+       OUTPUT_16BIT
+};
+
+enum resizer_rgb_msk_t {
+       NOMASK = 0,
+       MASKLAST2 = 1,
+};
+
+/* Resizer RGB Conversion Parameters */
+struct resizer_rgb {
+       bool rgb_en;
+       enum resizer_rgb_t rgb_typ;
+       enum resizer_rgb_msk_t rgb_msk0;
+       enum resizer_rgb_msk_t rgb_msk1;
+       unsigned int rgb_alpha_val;
+};
+
+/* Resizer External Memory Parameters */
+struct rsz_ext_mem_param {
+       unsigned int rsz_sdr_oft_y;
+       unsigned int rsz_sdr_ptr_s_y;
+       unsigned int rsz_sdr_ptr_e_y;
+       unsigned int rsz_sdr_oft_c;
+       unsigned int rsz_sdr_ptr_s_c;
+       unsigned int rsz_sdr_ptr_e_c;
+       /* offset to be added to buffer start when flipping for y/ycbcr */
+       unsigned int flip_ofst_y;
+       /* offset to be added to buffer start when flipping for c */
+       unsigned int flip_ofst_c;
+       /* c offset for YUV 420SP */
+       unsigned int c_offset;
+       /* User Defined Y offset for YUV 420SP or YUV420ILE data */
+       unsigned int user_y_ofst;
+       /* User Defined C offset for YUV 420SP data */
+       unsigned int user_c_ofst;
+};
+
+enum rsz_data_source {
+       IPIPE_DATA,
+       IPIPEIF_DATA
+};
+
+enum rsz_src_img_fmt {
+       RSZ_IMG_422,
+       RSZ_IMG_420
+};
+
+enum rsz_dpaths_bypass_t {
+       BYPASS_OFF = 0,
+       BYPASS_ON = 1,
+};
+
+struct rsz_common_params {
+       unsigned int vps;
+       unsigned int vsz;
+       unsigned int hps;
+       unsigned int hsz;
+       /* 420 or 422 */
+       enum rsz_src_img_fmt src_img_fmt;
+       /* Y or C when src_fmt is 420, 0 - y, 1 - c */
+       unsigned char y_c;
+       /* flip raw or ycbcr */
+       unsigned char raw_flip;
+       /* IPIPE or IPIPEIF data */
+       enum rsz_data_source source;
+       enum rsz_dpaths_bypass_t passthrough;
+       unsigned char yuv_y_min;
+       unsigned char yuv_y_max;
+       unsigned char yuv_c_min;
+       unsigned char yuv_c_max;
+       bool rsz_seq_crv;
+       enum vpfe_chr_pos out_chr_pos;
+};
+
+struct resizer_params {
+       enum resizer_oper_mode oper_mode;
+       struct rsz_common_params rsz_common;
+       struct resizer_scale_param rsz_rsc_param[2];
+       struct resizer_rgb rsz2rgb[2];
+       struct rsz_ext_mem_param ext_mem_param[2];
+       bool rsz_en[2];
+       struct vpfe_rsz_config_params user_config;
+};
+
+#define ENABLE                 1
+#define DISABLE                        (!ENABLE)
+
+#define RESIZER_CROP_PAD_SINK          0
+#define RESIZER_CROP_PAD_SOURCE                1
+#define RESIZER_CROP_PAD_SOURCE2       2
+
+#define RESIZER_CROP_PADS_NUM          3
+
+enum resizer_crop_input_entity {
+       RESIZER_CROP_INPUT_NONE = 0,
+       RESIZER_CROP_INPUT_IPIPEIF = 1,
+       RESIZER_CROP_INPUT_IPIPE = 2,
+};
+
+enum resizer_crop_output_entity {
+       RESIZER_CROP_OUTPUT_NONE,
+       RESIZER_A,
+       RESIZER_B,
+};
+
+struct dm365_crop_resizer_device {
+       struct v4l2_subdev                      subdev;
+       struct media_pad                        pads[RESIZER_CROP_PADS_NUM];
+       struct v4l2_mbus_framefmt               formats[RESIZER_CROP_PADS_NUM];
+       enum resizer_crop_input_entity          input;
+       enum resizer_crop_output_entity         output;
+       enum resizer_crop_output_entity         output2;
+       struct vpfe_resizer_device              *rsz_device;
+};
+
+#define RESIZER_PAD_SINK               0
+#define RESIZER_PAD_SOURCE             1
+
+#define RESIZER_PADS_NUM               2
+
+enum resizer_input_entity {
+       RESIZER_INPUT_NONE = 0,
+       RESIZER_INPUT_CROP_RESIZER = 1,
+};
+
+enum resizer_output_entity {
+       RESIZER_OUTPUT_NONE = 0,
+       RESIZER_OUPUT_MEMORY = 1,
+};
+
+struct dm365_resizer_device {
+       struct v4l2_subdev              subdev;
+       struct media_pad                pads[RESIZER_PADS_NUM];
+       struct v4l2_mbus_framefmt       formats[RESIZER_PADS_NUM];
+       enum resizer_input_entity       input;
+       enum resizer_output_entity      output;
+       struct vpfe_video_device        video_out;
+       struct vpfe_resizer_device      *rsz_device;
+};
+
+struct vpfe_resizer_device {
+       struct dm365_crop_resizer_device        crop_resizer;
+       struct dm365_resizer_device             resizer_a;
+       struct dm365_resizer_device             resizer_b;
+       struct resizer_params                   config;
+       void *__iomem base_addr;
+};
+
+int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz,
+                     struct platform_device *pdev);
+int vpfe_resizer_register_entities(struct vpfe_resizer_device *vpfe_rsz,
+                                  struct v4l2_device *v4l2_dev);
+void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz);
+void vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz,
+                         struct platform_device *pdev);
+void vpfe_resizer_buffer_isr(struct vpfe_resizer_device *resizer);
+void vpfe_resizer_dma_isr(struct vpfe_resizer_device *resizer);
+
+#endif         /* _DAVINCI_VPFE_DM365_RESIZER_H */
diff --git a/drivers/staging/media/davinci_vpfe/vpfe.h b/drivers/staging/media/davinci_vpfe/vpfe.h
new file mode 100644 (file)
index 0000000..0587bc5
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _VPFE_H
+#define _VPFE_H
+
+#ifdef __KERNEL__
+#include <linux/v4l2-subdev.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+
+#include <media/davinci/vpfe_types.h>
+
+#define CAPTURE_DRV_NAME       "vpfe-capture"
+
+struct vpfe_route {
+       __u32 input;
+       __u32 output;
+};
+
+enum vpfe_subdev_id {
+       VPFE_SUBDEV_TVP5146 = 1,
+       VPFE_SUBDEV_MT9T031 = 2,
+       VPFE_SUBDEV_TVP7002 = 3,
+       VPFE_SUBDEV_MT9P031 = 4,
+};
+
+struct vpfe_ext_subdev_info {
+       /* v4l2 subdev */
+       struct v4l2_subdev *subdev;
+       /* Sub device module name */
+       char module_name[32];
+       /* Sub device group id */
+       int grp_id;
+       /* Number of inputs supported */
+       int num_inputs;
+       /* inputs available at the sub device */
+       struct v4l2_input *inputs;
+       /* Sub dev routing information for each input */
+       struct vpfe_route *routes;
+       /* ccdc bus/interface configuration */
+       struct vpfe_hw_if_param ccdc_if_params;
+       /* i2c subdevice board info */
+       struct i2c_board_info board_info;
+       /* Is this a camera sub device ? */
+       unsigned is_camera:1;
+       /* check if sub dev supports routing */
+       unsigned can_route:1;
+       /* registered ? */
+       unsigned registered:1;
+};
+
+struct vpfe_config {
+       /* Number of sub devices connected to vpfe */
+       int num_subdevs;
+       /* information about each subdev */
+       struct vpfe_ext_subdev_info *sub_devs;
+       /* evm card info */
+       char *card_name;
+       /* setup function for the input path */
+       int (*setup_input)(enum vpfe_subdev_id id);
+       /* number of clocks */
+       int num_clocks;
+       /* clocks used for vpfe capture */
+       char *clocks[];
+};
+#endif
+#endif
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
new file mode 100644 (file)
index 0000000..7b35171
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ *
+ *
+ * Driver name : VPFE Capture driver
+ *    VPFE Capture driver allows applications to capture and stream video
+ *    frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
+ *    TVP5146 or  Raw Bayer RGB image data from an image sensor
+ *    such as Microns' MT9T001, MT9T031 etc.
+ *
+ *    These SoCs have, in common, a Video Processing Subsystem (VPSS) that
+ *    consists of a Video Processing Front End (VPFE) for capturing
+ *    video/raw image data and Video Processing Back End (VPBE) for displaying
+ *    YUV data through an in-built analog encoder or Digital LCD port. This
+ *    driver is for capture through VPFE. A typical EVM using these SoCs have
+ *    following high level configuration.
+ *
+ *    decoder(TVP5146/         YUV/
+ *     MT9T001)   -->  Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
+ *                     data input              |      |
+ *                                                     V      |
+ *                                                   SDRAM    |
+ *                                                            V
+ *                                                        Image Processor
+ *                                                            |
+ *                                                            V
+ *                                                          SDRAM
+ *    The data flow happens from a decoder connected to the VPFE over a
+ *    YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
+ *    and to the input of VPFE through an optional MUX (if more inputs are
+ *    to be interfaced on the EVM). The input data is first passed through
+ *    CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
+ *    does very little or no processing on YUV data and does pre-process Raw
+ *    Bayer RGB data through modules such as Defect Pixel Correction (DFC)
+ *    Color Space Conversion (CSC), data gain/offset etc. After this, data
+ *    can be written to SDRAM or can be connected to the image processing
+ *    block such as IPIPE (on DM355/DM365 only).
+ *
+ *    Features supported
+ *             - MMAP IO
+ *             - USERPTR IO
+ *             - Capture using TVP5146 over BT.656
+ *             - Support for interfacing decoders using sub device model
+ *             - Work with DM365 or DM355 or DM6446 CCDC to do Raw Bayer
+ *               RGB/YUV data capture to SDRAM.
+ *             - Chaining of Image Processor
+ *             - SINGLE-SHOT mode
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "vpfe.h"
+#include "vpfe_mc_capture.h"
+
+static bool debug;
+static bool interface;
+
+module_param(interface, bool, S_IRUGO);
+module_param(debug, bool, 0644);
+
+/**
+ * VPFE capture can be used for capturing video such as from TVP5146 or TVP7002
+ * and for capture raw bayer data from camera sensors such as mt9p031. At this
+ * point there is problem in co-existence of mt9p031 and tvp5146 due to i2c
+ * address collision. So set the variable below from bootargs to do either video
+ * capture or camera capture.
+ * interface = 0 - video capture (from TVP514x or such),
+ * interface = 1 - Camera capture (from mt9p031 or such)
+ * Re-visit this when we fix the co-existence issue
+ */
+MODULE_PARM_DESC(interface, "interface 0-1 (default:0)");
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments");
+
+/* map mbus_fmt to pixelformat */
+void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus,
+                          struct v4l2_pix_format *pix)
+{
+       switch (mbus->code) {
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+               pix->pixelformat = V4L2_PIX_FMT_UYVY;
+               pix->bytesperline = pix->width * 2;
+               break;
+
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+               pix->pixelformat = V4L2_PIX_FMT_YUYV;
+               pix->bytesperline = pix->width * 2;
+               break;
+
+       case V4L2_MBUS_FMT_YUYV10_1X20:
+               pix->pixelformat = V4L2_PIX_FMT_UYVY;
+               pix->bytesperline = pix->width * 2;
+               break;
+
+       case V4L2_MBUS_FMT_SGRBG12_1X12:
+               pix->pixelformat = V4L2_PIX_FMT_SBGGR16;
+               pix->bytesperline = pix->width * 2;
+               break;
+
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+               pix->pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8;
+               pix->bytesperline = pix->width;
+               break;
+
+       case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+               pix->pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8;
+               pix->bytesperline = pix->width;
+               break;
+
+       case V4L2_MBUS_FMT_YDYUYDYV8_1X16:
+               pix->pixelformat = V4L2_PIX_FMT_NV12;
+               pix->bytesperline = pix->width;
+               break;
+
+       case V4L2_MBUS_FMT_Y8_1X8:
+               pix->pixelformat = V4L2_PIX_FMT_GREY;
+               pix->bytesperline = pix->width;
+               break;
+
+       case V4L2_MBUS_FMT_UV8_1X8:
+               pix->pixelformat = V4L2_PIX_FMT_UV8;
+               pix->bytesperline = pix->width;
+               break;
+
+       default:
+               pr_err("Invalid mbus code set\n");
+       }
+       /* pitch should be 32 bytes aligned */
+       pix->bytesperline = ALIGN(pix->bytesperline, 32);
+       if (pix->pixelformat == V4L2_PIX_FMT_NV12)
+               pix->sizeimage = pix->bytesperline * pix->height +
+                               ((pix->bytesperline * pix->height) >> 1);
+       else
+               pix->sizeimage = pix->bytesperline * pix->height;
+}
+
+/* ISR for VINT0*/
+static irqreturn_t vpfe_isr(int irq, void *dev_id)
+{
+       struct vpfe_device *vpfe_dev = dev_id;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_isr\n");
+       vpfe_isif_buffer_isr(&vpfe_dev->vpfe_isif);
+       vpfe_resizer_buffer_isr(&vpfe_dev->vpfe_resizer);
+       return IRQ_HANDLED;
+}
+
+/* vpfe_vdint1_isr() - isr handler for VINT1 interrupt */
+static irqreturn_t vpfe_vdint1_isr(int irq, void *dev_id)
+{
+       struct vpfe_device *vpfe_dev = dev_id;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_vdint1_isr\n");
+       vpfe_isif_vidint1_isr(&vpfe_dev->vpfe_isif);
+       return IRQ_HANDLED;
+}
+
+/* vpfe_imp_dma_isr() - ISR for ipipe dma completion */
+static irqreturn_t vpfe_imp_dma_isr(int irq, void *dev_id)
+{
+       struct vpfe_device *vpfe_dev = dev_id;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_imp_dma_isr\n");
+       vpfe_ipipeif_ss_buffer_isr(&vpfe_dev->vpfe_ipipeif);
+       vpfe_resizer_dma_isr(&vpfe_dev->vpfe_resizer);
+       return IRQ_HANDLED;
+}
+
+/*
+ * vpfe_disable_clock() - Disable clocks for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Disables clocks defined in vpfe configuration. The function
+ * assumes that at least one clock is to be defined which is
+ * true as of now.
+ */
+static void vpfe_disable_clock(struct vpfe_device *vpfe_dev)
+{
+       struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
+       int i;
+
+       for (i = 0; i < vpfe_cfg->num_clocks; i++) {
+               clk_disable_unprepare(vpfe_dev->clks[i]);
+               clk_put(vpfe_dev->clks[i]);
+       }
+       kzfree(vpfe_dev->clks);
+       v4l2_info(vpfe_dev->pdev->driver, "vpfe capture clocks disabled\n");
+}
+
+/*
+ * vpfe_enable_clock() - Enable clocks for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Enables clocks defined in vpfe configuration. The function
+ * assumes that at least one clock is to be defined which is
+ * true as of now.
+ */
+static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
+{
+       struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
+       int ret = -EFAULT;
+       int i;
+
+       if (!vpfe_cfg->num_clocks)
+               return 0;
+
+       vpfe_dev->clks = kzalloc(vpfe_cfg->num_clocks *
+                                  sizeof(struct clock *), GFP_KERNEL);
+       if (vpfe_dev->clks == NULL) {
+               v4l2_err(vpfe_dev->pdev->driver, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < vpfe_cfg->num_clocks; i++) {
+               if (vpfe_cfg->clocks[i] == NULL) {
+                       v4l2_err(vpfe_dev->pdev->driver,
+                               "clock %s is not defined in vpfe config\n",
+                               vpfe_cfg->clocks[i]);
+                       goto out;
+               }
+
+               vpfe_dev->clks[i] =
+                               clk_get(vpfe_dev->pdev, vpfe_cfg->clocks[i]);
+               if (vpfe_dev->clks[i] == NULL) {
+                       v4l2_err(vpfe_dev->pdev->driver,
+                               "Failed to get clock %s\n",
+                               vpfe_cfg->clocks[i]);
+                       goto out;
+               }
+
+               if (clk_prepare_enable(vpfe_dev->clks[i])) {
+                       v4l2_err(vpfe_dev->pdev->driver,
+                               "vpfe clock %s not enabled\n",
+                               vpfe_cfg->clocks[i]);
+                       goto out;
+               }
+
+               v4l2_info(vpfe_dev->pdev->driver, "vpss clock %s enabled",
+                         vpfe_cfg->clocks[i]);
+       }
+
+       return 0;
+out:
+       for (i = 0; i < vpfe_cfg->num_clocks; i++)
+               if (vpfe_dev->clks[i]) {
+                       clk_disable_unprepare(vpfe_dev->clks[i]);
+                       clk_put(vpfe_dev->clks[i]);
+               }
+
+       v4l2_err(vpfe_dev->pdev->driver, "Failed to enable clocks\n");
+       kzfree(vpfe_dev->clks);
+
+       return ret;
+}
+
+/*
+ * vpfe_detach_irq() - Detach IRQs for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Detach all IRQs defined in vpfe configuration.
+ */
+static void vpfe_detach_irq(struct vpfe_device *vpfe_dev)
+{
+       free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+       free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);
+       free_irq(vpfe_dev->imp_dma_irq, vpfe_dev);
+}
+
+/*
+ * vpfe_attach_irq() - Attach IRQs for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Attach all IRQs defined in vpfe configuration.
+ */
+static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
+{
+       int ret = 0;
+
+       ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
+                         "vpfe_capture0", vpfe_dev);
+       if (ret < 0) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                       "Error: requesting VINT0 interrupt\n");
+               return ret;
+       }
+
+       ret = request_irq(vpfe_dev->ccdc_irq1, vpfe_vdint1_isr, IRQF_DISABLED,
+                         "vpfe_capture1", vpfe_dev);
+       if (ret < 0) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                       "Error: requesting VINT1 interrupt\n");
+               free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+               return ret;
+       }
+
+       ret = request_irq(vpfe_dev->imp_dma_irq, vpfe_imp_dma_isr,
+                         IRQF_DISABLED, "Imp_Sdram_Irq", vpfe_dev);
+       if (ret < 0) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                        "Error: requesting IMP IRQ interrupt\n");
+               free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);
+               free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * register_i2c_devices() - register all i2c v4l2 subdevs
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * register all i2c v4l2 subdevs
+ */
+static int register_i2c_devices(struct vpfe_device *vpfe_dev)
+{
+       struct vpfe_ext_subdev_info *sdinfo;
+       struct vpfe_config *vpfe_cfg;
+       struct i2c_adapter *i2c_adap;
+       unsigned int num_subdevs;
+       int ret;
+       int i;
+       int k;
+
+       vpfe_cfg = vpfe_dev->cfg;
+       i2c_adap = i2c_get_adapter(1);
+       num_subdevs = vpfe_cfg->num_subdevs;
+       vpfe_dev->sd =
+                 kzalloc(sizeof(struct v4l2_subdev *)*num_subdevs, GFP_KERNEL);
+       if (vpfe_dev->sd == NULL) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                       "unable to allocate memory for subdevice\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0, k = 0; i < num_subdevs; i++) {
+               sdinfo = &vpfe_cfg->sub_devs[i];
+               /*
+                * register subdevices based on interface setting. Currently
+                * tvp5146 and mt9p031 cannot co-exists due to i2c address
+                * conflicts. So only one of them is registered. Re-visit this
+                * once we have support for i2c switch handling in i2c driver
+                * framework
+                */
+               if (interface == sdinfo->is_camera) {
+                       /* setup input path */
+                       if (vpfe_cfg->setup_input &&
+                               vpfe_cfg->setup_input(sdinfo->grp_id) < 0) {
+                               ret = -EFAULT;
+                               v4l2_info(&vpfe_dev->v4l2_dev,
+                                         "could not setup input for %s\n",
+                                               sdinfo->module_name);
+                               goto probe_sd_out;
+                       }
+                       /* Load up the subdevice */
+                       vpfe_dev->sd[k] =
+                               v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev,
+                                                 i2c_adap, &sdinfo->board_info,
+                                                 NULL);
+                       if (vpfe_dev->sd[k]) {
+                               v4l2_info(&vpfe_dev->v4l2_dev,
+                                               "v4l2 sub device %s registered\n",
+                                               sdinfo->module_name);
+
+                               vpfe_dev->sd[k]->grp_id = sdinfo->grp_id;
+                               k++;
+
+                               sdinfo->registered = 1;
+                       }
+               } else {
+                       v4l2_info(&vpfe_dev->v4l2_dev,
+                                 "v4l2 sub device %s is not registered\n",
+                                 sdinfo->module_name);
+               }
+       }
+       vpfe_dev->num_ext_subdevs = k;
+
+       return 0;
+
+probe_sd_out:
+       kzfree(vpfe_dev->sd);
+
+       return ret;
+}
+
+/*
+ * vpfe_register_entities() - register all v4l2 subdevs and media entities
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * register all v4l2 subdevs, media entities, and creates links
+ * between entities
+ */
+static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
+{
+       unsigned int flags = 0;
+       int ret;
+       int i;
+
+       /* register i2c devices first */
+       ret = register_i2c_devices(vpfe_dev);
+       if (ret)
+               return ret;
+
+       /* register rest of the sub-devs */
+       ret = vpfe_isif_register_entities(&vpfe_dev->vpfe_isif,
+                                         &vpfe_dev->v4l2_dev);
+       if (ret)
+               return ret;
+
+       ret = vpfe_ipipeif_register_entities(&vpfe_dev->vpfe_ipipeif,
+                                            &vpfe_dev->v4l2_dev);
+       if (ret)
+               goto out_isif_register;
+
+       ret = vpfe_ipipe_register_entities(&vpfe_dev->vpfe_ipipe,
+                                          &vpfe_dev->v4l2_dev);
+       if (ret)
+               goto out_ipipeif_register;
+
+       ret = vpfe_resizer_register_entities(&vpfe_dev->vpfe_resizer,
+                                            &vpfe_dev->v4l2_dev);
+       if (ret)
+               goto out_ipipe_register;
+
+       /* create links now, starting with external(i2c) entities */
+       for (i = 0; i < vpfe_dev->num_ext_subdevs; i++)
+               /* if entity has no pads (ex: amplifier),
+                  cant establish link */
+               if (vpfe_dev->sd[i]->entity.num_pads) {
+                       ret = media_entity_create_link(&vpfe_dev->sd[i]->entity,
+                               0, &vpfe_dev->vpfe_isif.subdev.entity,
+                               0, flags);
+                       if (ret < 0)
+                               goto out_resizer_register;
+               }
+
+       ret = media_entity_create_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
+                                      &vpfe_dev->vpfe_ipipeif.subdev.entity,
+                                      0, flags);
+       if (ret < 0)
+               goto out_resizer_register;
+
+       ret = media_entity_create_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
+                                      &vpfe_dev->vpfe_ipipe.subdev.entity,
+                                      0, flags);
+       if (ret < 0)
+               goto out_resizer_register;
+
+       ret = media_entity_create_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
+                       1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
+                       0, flags);
+       if (ret < 0)
+               goto out_resizer_register;
+
+       ret = media_entity_create_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
+                       &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
+                       0, flags);
+       if (ret < 0)
+               goto out_resizer_register;
+
+       ret = v4l2_device_register_subdev_nodes(&vpfe_dev->v4l2_dev);
+       if (ret < 0)
+               goto out_resizer_register;
+
+       return 0;
+
+out_resizer_register:
+       vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer);
+out_ipipe_register:
+       vpfe_ipipe_unregister_entities(&vpfe_dev->vpfe_ipipe);
+out_ipipeif_register:
+       vpfe_ipipeif_unregister_entities(&vpfe_dev->vpfe_ipipeif);
+out_isif_register:
+       vpfe_isif_unregister_entities(&vpfe_dev->vpfe_isif);
+
+       return ret;
+}
+
+/*
+ * vpfe_unregister_entities() - unregister all v4l2 subdevs and media entities
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * unregister all v4l2 subdevs and media entities
+ */
+static void vpfe_unregister_entities(struct vpfe_device *vpfe_dev)
+{
+       vpfe_isif_unregister_entities(&vpfe_dev->vpfe_isif);
+       vpfe_ipipeif_unregister_entities(&vpfe_dev->vpfe_ipipeif);
+       vpfe_ipipe_unregister_entities(&vpfe_dev->vpfe_ipipe);
+       vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer);
+}
+
+/*
+ * vpfe_cleanup_modules() - cleanup all non-i2c v4l2 subdevs
+ * @vpfe_dev - ptr to vpfe capture device
+ * @pdev - pointer to platform device
+ *
+ * cleanup all v4l2 subdevs
+ */
+static void vpfe_cleanup_modules(struct vpfe_device *vpfe_dev,
+                                struct platform_device *pdev)
+{
+       vpfe_isif_cleanup(&vpfe_dev->vpfe_isif, pdev);
+       vpfe_ipipeif_cleanup(&vpfe_dev->vpfe_ipipeif, pdev);
+       vpfe_ipipe_cleanup(&vpfe_dev->vpfe_ipipe, pdev);
+       vpfe_resizer_cleanup(&vpfe_dev->vpfe_resizer, pdev);
+}
+
+/*
+ * vpfe_initialize_modules() - initialize all non-i2c v4l2 subdevs
+ * @vpfe_dev - ptr to vpfe capture device
+ * @pdev - pointer to platform device
+ *
+ * intialize all v4l2 subdevs and media entities
+ */
+static int vpfe_initialize_modules(struct vpfe_device *vpfe_dev,
+                                  struct platform_device *pdev)
+{
+       int ret;
+
+       ret = vpfe_isif_init(&vpfe_dev->vpfe_isif, pdev);
+       if (ret)
+               return ret;
+
+       ret = vpfe_ipipeif_init(&vpfe_dev->vpfe_ipipeif, pdev);
+       if (ret)
+               goto out_isif_init;
+
+       ret = vpfe_ipipe_init(&vpfe_dev->vpfe_ipipe, pdev);
+       if (ret)
+               goto out_ipipeif_init;
+
+       ret = vpfe_resizer_init(&vpfe_dev->vpfe_resizer, pdev);
+       if (ret)
+               goto out_ipipe_init;
+
+       return 0;
+
+out_ipipe_init:
+       vpfe_ipipe_cleanup(&vpfe_dev->vpfe_ipipe, pdev);
+out_ipipeif_init:
+       vpfe_ipipeif_cleanup(&vpfe_dev->vpfe_ipipeif, pdev);
+out_isif_init:
+       vpfe_isif_cleanup(&vpfe_dev->vpfe_isif, pdev);
+
+       return ret;
+}
+
+/*
+ * vpfe_probe() : vpfe probe function
+ * @pdev: platform device pointer
+ *
+ * This function creates device entries by register itself to the V4L2 driver
+ * and initializes fields of each device objects
+ */
+static int vpfe_probe(struct platform_device *pdev)
+{
+       struct vpfe_device *vpfe_dev;
+       struct resource *res1;
+       int ret = -ENOMEM;
+
+       vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL);
+       if (!vpfe_dev) {
+               v4l2_err(pdev->dev.driver,
+                       "Failed to allocate memory for vpfe_dev\n");
+               return ret;
+       }
+
+       if (pdev->dev.platform_data == NULL) {
+               v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
+               ret = -ENOENT;
+               goto probe_free_dev_mem;
+       }
+
+       vpfe_dev->cfg = pdev->dev.platform_data;
+       if (vpfe_dev->cfg->card_name == NULL ||
+                       vpfe_dev->cfg->sub_devs == NULL) {
+               v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");
+               ret = -ENOENT;
+               goto probe_free_dev_mem;
+       }
+
+       /* Get VINT0 irq resource */
+       res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res1) {
+               v4l2_err(pdev->dev.driver,
+                        "Unable to get interrupt for VINT0\n");
+               ret = -ENOENT;
+               goto probe_free_dev_mem;
+       }
+       vpfe_dev->ccdc_irq0 = res1->start;
+
+       /* Get VINT1 irq resource */
+       res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+       if (!res1) {
+               v4l2_err(pdev->dev.driver,
+                        "Unable to get interrupt for VINT1\n");
+               ret = -ENOENT;
+               goto probe_free_dev_mem;
+       }
+       vpfe_dev->ccdc_irq1 = res1->start;
+
+       /* Get DMA irq resource */
+       res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
+       if (!res1) {
+               v4l2_err(pdev->dev.driver,
+                        "Unable to get interrupt for DMA\n");
+               ret = -ENOENT;
+               goto probe_free_dev_mem;
+       }
+       vpfe_dev->imp_dma_irq = res1->start;
+
+       vpfe_dev->pdev = &pdev->dev;
+
+       /* enable vpss clocks */
+       ret = vpfe_enable_clock(vpfe_dev);
+       if (ret)
+               goto probe_free_dev_mem;
+
+       if (vpfe_initialize_modules(vpfe_dev, pdev))
+               goto probe_disable_clock;
+
+       vpfe_dev->media_dev.dev = vpfe_dev->pdev;
+       strcpy((char *)&vpfe_dev->media_dev.model, "davinci-media");
+
+       ret = media_device_register(&vpfe_dev->media_dev);
+       if (ret) {
+               v4l2_err(pdev->dev.driver,
+                       "Unable to register media device.\n");
+               goto probe_out_entities_cleanup;
+       }
+
+       vpfe_dev->v4l2_dev.mdev = &vpfe_dev->media_dev;
+       ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);
+       if (ret) {
+               v4l2_err(pdev->dev.driver, "Unable to register v4l2 device.\n");
+               goto probe_out_media_unregister;
+       }
+
+       v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");
+       /* set the driver data in platform device */
+       platform_set_drvdata(pdev, vpfe_dev);
+       /* register subdevs/entities */
+       if (vpfe_register_entities(vpfe_dev))
+               goto probe_out_v4l2_unregister;
+
+       ret = vpfe_attach_irq(vpfe_dev);
+       if (ret)
+               goto probe_out_entities_unregister;
+
+       return 0;
+
+probe_out_entities_unregister:
+       vpfe_unregister_entities(vpfe_dev);
+       kzfree(vpfe_dev->sd);
+probe_out_v4l2_unregister:
+       v4l2_device_unregister(&vpfe_dev->v4l2_dev);
+probe_out_media_unregister:
+       media_device_unregister(&vpfe_dev->media_dev);
+probe_out_entities_cleanup:
+       vpfe_cleanup_modules(vpfe_dev, pdev);
+probe_disable_clock:
+       vpfe_disable_clock(vpfe_dev);
+probe_free_dev_mem:
+       kzfree(vpfe_dev);
+
+       return ret;
+}
+
+/*
+ * vpfe_remove : This function un-registers device from V4L2 driver
+ */
+static int vpfe_remove(struct platform_device *pdev)
+{
+       struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
+
+       v4l2_info(pdev->dev.driver, "vpfe_remove\n");
+
+       kzfree(vpfe_dev->sd);
+       vpfe_detach_irq(vpfe_dev);
+       vpfe_unregister_entities(vpfe_dev);
+       vpfe_cleanup_modules(vpfe_dev, pdev);
+       v4l2_device_unregister(&vpfe_dev->v4l2_dev);
+       media_device_unregister(&vpfe_dev->media_dev);
+       vpfe_disable_clock(vpfe_dev);
+       kzfree(vpfe_dev);
+
+       return 0;
+}
+
+static struct platform_driver vpfe_driver = {
+       .driver = {
+               .name = CAPTURE_DRV_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = vpfe_probe,
+       .remove = vpfe_remove,
+};
+
+/**
+ * vpfe_init : This function registers device driver
+ */
+static __init int vpfe_init(void)
+{
+       /* Register driver to the kernel */
+       return platform_driver_register(&vpfe_driver);
+}
+
+/**
+ * vpfe_cleanup : This function un-registers device driver
+ */
+static void vpfe_cleanup(void)
+{
+       platform_driver_unregister(&vpfe_driver);
+}
+
+module_init(vpfe_init);
+module_exit(vpfe_cleanup);
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h
new file mode 100644 (file)
index 0000000..68f6fe4
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_MC_CAPTURE_H
+#define _DAVINCI_VPFE_MC_CAPTURE_H
+
+#include "dm365_ipipe.h"
+#include "dm365_ipipeif.h"
+#include "dm365_isif.h"
+#include "dm365_resizer.h"
+#include "vpfe_video.h"
+
+#define VPFE_MAJOR_RELEASE             0
+#define VPFE_MINOR_RELEASE             0
+#define VPFE_BUILD                     1
+#define VPFE_CAPTURE_VERSION_CODE       ((VPFE_MAJOR_RELEASE << 16) | \
+                                       (VPFE_MINOR_RELEASE << 8)  | \
+                                       VPFE_BUILD)
+
+/* IPIPE hardware limits */
+#define IPIPE_MAX_OUTPUT_WIDTH_A       2176
+#define IPIPE_MAX_OUTPUT_WIDTH_B       640
+
+/* Based on max resolution supported. QXGA */
+#define IPIPE_MAX_OUTPUT_HEIGHT_A      1536
+/* Based on max resolution supported. VGA */
+#define IPIPE_MAX_OUTPUT_HEIGHT_B      480
+
+#define to_vpfe_device(ptr_module)                             \
+       container_of(ptr_module, struct vpfe_device, vpfe_##ptr_module)
+#define to_device(ptr_module)                                          \
+       (to_vpfe_device(ptr_module)->dev)
+
+struct vpfe_device {
+       /* external registered sub devices */
+       struct v4l2_subdev              **sd;
+       /* number of registered external subdevs */
+       unsigned int                    num_ext_subdevs;
+       /* vpfe cfg */
+       struct vpfe_config              *cfg;
+       /* clock ptrs for vpfe capture */
+       struct clk                      **clks;
+       /* V4l2 device */
+       struct v4l2_device              v4l2_dev;
+       /* parent device */
+       struct device                   *pdev;
+       /* IRQ number for DMA transfer completion at the image processor */
+       unsigned int                    imp_dma_irq;
+       /* CCDC IRQs used when CCDC/ISIF output to SDRAM */
+       unsigned int                    ccdc_irq0;
+       unsigned int                    ccdc_irq1;
+       /* maximum video memory that is available*/
+       unsigned int                    video_limit;
+       /* media device */
+       struct media_device             media_dev;
+       /* ccdc subdevice */
+       struct vpfe_isif_device         vpfe_isif;
+       /* ipipeif subdevice */
+       struct vpfe_ipipeif_device      vpfe_ipipeif;
+       /* ipipe subdevice */
+       struct vpfe_ipipe_device        vpfe_ipipe;
+       /* resizer subdevice */
+       struct vpfe_resizer_device      vpfe_resizer;
+};
+
+/* File handle structure */
+struct vpfe_fh {
+       struct v4l2_fh vfh;
+       struct vpfe_video_device *video;
+       /* Indicates whether this file handle is doing IO */
+       u8 io_allowed;
+       /* Used to keep track priority of this instance */
+       enum v4l2_priority prio;
+};
+
+void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus,
+                          struct v4l2_pix_format *pix);
+
+#endif         /* _DAVINCI_VPFE_MC_CAPTURE_H */
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
new file mode 100644 (file)
index 0000000..99ccbeb
--- /dev/null
@@ -0,0 +1,1620 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-ioctl.h>
+
+#include "vpfe.h"
+#include "vpfe_mc_capture.h"
+
+/* minimum number of buffers needed in cont-mode */
+#define MIN_NUM_BUFFERS                        3
+
+static int debug;
+
+/* get v4l2 subdev pointer to external subdev which is active */
+static struct media_entity *vpfe_get_input_entity
+                       (struct vpfe_video_device *video)
+{
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct media_pad *remote;
+
+       remote = media_entity_remote_source(&vpfe_dev->vpfe_isif.pads[0]);
+       if (remote == NULL) {
+               pr_err("Invalid media connection to isif/ccdc\n");
+               return NULL;
+       }
+       return remote->entity;
+}
+
+/* updates external subdev(sensor/decoder) which is active */
+static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video)
+{
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_config *vpfe_cfg;
+       struct v4l2_subdev *subdev;
+       struct media_pad *remote;
+       int i;
+
+       remote = media_entity_remote_source(&vpfe_dev->vpfe_isif.pads[0]);
+       if (remote == NULL) {
+               pr_err("Invalid media connection to isif/ccdc\n");
+               return -EINVAL;
+       }
+
+       subdev = media_entity_to_v4l2_subdev(remote->entity);
+       vpfe_cfg = vpfe_dev->pdev->platform_data;
+       for (i = 0; i < vpfe_cfg->num_subdevs; i++) {
+               if (!strcmp(vpfe_cfg->sub_devs[i].module_name, subdev->name)) {
+                       video->current_ext_subdev = &vpfe_cfg->sub_devs[i];
+                       break;
+               }
+       }
+
+       /* if user not linked decoder/sensor to isif/ccdc */
+       if (i == vpfe_cfg->num_subdevs) {
+               pr_err("Invalid media chain connection to isif/ccdc\n");
+               return -EINVAL;
+       }
+       /* find the v4l2 subdev pointer */
+       for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) {
+               if (!strcmp(video->current_ext_subdev->module_name,
+                       vpfe_dev->sd[i]->name))
+                       video->current_ext_subdev->subdev = vpfe_dev->sd[i];
+       }
+       return 0;
+}
+
+/* get the subdev which is connected to the output video node */
+static struct v4l2_subdev *
+vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad)
+{
+       struct media_pad *remote = media_entity_remote_source(&video->pad);
+
+       if (remote == NULL || remote->entity->type != MEDIA_ENT_T_V4L2_SUBDEV)
+               return NULL;
+       if (pad)
+               *pad = remote->index;
+       return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+/* get the format set at output pad of the adjacent subdev */
+static int
+__vpfe_video_get_format(struct vpfe_video_device *video,
+                       struct v4l2_format *format)
+{
+       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev *subdev;
+       struct media_pad *remote;
+       u32 pad;
+       int ret;
+
+       subdev = vpfe_video_remote_subdev(video, &pad);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       remote = media_entity_remote_source(&video->pad);
+       fmt.pad = remote->index;
+
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+       if (ret == -ENOIOCTLCMD)
+               return -EINVAL;
+
+       format->type = video->type;
+       /* convert mbus_format to v4l2_format */
+       v4l2_fill_pix_format(&format->fmt.pix, &fmt.format);
+       mbus_to_pix(&fmt.format, &format->fmt.pix);
+
+       return 0;
+}
+
+/* make a note of pipeline details */
+static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
+{
+       struct media_entity *entity = &video->video_dev.entity;
+       struct media_device *mdev = entity->parent;
+       struct vpfe_pipeline *pipe = &video->pipe;
+       struct vpfe_video_device *far_end = NULL;
+       struct media_entity_graph graph;
+
+       pipe->input_num = 0;
+       pipe->output_num = 0;
+
+       if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               pipe->inputs[pipe->input_num++] = video;
+       else
+               pipe->outputs[pipe->output_num++] = video;
+
+       mutex_lock(&mdev->graph_mutex);
+       media_entity_graph_walk_start(&graph, entity);
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+               if (entity == &video->video_dev.entity)
+                       continue;
+               if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+                       continue;
+               far_end = to_vpfe_video(media_entity_to_video_device(entity));
+               if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                       pipe->inputs[pipe->input_num++] = far_end;
+               else
+                       pipe->outputs[pipe->output_num++] = far_end;
+       }
+       mutex_unlock(&mdev->graph_mutex);
+}
+
+/* update pipe state selected by user */
+static int vpfe_update_pipe_state(struct vpfe_video_device *video)
+{
+       struct vpfe_pipeline *pipe = &video->pipe;
+       int ret;
+
+       vpfe_prepare_pipeline(video);
+
+       /* Find out if there is any input video
+         if yes, it is single shot.
+       */
+       if (pipe->input_num == 0) {
+               pipe->state = VPFE_PIPELINE_STREAM_CONTINUOUS;
+               ret = vpfe_update_current_ext_subdev(video);
+               if (ret) {
+                       pr_err("Invalid external subdev\n");
+                       return ret;
+               }
+       } else {
+               pipe->state = VPFE_PIPELINE_STREAM_SINGLESHOT;
+       }
+       video->initialized = 1;
+       video->skip_frame_count = 1;
+       video->skip_frame_count_init = 1;
+       return 0;
+}
+
+/* checks wether pipeline is ready for enabling */
+int vpfe_video_is_pipe_ready(struct vpfe_pipeline *pipe)
+{
+       int i;
+
+       for (i = 0; i < pipe->input_num; i++)
+               if (!pipe->inputs[i]->started ||
+                       pipe->inputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED)
+                       return 0;
+       for (i = 0; i < pipe->output_num; i++)
+               if (!pipe->outputs[i]->started ||
+                       pipe->outputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED)
+                       return 0;
+       return 1;
+}
+
+/**
+ * Validate a pipeline by checking both ends of all links for format
+ * discrepancies.
+ *
+ * Return 0 if all formats match, or -EPIPE if at least one link is found with
+ * different formats on its two ends.
+ */
+static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe)
+{
+       struct v4l2_subdev_format fmt_source;
+       struct v4l2_subdev_format fmt_sink;
+       struct v4l2_subdev *subdev;
+       struct media_pad *pad;
+       int ret;
+
+       /*
+        * Should not matter if it is output[0] or 1 as
+        * the general ideas is to traverse backwards and
+        * the fact that the out video node always has the
+        * format of the connected pad.
+        */
+       subdev = vpfe_video_remote_subdev(pipe->outputs[0], NULL);
+       if (subdev == NULL)
+               return -EPIPE;
+
+       while (1) {
+               /* Retrieve the sink format */
+               pad = &subdev->entity.pads[0];
+               if (!(pad->flags & MEDIA_PAD_FL_SINK))
+                       break;
+
+               fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               fmt_sink.pad = pad->index;
+               ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL,
+                                      &fmt_sink);
+
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       return -EPIPE;
+
+               /* Retrieve the source format */
+               pad = media_entity_remote_source(pad);
+               if (pad == NULL ||
+                       pad->entity->type != MEDIA_ENT_T_V4L2_SUBDEV)
+                       break;
+
+               subdev = media_entity_to_v4l2_subdev(pad->entity);
+
+               fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               fmt_source.pad = pad->index;
+               ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       return -EPIPE;
+
+               /* Check if the two ends match */
+               if (fmt_source.format.code != fmt_sink.format.code ||
+                   fmt_source.format.width != fmt_sink.format.width ||
+                   fmt_source.format.height != fmt_sink.format.height)
+                       return -EPIPE;
+       }
+       return 0;
+}
+
+/*
+ * vpfe_pipeline_enable() - Enable streaming on a pipeline
+ * @vpfe_dev: vpfe device
+ * @pipe: vpfe pipeline
+ *
+ * Walk the entities chain starting at the pipeline output video node and start
+ * all modules in the chain in the given mode.
+ *
+ * Return 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
+{
+       struct media_entity_graph graph;
+       struct media_entity *entity;
+       struct v4l2_subdev *subdev;
+       struct media_device *mdev;
+       int ret = 0;
+
+       if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
+               entity = vpfe_get_input_entity(pipe->outputs[0]);
+       else
+               entity = &pipe->inputs[0]->video_dev.entity;
+
+       mdev = entity->parent;
+       mutex_lock(&mdev->graph_mutex);
+       media_entity_graph_walk_start(&graph, entity);
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+
+               if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+                       continue;
+               subdev = media_entity_to_v4l2_subdev(entity);
+               ret = v4l2_subdev_call(subdev, video, s_stream, 1);
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       break;
+       }
+       mutex_unlock(&mdev->graph_mutex);
+       return ret;
+}
+
+/*
+ * vpfe_pipeline_disable() - Disable streaming on a pipeline
+ * @vpfe_dev: vpfe device
+ * @pipe: VPFE pipeline
+ *
+ * Walk the entities chain starting at the pipeline output video node and stop
+ * all modules in the chain.
+ *
+ * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module
+ * can't be stopped.
+ */
+static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
+{
+       struct media_entity_graph graph;
+       struct media_entity *entity;
+       struct v4l2_subdev *subdev;
+       struct media_device *mdev;
+       int ret = 0;
+
+       if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
+               entity = vpfe_get_input_entity(pipe->outputs[0]);
+       else
+               entity = &pipe->inputs[0]->video_dev.entity;
+
+       mdev = entity->parent;
+       mutex_lock(&mdev->graph_mutex);
+       media_entity_graph_walk_start(&graph, entity);
+
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+
+               if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+                       continue;
+               subdev = media_entity_to_v4l2_subdev(entity);
+               ret = v4l2_subdev_call(subdev, video, s_stream, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       break;
+       }
+       mutex_unlock(&mdev->graph_mutex);
+
+       return (ret == 0) ? ret : -ETIMEDOUT ;
+}
+
+/*
+ * vpfe_pipeline_set_stream() - Enable/disable streaming on a pipeline
+ * @vpfe_dev: VPFE device
+ * @pipe: VPFE pipeline
+ * @state: Stream state (stopped or active)
+ *
+ * Set the pipeline to the given stream state.
+ *
+ * Return 0 if successfull, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int vpfe_pipeline_set_stream(struct vpfe_pipeline *pipe,
+                           enum vpfe_pipeline_stream_state state)
+{
+       if (state == VPFE_PIPELINE_STREAM_STOPPED)
+               return vpfe_pipeline_disable(pipe);
+
+       return vpfe_pipeline_enable(pipe);
+}
+
+static int all_videos_stopped(struct vpfe_video_device *video)
+{
+       struct vpfe_pipeline *pipe = &video->pipe;
+       int i;
+
+       for (i = 0; i < pipe->input_num; i++)
+               if (pipe->inputs[i]->started)
+                       return 0;
+       for (i = 0; i < pipe->output_num; i++)
+               if (pipe->outputs[i]->started)
+                       return 0;
+       return 1;
+}
+
+/*
+ * vpfe_open() - open video device
+ * @file: file pointer
+ *
+ * initialize media pipeline state, allocate memory for file handle
+ *
+ * Return 0 if successful, or the return -ENODEV otherwise.
+ */
+static int vpfe_open(struct file *file)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_fh *handle;
+
+       /* Allocate memory for the file handle object */
+       handle = kzalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
+
+       if (handle == NULL)
+               return -ENOMEM;
+
+       v4l2_fh_init(&handle->vfh, &video->video_dev);
+       v4l2_fh_add(&handle->vfh);
+
+       mutex_lock(&video->lock);
+       /* If decoder is not initialized. initialize it */
+       if (!video->initialized && vpfe_update_pipe_state(video)) {
+               mutex_unlock(&video->lock);
+               return -ENODEV;
+       }
+       /* Increment device users counter */
+       video->usrs++;
+       /* Set io_allowed member to false */
+       handle->io_allowed = 0;
+       v4l2_prio_open(&video->prio, &handle->prio);
+       handle->video = video;
+       file->private_data = &handle->vfh;
+       mutex_unlock(&video->lock);
+
+       return 0;
+}
+
+/* get the next buffer available from dma queue */
+static unsigned long
+vpfe_video_get_next_buffer(struct vpfe_video_device *video)
+{
+       video->cur_frm = video->next_frm =
+               list_entry(video->dma_queue.next,
+                          struct vpfe_cap_buffer, list);
+
+       list_del(&video->next_frm->list);
+       video->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+       return vb2_dma_contig_plane_dma_addr(&video->next_frm->vb, 0);
+}
+
+/* schedule the next buffer which is available on dma queue */
+void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video)
+{
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       unsigned long addr;
+
+       if (list_empty(&video->dma_queue))
+               return;
+
+       video->next_frm = list_entry(video->dma_queue.next,
+                                       struct vpfe_cap_buffer, list);
+
+       if (VPFE_PIPELINE_STREAM_SINGLESHOT == video->pipe.state)
+               video->cur_frm = video->next_frm;
+
+       list_del(&video->next_frm->list);
+       video->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+       addr = vb2_dma_contig_plane_dma_addr(&video->next_frm->vb, 0);
+       video->ops->queue(vpfe_dev, addr);
+       video->state = VPFE_VIDEO_BUFFER_QUEUED;
+}
+
+/* schedule the buffer for capturing bottom field */
+void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video)
+{
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       unsigned long addr;
+
+       addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb, 0);
+       addr += video->field_off;
+       video->ops->queue(vpfe_dev, addr);
+}
+
+/* make buffer available for dequeue */
+void vpfe_video_process_buffer_complete(struct vpfe_video_device *video)
+{
+       struct vpfe_pipeline *pipe = &video->pipe;
+
+       do_gettimeofday(&video->cur_frm->vb.v4l2_buf.timestamp);
+       vb2_buffer_done(&video->cur_frm->vb, VB2_BUF_STATE_DONE);
+       if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
+               video->cur_frm = video->next_frm;
+}
+
+/* vpfe_stop_capture() - stop streaming */
+static void vpfe_stop_capture(struct vpfe_video_device *video)
+{
+       struct vpfe_pipeline *pipe = &video->pipe;
+
+       video->started = 0;
+
+       if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return;
+       if (all_videos_stopped(video))
+               vpfe_pipeline_set_stream(pipe,
+                                        VPFE_PIPELINE_STREAM_STOPPED);
+}
+
+/*
+ * vpfe_release() - release video device
+ * @file: file pointer
+ *
+ * deletes buffer queue, frees the buffers and the vpfe file handle
+ *
+ * Return 0
+ */
+static int vpfe_release(struct file *file)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct v4l2_fh *vfh = file->private_data;
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_fh *fh = container_of(vfh, struct vpfe_fh, vfh);
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
+
+       /* Get the device lock */
+       mutex_lock(&video->lock);
+       /* if this instance is doing IO */
+       if (fh->io_allowed) {
+               if (video->started) {
+                       vpfe_stop_capture(video);
+                       /* mark pipe state as stopped in vpfe_release(),
+                          as app might call streamon() after streamoff()
+                          in which case driver has to start streaming.
+                       */
+                       video->pipe.state = VPFE_PIPELINE_STREAM_STOPPED;
+                       vb2_streamoff(&video->buffer_queue,
+                                     video->buffer_queue.type);
+               }
+               video->io_usrs = 0;
+               /* Free buffers allocated */
+               vb2_queue_release(&video->buffer_queue);
+               vb2_dma_contig_cleanup_ctx(video->alloc_ctx);
+       }
+       /* Decrement device users counter */
+       video->usrs--;
+       /* Close the priority */
+       v4l2_prio_close(&video->prio, fh->prio);
+       /* If this is the last file handle */
+       if (!video->usrs)
+               video->initialized = 0;
+       mutex_unlock(&video->lock);
+       file->private_data = NULL;
+       /* Free memory allocated to file handle object */
+       v4l2_fh_del(vfh);
+       kzfree(fh);
+       return 0;
+}
+
+/*
+ * vpfe_mmap() - It is used to map kernel space buffers
+ * into user spaces
+ */
+static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
+       return vb2_mmap(&video->buffer_queue, vma);
+}
+
+/*
+ * vpfe_poll() - It is used for select/poll system call
+ */
+static unsigned int vpfe_poll(struct file *file, poll_table *wait)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
+       if (video->started)
+               return vb2_poll(&video->buffer_queue, file, wait);
+       return 0;
+}
+
+/* vpfe capture driver file operations */
+static const struct v4l2_file_operations vpfe_fops = {
+       .owner = THIS_MODULE,
+       .open = vpfe_open,
+       .release = vpfe_release,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap = vpfe_mmap,
+       .poll = vpfe_poll
+};
+
+/*
+ * vpfe_querycap() - query capabilities of video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @cap: pointer to v4l2_capability structure
+ *
+ * fills v4l2 capabilities structure
+ *
+ * Return 0
+ */
+static int vpfe_querycap(struct file *file, void  *priv,
+                              struct v4l2_capability *cap)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
+
+       if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       else
+               cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+       cap->device_caps = cap->capabilities;
+       cap->version = VPFE_CAPTURE_VERSION_CODE;
+       strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
+       strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
+       strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
+
+       return 0;
+}
+
+/*
+ * vpfe_g_fmt() - get the format which is active on video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_format structure
+ *
+ * fills v4l2 format structure with active format
+ *
+ * Return 0
+ */
+static int vpfe_g_fmt(struct file *file, void *priv,
+                               struct v4l2_format *fmt)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt\n");
+       /* Fill in the information about format */
+       *fmt = video->fmt;
+       return 0;
+}
+
+/*
+ * vpfe_enum_fmt() - enum formats supported on media chain
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_fmtdesc structure
+ *
+ * fills v4l2_fmtdesc structure with output format set on adjacent subdev,
+ * only one format is enumearted as subdevs are already configured
+ *
+ * Return 0 if successfull, error code otherwise
+ */
+static int vpfe_enum_fmt(struct file *file, void  *priv,
+                                  struct v4l2_fmtdesc *fmt)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct v4l2_subdev_format sd_fmt;
+       struct v4l2_mbus_framefmt mbus;
+       struct v4l2_subdev *subdev;
+       struct v4l2_format format;
+       struct media_pad *remote;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt\n");
+
+       /* since already subdev pad format is set,
+       only one pixel format is available */
+       if (fmt->index > 0) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid index\n");
+               return -EINVAL;
+       }
+       /* get the remote pad */
+       remote = media_entity_remote_source(&video->pad);
+       if (remote == NULL) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                        "invalid remote pad for video node\n");
+               return -EINVAL;
+       }
+       /* get the remote subdev */
+       subdev = vpfe_video_remote_subdev(video, NULL);
+       if (subdev == NULL) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                        "invalid remote subdev for video node\n");
+               return -EINVAL;
+       }
+       sd_fmt.pad = remote->index;
+       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       /* get output format of remote subdev */
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt);
+       if (ret) {
+               v4l2_err(&vpfe_dev->v4l2_dev,
+                        "invalid remote subdev for video node\n");
+               return ret;
+       }
+       /* convert to pix format */
+       mbus.code = sd_fmt.format.code;
+       mbus_to_pix(&mbus, &format.fmt.pix);
+       /* copy the result */
+       fmt->pixelformat = format.fmt.pix.pixelformat;
+
+       return 0;
+}
+
+/*
+ * vpfe_s_fmt() - set the format on video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_format structure
+ *
+ * validate and set the format on video device
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_s_fmt(struct file *file, void *priv,
+                               struct v4l2_format *fmt)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct v4l2_format format;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt\n");
+       /* If streaming is started, return error */
+       if (video->started) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
+               return -EBUSY;
+       }
+       /* get adjacent subdev's output pad format */
+       ret = __vpfe_video_get_format(video, &format);
+       if (ret)
+               return ret;
+       *fmt = format;
+       video->fmt = *fmt;
+       return 0;
+}
+
+/*
+ * vpfe_try_fmt() - try the format on video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_format structure
+ *
+ * validate the format, update with correct format
+ * based on output format set on adjacent subdev
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_try_fmt(struct file *file, void *priv,
+                                 struct v4l2_format *fmt)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct v4l2_format format;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt\n");
+       /* get adjacent subdev's output pad format */
+       ret = __vpfe_video_get_format(video, &format);
+       if (ret)
+               return ret;
+
+       *fmt = format;
+       return 0;
+}
+
+/*
+ * vpfe_enum_input() - enum inputs supported on media chain
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_fmtdesc structure
+ *
+ * fills v4l2_input structure with input available on media chain,
+ * only one input is enumearted as media chain is setup by this time
+ *
+ * Return 0 if successfull, -EINVAL is media chain is invalid
+ */
+static int vpfe_enum_input(struct file *file, void *priv,
+                                struct v4l2_input *inp)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_ext_subdev_info *sdinfo = video->current_ext_subdev;
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
+       /* enumerate from the subdev user has choosen through mc */
+       if (inp->index < sdinfo->num_inputs) {
+               memcpy(inp, &sdinfo->inputs[inp->index],
+                      sizeof(struct v4l2_input));
+               return 0;
+       }
+       return -EINVAL;
+}
+
+/*
+ * vpfe_g_input() - get index of the input which is active
+ * @file: file pointer
+ * @priv: void pointer
+ * @index: pointer to unsigned int
+ *
+ * set index with input index which is active
+ */
+static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
+
+       *index = video->current_input;
+       return 0;
+}
+
+/*
+ * vpfe_s_input() - set input which is pointed by input index
+ * @file: file pointer
+ * @priv: void pointer
+ * @index: pointer to unsigned int
+ *
+ * set input on external subdev
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_ext_subdev_info *sdinfo;
+       struct vpfe_route *route;
+       struct v4l2_input *inps;
+       u32 output;
+       u32 input;
+       int ret;
+       int i;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
+
+       ret = mutex_lock_interruptible(&video->lock);
+       if (ret)
+               return ret;
+       /*
+        * If streaming is started return device busy
+        * error
+        */
+       if (video->started) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
+               ret = -EBUSY;
+               goto unlock_out;
+       }
+
+       sdinfo = video->current_ext_subdev;
+       if (!sdinfo->registered) {
+               ret = -EINVAL;
+               goto unlock_out;
+       }
+       if (vpfe_dev->cfg->setup_input &&
+               vpfe_dev->cfg->setup_input(sdinfo->grp_id) < 0) {
+               ret = -EFAULT;
+               v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+                         "couldn't setup input for %s\n",
+                         sdinfo->module_name);
+               goto unlock_out;
+       }
+       route = &sdinfo->routes[index];
+       if (route && sdinfo->can_route) {
+               input = route->input;
+               output = route->output;
+               ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+                                                sdinfo->grp_id, video,
+                                                s_routing, input, output, 0);
+               if (ret) {
+                       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+                               "s_input:error in setting input in decoder\n");
+                       ret = -EINVAL;
+                       goto unlock_out;
+               }
+       }
+       /* set standards set by subdev in video device */
+       for (i = 0; i < sdinfo->num_inputs; i++) {
+               inps = &sdinfo->inputs[i];
+               video->video_dev.tvnorms |= inps->std;
+       }
+       video->current_input = index;
+unlock_out:
+       mutex_unlock(&video->lock);
+       return ret;
+}
+
+/*
+ * vpfe_querystd() - query std which is being input on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @std_id: pointer to v4l2_std_id structure
+ *
+ * call external subdev through v4l2_device_call_until_err to
+ * get the std that is being active.
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_ext_subdev_info *sdinfo;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
+
+       ret = mutex_lock_interruptible(&video->lock);
+       sdinfo = video->current_ext_subdev;
+       if (ret)
+               return ret;
+       /* Call querystd function of decoder device */
+       ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
+                                        video, querystd, std_id);
+       mutex_unlock(&video->lock);
+       return ret;
+}
+
+/*
+ * vpfe_s_std() - set std on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @std_id: pointer to v4l2_std_id structure
+ *
+ * set std pointed by std_id on external subdev by calling it using
+ * v4l2_device_call_until_err
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_ext_subdev_info *sdinfo;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
+
+       /* Call decoder driver function to set the standard */
+       ret = mutex_lock_interruptible(&video->lock);
+       if (ret)
+               return ret;
+       sdinfo = video->current_ext_subdev;
+       /* If streaming is started, return device busy error */
+       if (video->started) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
+               ret = -EBUSY;
+               goto unlock_out;
+       }
+       ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
+                                        core, s_std, *std_id);
+       if (ret < 0) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
+               video->stdid = V4L2_STD_UNKNOWN;
+               goto unlock_out;
+       }
+       video->stdid = *std_id;
+unlock_out:
+       mutex_unlock(&video->lock);
+       return ret;
+}
+
+static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
+       *tvnorm = video->stdid;
+       return 0;
+}
+
+/*
+ * vpfe_enum_dv_timings() - enumerate dv_timings which are supported by
+ *                     to external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @timings: pointer to v4l2_enum_dv_timings structure
+ *
+ * enum dv_timings's which are supported by external subdev through
+ * v4l2_subdev_call
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int
+vpfe_enum_dv_timings(struct file *file, void *fh,
+                 struct v4l2_enum_dv_timings *timings)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_dv_timings\n");
+       return v4l2_subdev_call(subdev, video, enum_dv_timings, timings);
+}
+
+/*
+ * vpfe_query_dv_timings() - query the dv_timings which is being input
+ *                     to external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @timings: pointer to v4l2_dv_timings structure
+ *
+ * get dv_timings which is being input on external subdev through
+ * v4l2_subdev_call
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int
+vpfe_query_dv_timings(struct file *file, void *fh,
+                  struct v4l2_dv_timings *timings)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_query_dv_timings\n");
+       return v4l2_subdev_call(subdev, video, query_dv_timings, timings);
+}
+
+/*
+ * vpfe_s_dv_timings() - set dv_preset on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @timings: pointer to v4l2_dv_timings structure
+ *
+ * set dv_timings pointed by preset on external subdev through
+ * v4l2_device_call_until_err, this configures amplifier also
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int
+vpfe_s_dv_timings(struct file *file, void *fh,
+                 struct v4l2_dv_timings *timings)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_dv_timings\n");
+
+       video->stdid = V4L2_STD_UNKNOWN;
+       return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+                                         video->current_ext_subdev->grp_id,
+                                         video, s_dv_timings, timings);
+}
+
+/*
+ * vpfe_g_dv_timings() - get dv_preset which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @timings: pointer to v4l2_dv_timings structure
+ *
+ * get dv_preset which is set on external subdev through
+ * v4l2_subdev_call
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int
+vpfe_g_dv_timings(struct file *file, void *fh,
+             struct v4l2_dv_timings *timings)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_dv_timings\n");
+       return v4l2_subdev_call(subdev, video, g_dv_timings, timings);
+}
+
+/*
+ *  Videobuf operations
+ */
+/*
+ * vpfe_buffer_queue_setup : Callback function for buffer setup.
+ * @vq: vb2_queue ptr
+ * @fmt: v4l2 format
+ * @nbuffers: ptr to number of buffers requested by application
+ * @nplanes:: contains number of distinct video planes needed to hold a frame
+ * @sizes[]: contains the size (in bytes) of each plane.
+ * @alloc_ctxs: ptr to allocation context
+ *
+ * This callback function is called when reqbuf() is called to adjust
+ * the buffer nbuffers and buffer size
+ */
+static int
+vpfe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                       unsigned int *nbuffers, unsigned int *nplanes,
+                       unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct vpfe_fh *fh = vb2_get_drv_priv(vq);
+       struct vpfe_video_device *video = fh->video;
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_pipeline *pipe = &video->pipe;
+       unsigned long size;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue_setup\n");
+       size = video->fmt.fmt.pix.sizeimage;
+
+       if (vpfe_dev->video_limit) {
+               while (size * *nbuffers > vpfe_dev->video_limit)
+                       (*nbuffers)--;
+       }
+       if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) {
+               if (*nbuffers < MIN_NUM_BUFFERS)
+                       *nbuffers = MIN_NUM_BUFFERS;
+       }
+       *nplanes = 1;
+       sizes[0] = size;
+       alloc_ctxs[0] = video->alloc_ctx;
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+                "nbuffers=%d, size=%lu\n", *nbuffers, size);
+       return 0;
+}
+
+/*
+ * vpfe_buffer_prepare : callback function for buffer prepare
+ * @vb: ptr to vb2_buffer
+ *
+ * This is the callback function for buffer prepare when vb2_qbuf()
+ * function is called. The buffer is prepared and user space virtual address
+ * or user address is converted into  physical address
+ */
+static int vpfe_buffer_prepare(struct vb2_buffer *vb)
+{
+       struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+       struct vpfe_video_device *video = fh->video;
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       unsigned long addr;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
+
+       if (vb->state != VB2_BUF_STATE_ACTIVE &&
+           vb->state != VB2_BUF_STATE_PREPARED)
+               return 0;
+
+       /* Initialize buffer */
+       vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage);
+       if (vb2_plane_vaddr(vb, 0) &&
+               vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
+                       return -EINVAL;
+
+       addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+       /* Make sure user addresses are aligned to 32 bytes */
+       if (!ALIGN(addr, 32))
+               return -EINVAL;
+
+       return 0;
+}
+
+static void vpfe_buffer_queue(struct vb2_buffer *vb)
+{
+       /* Get the file handle object and device object */
+       struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+       struct vpfe_video_device *video = fh->video;
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_pipeline *pipe = &video->pipe;
+       struct vpfe_cap_buffer *buf = container_of(vb,
+                               struct vpfe_cap_buffer, vb);
+       unsigned long flags;
+       unsigned long empty;
+       unsigned long addr;
+
+       spin_lock_irqsave(&video->dma_queue_lock, flags);
+       empty = list_empty(&video->dma_queue);
+       /* add the buffer to the DMA queue */
+       list_add_tail(&buf->list, &video->dma_queue);
+       spin_unlock_irqrestore(&video->dma_queue_lock, flags);
+       /* this case happens in case of single shot */
+       if (empty && video->started && pipe->state ==
+               VPFE_PIPELINE_STREAM_SINGLESHOT &&
+               video->state == VPFE_VIDEO_BUFFER_NOT_QUEUED) {
+               spin_lock(&video->dma_queue_lock);
+               addr = vpfe_video_get_next_buffer(video);
+               video->ops->queue(vpfe_dev, addr);
+
+               video->state = VPFE_VIDEO_BUFFER_QUEUED;
+               spin_unlock(&video->dma_queue_lock);
+
+               /* enable h/w each time in single shot */
+               if (vpfe_video_is_pipe_ready(pipe))
+                       vpfe_pipeline_set_stream(pipe,
+                                       VPFE_PIPELINE_STREAM_SINGLESHOT);
+       }
+}
+
+/* vpfe_start_capture() - start streaming on all the subdevs */
+static int vpfe_start_capture(struct vpfe_video_device *video)
+{
+       struct vpfe_pipeline *pipe = &video->pipe;
+       int ret = 0;
+
+       video->started = 1;
+       if (vpfe_video_is_pipe_ready(pipe))
+               ret = vpfe_pipeline_set_stream(pipe, pipe->state);
+
+       return ret;
+}
+
+static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct vpfe_fh *fh = vb2_get_drv_priv(vq);
+       struct vpfe_video_device *video = fh->video;
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       unsigned long addr;
+       int ret;
+
+       ret = mutex_lock_interruptible(&video->lock);
+       if (ret)
+               goto streamoff;
+
+       /* Get the next frame from the buffer queue */
+       video->cur_frm = video->next_frm =
+               list_entry(video->dma_queue.next, struct vpfe_cap_buffer, list);
+       /* Remove buffer from the buffer queue */
+       list_del(&video->cur_frm->list);
+       /* Mark state of the current frame to active */
+       video->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+       /* Initialize field_id and started member */
+       video->field_id = 0;
+       addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb, 0);
+       video->ops->queue(vpfe_dev, addr);
+       video->state = VPFE_VIDEO_BUFFER_QUEUED;
+
+       ret = vpfe_start_capture(video);
+       if (ret)
+               goto unlock_out;
+
+       mutex_unlock(&video->lock);
+
+       return ret;
+unlock_out:
+       mutex_unlock(&video->lock);
+streamoff:
+       ret = vb2_streamoff(&video->buffer_queue, video->buffer_queue.type);
+       return 0;
+}
+
+static int vpfe_buffer_init(struct vb2_buffer *vb)
+{
+       struct vpfe_cap_buffer *buf = container_of(vb,
+                                                  struct vpfe_cap_buffer, vb);
+
+       INIT_LIST_HEAD(&buf->list);
+       return 0;
+}
+
+/* abort streaming and wait for last buffer */
+static int vpfe_stop_streaming(struct vb2_queue *vq)
+{
+       struct vpfe_fh *fh = vb2_get_drv_priv(vq);
+       struct vpfe_video_device *video = fh->video;
+
+       if (!vb2_is_streaming(vq))
+               return 0;
+       /* release all active buffers */
+       while (!list_empty(&video->dma_queue)) {
+               video->next_frm = list_entry(video->dma_queue.next,
+                                               struct vpfe_cap_buffer, list);
+               list_del(&video->next_frm->list);
+               vb2_buffer_done(&video->next_frm->vb, VB2_BUF_STATE_ERROR);
+       }
+       return 0;
+}
+
+static void vpfe_buf_cleanup(struct vb2_buffer *vb)
+{
+       struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+       struct vpfe_video_device *video = fh->video;
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_cap_buffer *buf = container_of(vb,
+                                       struct vpfe_cap_buffer, vb);
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buf_cleanup\n");
+       if (vb->state == VB2_BUF_STATE_ACTIVE)
+               list_del_init(&buf->list);
+}
+
+static struct vb2_ops video_qops = {
+       .queue_setup            = vpfe_buffer_queue_setup,
+       .buf_init               = vpfe_buffer_init,
+       .buf_prepare            = vpfe_buffer_prepare,
+       .start_streaming        = vpfe_start_streaming,
+       .stop_streaming         = vpfe_stop_streaming,
+       .buf_cleanup            = vpfe_buf_cleanup,
+       .buf_queue              = vpfe_buffer_queue,
+};
+
+/*
+ * vpfe_reqbufs() - supported REQBUF only once opening
+ * the device.
+ */
+static int vpfe_reqbufs(struct file *file, void *priv,
+                       struct v4l2_requestbuffers *req_buf)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_fh *fh = file->private_data;
+       struct vb2_queue *q;
+       int ret;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type &&
+           V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       ret = mutex_lock_interruptible(&video->lock);
+       if (ret)
+               return ret;
+
+       if (video->io_usrs != 0) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
+               ret = -EBUSY;
+               goto unlock_out;
+       }
+       video->memory = req_buf->memory;
+
+       /* Initialize videobuf2 queue as per the buffer type */
+       video->alloc_ctx = vb2_dma_contig_init_ctx(vpfe_dev->pdev);
+       if (IS_ERR(video->alloc_ctx)) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Failed to get the context\n");
+               return PTR_ERR(video->alloc_ctx);
+       }
+
+       q = &video->buffer_queue;
+       q->type = req_buf->type;
+       q->io_modes = VB2_MMAP | VB2_USERPTR;
+       q->drv_priv = fh;
+       q->ops = &video_qops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->buf_struct_size = sizeof(struct vpfe_cap_buffer);
+
+       ret = vb2_queue_init(q);
+       if (ret) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(vpfe_dev->pdev);
+               return ret;
+       }
+
+       fh->io_allowed = 1;
+       video->io_usrs = 1;
+       INIT_LIST_HEAD(&video->dma_queue);
+       ret = vb2_reqbufs(&video->buffer_queue, req_buf);
+
+unlock_out:
+       mutex_unlock(&video->lock);
+       return ret;
+}
+
+/*
+ * vpfe_querybuf() - query buffers for exchange
+ */
+static int vpfe_querybuf(struct file *file, void *priv,
+                        struct v4l2_buffer *buf)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type &&
+           V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+               return  -EINVAL;
+       }
+
+       if (video->memory != V4L2_MEMORY_MMAP) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
+               return -EINVAL;
+       }
+
+       /* Call vb2_querybuf to get information */
+       return vb2_querybuf(&video->buffer_queue, buf);
+}
+
+/*
+ * vpfe_qbuf() - queue buffers for capture or processing
+ */
+static int vpfe_qbuf(struct file *file, void *priv,
+                    struct v4l2_buffer *p)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_fh *fh = file->private_data;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type &&
+           V4L2_BUF_TYPE_VIDEO_OUTPUT != p->type) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+               return -EINVAL;
+       }
+       /*
+        * If this file handle is not allowed to do IO,
+        * return error
+        */
+       if (!fh->io_allowed) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+               return -EACCES;
+       }
+
+       return vb2_qbuf(&video->buffer_queue, p);
+}
+
+/*
+ * vpfe_dqbuf() - deque buffer which is done with processing
+ */
+static int vpfe_dqbuf(struct file *file, void *priv,
+                     struct v4l2_buffer *buf)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type &&
+           V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+               return -EINVAL;
+       }
+
+       return vb2_dqbuf(&video->buffer_queue,
+                        buf, (file->f_flags & O_NONBLOCK));
+}
+
+/*
+ * vpfe_streamon() - get dv_preset which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @buf_type: enum v4l2_buf_type
+ *
+ * queue buffer onto hardware for capture/processing and
+ * start all the subdevs which are in media chain
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_streamon(struct file *file, void *priv,
+                        enum v4l2_buf_type buf_type)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_pipeline *pipe = &video->pipe;
+       struct vpfe_fh *fh = file->private_data;
+       struct vpfe_ext_subdev_info *sdinfo;
+       int ret = -EINVAL;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type &&
+           V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+               return ret;
+       }
+       /* If file handle is not allowed IO, return error */
+       if (!fh->io_allowed) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+               return -EACCES;
+       }
+       sdinfo = video->current_ext_subdev;
+       /* If buffer queue is empty, return error */
+       if (list_empty(&video->buffer_queue.queued_list)) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
+               return -EIO;
+       }
+       /* Validate the pipeline */
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE == buf_type) {
+               ret = vpfe_video_validate_pipeline(pipe);
+               if (ret < 0)
+                       return ret;
+       }
+       /* Call vb2_streamon to start streaming */
+       return vb2_streamon(&video->buffer_queue, buf_type);
+}
+
+/*
+ * vpfe_streamoff() - get dv_preset which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @buf_type: enum v4l2_buf_type
+ *
+ * stop all the subdevs which are in media chain
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_streamoff(struct file *file, void *priv,
+                         enum v4l2_buf_type buf_type)
+{
+       struct vpfe_video_device *video = video_drvdata(file);
+       struct vpfe_device *vpfe_dev = video->vpfe_dev;
+       struct vpfe_fh *fh = file->private_data;
+       int ret = 0;
+
+       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
+
+       if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid buf type\n");
+               return -EINVAL;
+       }
+
+       /* If io is allowed for this file handle, return error */
+       if (!fh->io_allowed) {
+               v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+               return -EACCES;
+       }
+
+       /* If streaming is not started, return error */
+       if (!video->started) {
+               v4l2_err(&vpfe_dev->v4l2_dev, "device is not started\n");
+               return -EINVAL;
+       }
+
+       ret = mutex_lock_interruptible(&video->lock);
+       if (ret)
+               return ret;
+
+       vpfe_stop_capture(video);
+       ret = vb2_streamoff(&video->buffer_queue, buf_type);
+       mutex_unlock(&video->lock);
+
+       return ret;
+}
+
+/* vpfe capture ioctl operations */
+static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
+       .vidioc_querycap         = vpfe_querycap,
+       .vidioc_g_fmt_vid_cap    = vpfe_g_fmt,
+       .vidioc_s_fmt_vid_cap    = vpfe_s_fmt,
+       .vidioc_try_fmt_vid_cap  = vpfe_try_fmt,
+       .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt,
+       .vidioc_g_fmt_vid_out    = vpfe_g_fmt,
+       .vidioc_s_fmt_vid_out    = vpfe_s_fmt,
+       .vidioc_try_fmt_vid_out  = vpfe_try_fmt,
+       .vidioc_enum_fmt_vid_out = vpfe_enum_fmt,
+       .vidioc_enum_input       = vpfe_enum_input,
+       .vidioc_g_input          = vpfe_g_input,
+       .vidioc_s_input          = vpfe_s_input,
+       .vidioc_querystd         = vpfe_querystd,
+       .vidioc_s_std            = vpfe_s_std,
+       .vidioc_g_std            = vpfe_g_std,
+       .vidioc_enum_dv_timings  = vpfe_enum_dv_timings,
+       .vidioc_query_dv_timings = vpfe_query_dv_timings,
+       .vidioc_s_dv_timings     = vpfe_s_dv_timings,
+       .vidioc_g_dv_timings     = vpfe_g_dv_timings,
+       .vidioc_reqbufs          = vpfe_reqbufs,
+       .vidioc_querybuf         = vpfe_querybuf,
+       .vidioc_qbuf             = vpfe_qbuf,
+       .vidioc_dqbuf            = vpfe_dqbuf,
+       .vidioc_streamon         = vpfe_streamon,
+       .vidioc_streamoff        = vpfe_streamoff,
+};
+
+/* VPFE video init function */
+int vpfe_video_init(struct vpfe_video_device *video, const char *name)
+{
+       const char *direction;
+       int ret;
+
+       switch (video->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               direction = "output";
+               video->pad.flags = MEDIA_PAD_FL_SINK;
+               video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               direction = "input";
+               video->pad.flags = MEDIA_PAD_FL_SOURCE;
+               video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       /* Initialize field of video device */
+       video->video_dev.release = video_device_release;
+       video->video_dev.fops = &vpfe_fops;
+       video->video_dev.ioctl_ops = &vpfe_ioctl_ops;
+       video->video_dev.minor = -1;
+       video->video_dev.tvnorms = 0;
+       snprintf(video->video_dev.name, sizeof(video->video_dev.name),
+                "DAVINCI VIDEO %s %s", name, direction);
+
+       /* Initialize prio member of device object */
+       v4l2_prio_init(&video->prio);
+       spin_lock_init(&video->irqlock);
+       spin_lock_init(&video->dma_queue_lock);
+       mutex_init(&video->lock);
+       ret = media_entity_init(&video->video_dev.entity,
+                               1, &video->pad, 0);
+       if (ret < 0)
+               return ret;
+
+       video_set_drvdata(&video->video_dev, video);
+
+       return 0;
+}
+
+/* vpfe video device register function */
+int vpfe_video_register(struct vpfe_video_device *video,
+                       struct v4l2_device *vdev)
+{
+       int ret;
+
+       video->video_dev.v4l2_dev = vdev;
+
+       ret = video_register_device(&video->video_dev, VFL_TYPE_GRABBER, -1);
+       if (ret < 0)
+               pr_err("%s: could not register video device (%d)\n",
+                      __func__, ret);
+       return ret;
+}
+
+/* vpfe video device unregister function */
+void vpfe_video_unregister(struct vpfe_video_device *video)
+{
+       if (video_is_registered(&video->video_dev)) {
+               media_entity_cleanup(&video->video_dev.entity);
+               video_unregister_device(&video->video_dev);
+       }
+}
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.h b/drivers/staging/media/davinci_vpfe/vpfe_video.h
new file mode 100644 (file)
index 0000000..bf8af01
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * 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 version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli@ti.com>
+ *      Prabhakar Lad <prabhakar.lad@ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_VIDEO_H
+#define _DAVINCI_VPFE_VIDEO_H
+
+#include <media/videobuf2-dma-contig.h>
+
+struct vpfe_device;
+
+/*
+ * struct vpfe_video_operations - VPFE video operations
+ * @queue:     Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
+ *             if there was no buffer previously queued.
+ */
+struct vpfe_video_operations {
+       int(*queue) (struct vpfe_device *vpfe_dev, unsigned long addr);
+};
+
+enum vpfe_pipeline_stream_state {
+       VPFE_PIPELINE_STREAM_STOPPED = 0,
+       VPFE_PIPELINE_STREAM_CONTINUOUS = 1,
+       VPFE_PIPELINE_STREAM_SINGLESHOT = 2,
+};
+
+enum vpfe_video_state {
+       /* indicates that buffer is not queued */
+       VPFE_VIDEO_BUFFER_NOT_QUEUED = 0,
+       /* indicates that buffer is queued */
+       VPFE_VIDEO_BUFFER_QUEUED = 1,
+};
+
+struct vpfe_pipeline {
+       /* media pipeline */
+       struct media_pipeline           *pipe;
+       /* state of the pipeline, continuous,
+        * single-shot or stopped
+        */
+       enum vpfe_pipeline_stream_state state;
+       /* number of active input video entities */
+       unsigned int                    input_num;
+       /* number of active output video entities */
+       unsigned int                    output_num;
+       /* input video nodes in case of single-shot mode */
+       struct vpfe_video_device        *inputs[10];
+       /* capturing video nodes */
+       struct vpfe_video_device        *outputs[10];
+};
+
+#define to_vpfe_pipeline(__e) \
+       container_of((__e)->pipe, struct vpfe_pipeline, pipe)
+
+#define to_vpfe_video(vdev) \
+       container_of(vdev, struct vpfe_video_device, video_dev)
+
+struct vpfe_cap_buffer {
+       struct vb2_buffer vb;
+       struct list_head list;
+};
+
+struct vpfe_video_device {
+       /* vpfe device */
+       struct vpfe_device                      *vpfe_dev;
+       /* video dev */
+       struct video_device                     video_dev;
+       /* media pad of video entity */
+       struct media_pad                        pad;
+       /* video operations supported by video device */
+       const struct vpfe_video_operations      *ops;
+       /* type of the video buffers used by user */
+       enum v4l2_buf_type                      type;
+       /* Indicates id of the field which is being captured */
+       u32                                     field_id;
+       /* pipeline for which video device is part of */
+       struct vpfe_pipeline                    pipe;
+       /* Indicates whether streaming started */
+       u8                                      started;
+       /* Indicates state of the stream */
+       unsigned int                            state;
+       /* current input at the sub device */
+       int                                     current_input;
+       /*
+        * This field keeps track of type of buffer exchange mechanism
+        * user has selected
+        */
+       enum v4l2_memory                        memory;
+       /* Used to keep track of state of the priority */
+       struct v4l2_prio_state                  prio;
+       /* number of open instances of the channel */
+       u32                                     usrs;
+       /* flag to indicate whether decoder is initialized */
+       u8                                      initialized;
+       /* skip frame count */
+       u8                                      skip_frame_count;
+       /* skip frame count init value */
+       u8                                      skip_frame_count_init;
+       /* time per frame for skipping */
+       struct v4l2_fract                       timeperframe;
+       /* ptr to currently selected sub device */
+       struct vpfe_ext_subdev_info             *current_ext_subdev;
+       /* Pointer pointing to current vpfe_cap_buffer */
+       struct vpfe_cap_buffer                  *cur_frm;
+       /* Pointer pointing to next vpfe_cap_buffer */
+       struct vpfe_cap_buffer                  *next_frm;
+       /* Used to store pixel format */
+       struct v4l2_format                      fmt;
+       struct vb2_queue                        buffer_queue;
+       /* allocator-specific contexts for each plane */
+       struct vb2_alloc_ctx *alloc_ctx;
+       /* Queue of filled frames */
+       struct list_head                        dma_queue;
+       spinlock_t                              irqlock;
+       /* IRQ lock for DMA queue */
+       spinlock_t                              dma_queue_lock;
+       /* lock used to access this structure */
+       struct mutex                            lock;
+       /* number of users performing IO */
+       u32                                     io_usrs;
+       /* Currently selected or default standard */
+       v4l2_std_id                             stdid;
+       /*
+        * offset where second field starts from the starting of the
+        * buffer for field seperated YCbCr formats
+        */
+       u32                                     field_off;
+};
+
+int vpfe_video_is_pipe_ready(struct vpfe_pipeline *pipe);
+void vpfe_video_unregister(struct vpfe_video_device *video);
+int vpfe_video_register(struct vpfe_video_device *video,
+                       struct v4l2_device *vdev);
+int vpfe_video_init(struct vpfe_video_device *video, const char *name);
+void vpfe_video_process_buffer_complete(struct vpfe_video_device *video);
+void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video);
+void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video);
+
+#endif         /* _DAVINCI_VPFE_VIDEO_H */
index 479c643da2f61c9382709161f9064747239df569..e33b7f55d84e2a9aa8232c28463e622b0785c53c 100644 (file)
@@ -785,7 +785,7 @@ dt3155_init_board(struct pci_dev *pdev)
        }
        write_i2c_reg(pd->regs, CONFIG, pd->config); /*  ACQ_MODE_EVEN  */
 
-       /* select chanel 1 for input and set sync level */
+       /* select channel 1 for input and set sync level */
        write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
        write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
 
index ece2dd146487b5051bb22e82560b2b871750fe8d..c9dfc75d1d2c3368193893f6928c5ea3097ad7d3 100644 (file)
@@ -201,7 +201,8 @@ static int init_i2c_module(struct i2c_adapter *adapter, const char *type,
        if (v4l2_i2c_new_subdev(v4l2_dev, adapter, type, addr, NULL))
                return 0;
 
-       printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", type);
+       dev_info(&adapter->dev,
+                "go7007: probing for module i2c:%s failed\n", type);
        return -1;
 }
 
@@ -217,7 +218,7 @@ int go7007_register_encoder(struct go7007 *go)
 {
        int i, ret;
 
-       printk(KERN_INFO "go7007: registering new %s\n", go->name);
+       dev_info(go->dev, "go7007: registering new %s\n", go->name);
 
        mutex_lock(&go->hw_lock);
        ret = go7007_init_encoder(go);
index 6bc82aaeef110e3135850daed2c6aca4b4f8302f..39456a36b2c6d67b732185c59ea152ffe79dfaa4 100644 (file)
@@ -60,10 +60,10 @@ static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
 
 #ifdef GO7007_I2C_DEBUG
        if (read)
-               printk(KERN_DEBUG "go7007-i2c: reading 0x%02x on 0x%02x\n",
+               dev_dbg(go->dev, "go7007-i2c: reading 0x%02x on 0x%02x\n",
                        command, addr);
        else
-               printk(KERN_DEBUG
+               dev_dbg(go->dev,
                        "go7007-i2c: writing 0x%02x to 0x%02x on 0x%02x\n",
                        *data, command, addr);
 #endif
@@ -85,7 +85,7 @@ static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
                msleep(100);
        }
        if (i == 10) {
-               printk(KERN_ERR "go7007-i2c: I2C adapter is hung\n");
+               dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n");
                goto i2c_done;
        }
 
@@ -119,7 +119,7 @@ static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
                msleep(100);
        }
        if (i == 10) {
-               printk(KERN_ERR "go7007-i2c: I2C adapter is hung\n");
+               dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n");
                goto i2c_done;
        }
 
@@ -216,7 +216,7 @@ int go7007_i2c_init(struct go7007 *go)
        go->i2c_adapter.dev.parent = go->dev;
        i2c_set_adapdata(&go->i2c_adapter, go);
        if (i2c_add_adapter(&go->i2c_adapter) < 0) {
-               printk(KERN_ERR
+               dev_err(go->dev,
                        "go7007-i2c: error: i2c_add_adapter failed\n");
                return -1;
        }
index a78133b67de2049f80190d3a2672c6fadbcaa68a..0d3713dceba5a165f69641314c877d7d3a9b86a8 100644 (file)
@@ -1811,8 +1811,8 @@ int go7007_v4l2_init(struct go7007 *go)
        }
        video_set_drvdata(go->video_dev, go);
        ++go->ref_count;
-       printk(KERN_INFO "%s: registered device %s [v4l2]\n",
-              go->video_dev->name, video_device_node_name(go->video_dev));
+       dev_info(go->dev, "registered device %s [v4l2]\n",
+                video_device_node_name(go->video_dev));
 
        return 0;
 }
index b3974100c6cdccd0899da64fa8d5a2d9915365aa..d60e065963753f7b5af1acd04ae9cd3e19bd87d4 100644 (file)
@@ -103,8 +103,7 @@ static u16 vid_regs_fp[] = {
 };
 
 /* PAL specific values */
-static u16 vid_regs_fp_pal[] =
-{
+static u16 vid_regs_fp_pal[] = {
        0x120, 0x017,
        0x121, 0xd22,
        0x122, 0x122,
@@ -174,7 +173,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value)
 
        usb = go->hpi_context;
        if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
-               printk(KERN_INFO "i2c lock failed\n");
+               dev_info(&client->dev, "i2c lock failed\n");
                kfree(buf);
                return -EINTR;
        }
@@ -213,7 +212,7 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
 
        usb = go->hpi_context;
        if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
-               printk(KERN_INFO "i2c lock failed\n");
+               dev_info(&client->dev, "i2c lock failed\n");
                kfree(buf);
                return -EINTR;
        }
@@ -231,13 +230,13 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
                val_read = (buf[2] << 8) + buf[3];
                kfree(buf);
                if (val_read != val) {
-                       printk(KERN_INFO "invalid fp write %x %x\n",
-                              val_read, val);
+                       dev_info(&client->dev, "invalid fp write %x %x\n",
+                                val_read, val);
                        return -EFAULT;
                }
                if (subaddr != addr) {
-                       printk(KERN_INFO "invalid fp write addr %x %x\n",
-                              subaddr, addr);
+                       dev_info(&client->dev, "invalid fp write addr %x %x\n",
+                                subaddr, addr);
                        return -EFAULT;
                }
        } else {
@@ -275,7 +274,7 @@ static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
        memset(buf, 0xcd, 6);
        usb = go->hpi_context;
        if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
-               printk(KERN_INFO "i2c lock failed\n");
+               dev_info(&client->dev, "i2c lock failed\n");
                kfree(buf);
                return -EINTR;
        }
@@ -299,7 +298,7 @@ static int write_regs(struct i2c_client *client, u8 *regs)
 
        for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
                if (write_reg(client, regs[i], regs[i+1]) < 0) {
-                       printk(KERN_INFO "s2250: failed\n");
+                       dev_info(&client->dev, "failed\n");
                        return -1;
                }
        }
@@ -312,7 +311,7 @@ static int write_regs_fp(struct i2c_client *client, u16 *regs)
 
        for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
                if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
-                       printk(KERN_INFO "s2250: failed fp\n");
+                       dev_info(&client->dev, "failed fp\n");
                        return -1;
                }
        }
@@ -606,23 +605,20 @@ static int s2250_probe(struct i2c_client *client,
 
        /* initialize the audio */
        if (write_regs(audio, aud_regs) < 0) {
-               printk(KERN_ERR
-                      "s2250: error initializing audio\n");
+               dev_err(&client->dev, "error initializing audio\n");
                i2c_unregister_device(audio);
                kfree(state);
                return 0;
        }
 
        if (write_regs(client, vid_regs) < 0) {
-               printk(KERN_ERR
-                      "s2250: error initializing decoder\n");
+               dev_err(&client->dev, "error initializing decoder\n");
                i2c_unregister_device(audio);
                kfree(state);
                return 0;
        }
        if (write_regs_fp(client, vid_regs_fp) < 0) {
-               printk(KERN_ERR
-                      "s2250: error initializing decoder\n");
+               dev_err(&client->dev, "error initializing decoder\n");
                i2c_unregister_device(audio);
                kfree(state);
                return 0;
index f1bd159ac19548ec6af9c652ab504936856c80e3..f57eb3beb3416f4d396164cd2b15a66f4323c964 100644 (file)
@@ -55,16 +55,16 @@ static int s2250loader_probe(struct usb_interface *interface,
 
        usbdev = usb_get_dev(interface_to_usbdev(interface));
        if (!usbdev) {
-               printk(KERN_ERR "Enter s2250loader_probe failed\n");
+               dev_err(&interface->dev, "Enter s2250loader_probe failed\n");
                return -1;
        }
-       printk(KERN_INFO "Enter s2250loader_probe 2.6 kernel\n");
-       printk(KERN_INFO "vendor id 0x%x, device id 0x%x devnum:%d\n",
-          usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-          usbdev->devnum);
+       dev_info(&interface->dev, "Enter s2250loader_probe 2.6 kernel\n");
+       dev_info(&interface->dev, "vendor id 0x%x, device id 0x%x devnum:%d\n",
+                usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
+                usbdev->devnum);
 
        if (usbdev->descriptor.bNumConfigurations != 1) {
-               printk(KERN_ERR "can't handle multiple config\n");
+               dev_err(&interface->dev, "can't handle multiple config\n");
                return -1;
        }
        mutex_lock(&s2250_dev_table_mutex);
@@ -75,31 +75,32 @@ static int s2250loader_probe(struct usb_interface *interface,
        }
 
        if (minor < 0 || minor >= MAX_DEVICES) {
-               printk(KERN_ERR "Invalid minor: %d\n", minor);
+               dev_err(&interface->dev, "Invalid minor: %d\n", minor);
                goto failed;
        }
 
        /* Allocate dev data structure */
        s = kmalloc(sizeof(device_extension_t), GFP_KERNEL);
        if (s == NULL) {
-               printk(KERN_ERR "Out of memory\n");
+               dev_err(&interface->dev, "Out of memory\n");
                goto failed;
        }
        s2250_dev_table[minor] = s;
 
-       printk(KERN_INFO "s2250loader_probe: Device %d on Bus %d Minor %d\n",
-               usbdev->devnum, usbdev->bus->busnum, minor);
+       dev_info(&interface->dev,
+                "s2250loader_probe: Device %d on Bus %d Minor %d\n",
+                usbdev->devnum, usbdev->bus->busnum, minor);
 
        memset(s, 0, sizeof(device_extension_t));
        s->usbdev = usbdev;
-       printk(KERN_INFO "loading 2250 loader\n");
+       dev_info(&interface->dev, "loading 2250 loader\n");
 
        kref_init(&(s->kref));
 
        mutex_unlock(&s2250_dev_table_mutex);
 
        if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) {
-               printk(KERN_ERR
+               dev_err(&interface->dev,
                        "s2250: unable to load firmware from file \"%s\"\n",
                        S2250_LOADER_FIRMWARE);
                goto failed2;
@@ -107,12 +108,12 @@ static int s2250loader_probe(struct usb_interface *interface,
        ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
        release_firmware(fw);
        if (0 != ret) {
-               printk(KERN_ERR "loader download failed\n");
+               dev_err(&interface->dev, "loader download failed\n");
                goto failed2;
        }
 
        if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) {
-               printk(KERN_ERR
+               dev_err(&interface->dev,
                        "s2250: unable to load firmware from file \"%s\"\n",
                        S2250_FIRMWARE);
                goto failed2;
@@ -120,7 +121,7 @@ static int s2250loader_probe(struct usb_interface *interface,
        ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
        release_firmware(fw);
        if (0 != ret) {
-               printk(KERN_ERR "firmware_s2250 download failed\n");
+               dev_err(&interface->dev, "firmware_s2250 download failed\n");
                goto failed2;
        }
 
@@ -133,14 +134,14 @@ failed2:
        if (s)
                kref_put(&(s->kref), s2250loader_delete);
 
-       printk(KERN_ERR "probe failed\n");
+       dev_err(&interface->dev, "probe failed\n");
        return -1;
 }
 
 static void s2250loader_disconnect(struct usb_interface *interface)
 {
        pdevice_extension_t s;
-       printk(KERN_INFO "s2250: disconnect\n");
+       dev_info(&interface->dev, "s2250: disconnect\n");
        s = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
        kref_put(&(s->kref), s2250loader_delete);
index 1291ab79d2af1189f5e5f319fab87097de6ac96c..5d7ff8c81d6dd89557378ccae8dd32803bddf798 100644 (file)
@@ -95,8 +95,8 @@ static int set_freq(struct i2c_client *client, int freq)
                band_name = "UHF";
                band_select = tun->UHF;
        }
-       printk(KERN_DEBUG "wis-sony-tuner: tuning to frequency %d.%04d (%s)\n",
-                       freq / 16, (freq % 16) * 625, band_name);
+       dev_dbg(&client->dev, "tuning to frequency %d.%04d (%s)\n",
+               freq / 16, (freq % 16) * 625, band_name);
        n = freq + tun->IFPCoff;
 
        buffer[0] = n >> 8;
@@ -288,16 +288,16 @@ static int mpx_setup(struct i2c_client *client)
                u8 buf1[3], buf2[2];
                struct i2c_msg msgs[2];
 
-               printk(KERN_DEBUG "wis-sony-tuner: MPX registers: %04x %04x "
-                               "%04x %04x %04x %04x %04x %04x\n",
-                               mpx_audio_modes[t->mpxmode].modus,
-                               source,
-                               mpx_audio_modes[t->mpxmode].acb,
-                               mpx_audio_modes[t->mpxmode].fm_prescale,
-                               mpx_audio_modes[t->mpxmode].nicam_prescale,
-                               mpx_audio_modes[t->mpxmode].scart_prescale,
-                               mpx_audio_modes[t->mpxmode].system,
-                               mpx_audio_modes[t->mpxmode].volume);
+               dev_dbg(&client->dev,
+                       "MPX registers: %04x %04x %04x %04x %04x %04x %04x %04x\n",
+                       mpx_audio_modes[t->mpxmode].modus,
+                       source,
+                       mpx_audio_modes[t->mpxmode].acb,
+                       mpx_audio_modes[t->mpxmode].fm_prescale,
+                       mpx_audio_modes[t->mpxmode].nicam_prescale,
+                       mpx_audio_modes[t->mpxmode].scart_prescale,
+                       mpx_audio_modes[t->mpxmode].system,
+                       mpx_audio_modes[t->mpxmode].volume);
                buf1[0] = 0x11;
                buf1[1] = 0x00;
                buf1[2] = 0x7e;
@@ -310,14 +310,14 @@ static int mpx_setup(struct i2c_client *client)
                msgs[1].len = 2;
                msgs[1].buf = buf2;
                i2c_transfer(client->adapter, msgs, 2);
-               printk(KERN_DEBUG "wis-sony-tuner: MPX system: %02x%02x\n",
-                               buf2[0], buf2[1]);
+               dev_dbg(&client->dev, "MPX system: %02x%02x\n",
+                       buf2[0], buf2[1]);
                buf1[0] = 0x11;
                buf1[1] = 0x02;
                buf1[2] = 0x00;
                i2c_transfer(client->adapter, msgs, 2);
-               printk(KERN_DEBUG "wis-sony-tuner: MPX status: %02x%02x\n",
-                               buf2[0], buf2[1]);
+               dev_dbg(&client->dev, "MPX status: %02x%02x\n",
+                       buf2[0], buf2[1]);
        }
 #endif
        return 0;
@@ -375,8 +375,7 @@ static int set_if(struct i2c_client *client)
                t->mpxmode = force_mpx_mode;
        else
                t->mpxmode = default_mpx_mode;
-       printk(KERN_DEBUG "wis-sony-tuner: setting MPX to mode %d\n",
-                       t->mpxmode);
+       dev_dbg(&client->dev, "setting MPX to mode %d\n", t->mpxmode);
        mpx_setup(client);
 
        return 0;
@@ -401,8 +400,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
                if (t->type >= 0) {
                        if (t->type != *type)
-                               printk(KERN_ERR "wis-sony-tuner: type already "
-                                       "set to %d, ignoring request for %d\n",
+                               dev_err(&client->dev,
+                                       "type already set to %d, ignoring request for %d\n",
                                        t->type, *type);
                        break;
                }
@@ -414,28 +413,28 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        case 'B':
                        case 'g':
                        case 'G':
-                               printk(KERN_INFO "wis-sony-tuner: forcing "
-                                               "tuner to PAL-B/G bands\n");
+                               dev_info(&client->dev,
+                                        "forcing tuner to PAL-B/G bands\n");
                                force_band = V4L2_STD_PAL_BG;
                                break;
                        case 'i':
                        case 'I':
-                               printk(KERN_INFO "wis-sony-tuner: forcing "
-                                               "tuner to PAL-I band\n");
+                               dev_info(&client->dev,
+                                        "forcing tuner to PAL-I band\n");
                                force_band = V4L2_STD_PAL_I;
                                break;
                        case 'd':
                        case 'D':
                        case 'k':
                        case 'K':
-                               printk(KERN_INFO "wis-sony-tuner: forcing "
-                                               "tuner to PAL-D/K bands\n");
+                               dev_info(&client->dev,
+                                        "forcing tuner to PAL-D/K bands\n");
                                force_band = V4L2_STD_PAL_I;
                                break;
                        case 'l':
                        case 'L':
-                               printk(KERN_INFO "wis-sony-tuner: forcing "
-                                               "tuner to SECAM-L band\n");
+                               dev_info(&client->dev,
+                                        "forcing tuner to SECAM-L band\n");
                                force_band = V4L2_STD_SECAM_L;
                                break;
                        default:
@@ -455,14 +454,15 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        t->std = V4L2_STD_NTSC_M;
                        break;
                default:
-                       printk(KERN_ERR "wis-sony-tuner: tuner type %d is not "
-                                       "supported by this module\n", *type);
+                       dev_err(&client->dev,
+                               "tuner type %d is not supported by this module\n",
+                               *type);
                        break;
                }
                if (type >= 0)
-                       printk(KERN_INFO
-                               "wis-sony-tuner: type set to %d (%s)\n",
-                               t->type, sony_tuners[t->type - 200].name);
+                       dev_info(&clinet->dev,
+                                "type set to %d (%s)\n",
+                                t->type, sony_tuners[t->type - 200].name);
                break;
        }
 #endif
@@ -544,9 +544,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        if (force_band && (*std & force_band) != *std &&
                                        *std != V4L2_STD_PAL &&
                                        *std != V4L2_STD_SECAM) {
-                               printk(KERN_DEBUG "wis-sony-tuner: ignoring "
-                                               "requested TV standard in "
-                                               "favor of force_band value\n");
+                               dev_dbg(&client->dev,
+                                       "ignoring requested TV standard in favor of force_band value\n");
                                t->std = force_band;
                        } else if (*std & V4L2_STD_PAL_BG) { /* default */
                                t->std = V4L2_STD_PAL_BG;
@@ -557,8 +556,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        } else if (*std & V4L2_STD_SECAM_L) {
                                t->std = V4L2_STD_SECAM_L;
                        } else {
-                               printk(KERN_ERR "wis-sony-tuner: TV standard "
-                                               "not supported\n");
+                               dev_err(&client->dev,
+                                       "TV standard not supported\n");
                                *std = 0; /* hack to indicate EINVAL */
                                break;
                        }
@@ -567,15 +566,15 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        break;
                case TUNER_SONY_BTF_PK467Z:
                        if (!(*std & V4L2_STD_NTSC_M_JP)) {
-                               printk(KERN_ERR "wis-sony-tuner: TV standard "
-                                               "not supported\n");
+                               dev_err(&client->dev,
+                                       "TV standard not supported\n");
                                *std = 0; /* hack to indicate EINVAL */
                        }
                        break;
                case TUNER_SONY_BTF_PB463Z:
                        if (!(*std & V4L2_STD_NTSC_M)) {
-                               printk(KERN_ERR "wis-sony-tuner: TV standard "
-                                               "not supported\n");
+                               dev_err(&client->dev,
+                                       "TV standard not supported\n");
                                *std = 0; /* hack to indicate EINVAL */
                        }
                        break;
@@ -673,8 +672,7 @@ static int wis_sony_tuner_probe(struct i2c_client *client,
        t->audmode = V4L2_TUNER_MODE_STEREO;
        i2c_set_clientdata(client, t);
 
-       printk(KERN_DEBUG
-               "wis-sony-tuner: initializing tuner at address %d on %s\n",
+       dev_dbg(&client->dev, "initializing tuner at address %d on %s\n",
                client->addr, adapter->name);
 
        return 0;
index d6410ee01be86fbaee8dbb9428d1313d9ed917b2..290fd8c7bfeff7923b2e4d5275b60b5f4a5f62bd 100644 (file)
@@ -128,30 +128,32 @@ static int wis_tw2804_command(struct i2c_client *client,
                int *input = arg;
 
                if (*input < 0 || *input > 3) {
-                       printk(KERN_ERR "wis-tw2804: channel %d is not "
-                                       "between 0 and 3!\n", *input);
+                       dev_err(&client->dev,
+                               "channel %d is not between 0 and 3!\n", *input);
                        return 0;
                }
                dec->channel = *input;
-               printk(KERN_DEBUG "wis-tw2804: initializing TW2804 "
-                               "channel %d\n", dec->channel);
+               dev_dbg(&client->dev, "initializing TW2804 channel %d\n",
+                       dec->channel);
                if (dec->channel == 0 &&
                                write_regs(client, global_registers, 0) < 0) {
-                       printk(KERN_ERR "wis-tw2804: error initializing "
-                                       "TW2804 global registers\n");
+                       dev_err(&client->dev,
+                               "error initializing TW2804 global registers\n");
                        return 0;
                }
                if (write_regs(client, channel_registers, dec->channel) < 0) {
-                       printk(KERN_ERR "wis-tw2804: error initializing "
-                                       "TW2804 channel %d\n", dec->channel);
+                       dev_err(&client->dev,
+                               "error initializing TW2804 channel %d\n",
+                               dec->channel);
                        return 0;
                }
                return 0;
        }
 
        if (dec->channel < 0) {
-               printk(KERN_DEBUG "wis-tw2804: ignoring command %08x until "
-                               "channel number is set\n", cmd);
+               dev_dbg(&client->dev,
+                       "ignoring command %08x until channel number is set\n",
+                       cmd);
                return 0;
        }
 
@@ -311,7 +313,7 @@ static int wis_tw2804_probe(struct i2c_client *client,
        dec->hue = 128;
        i2c_set_clientdata(client, dec);
 
-       printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n",
+       dev_dbg(&client->dev, "creating TW2804 at address %d on %s\n",
                client->addr, adapter->name);
 
        return 0;
index 94071def3bb47dd93bbeef5a0e8f8fe3e7a183df..684ca37f0382640894f1e3dbf49f86018e923557 100644 (file)
@@ -31,8 +31,7 @@ struct wis_tw9903 {
        int hue;
 };
 
-static u8 initial_registers[] =
-{
+static u8 initial_registers[] = {
        0x02, 0x44, /* input 1, composite */
        0x03, 0x92, /* correct digital format */
        0x04, 0x00,
@@ -128,8 +127,8 @@ static int wis_tw9903_command(struct i2c_client *client,
                        0x06, 0xc0, /* reset device */
                        0,      0,
                };
-               printk(KERN_DEBUG "vscale is %04x, hscale is %04x\n",
-                               vscale, hscale);
+               dev_dbg(&client->dev, "vscale is %04x, hscale is %04x\n",
+                       vscale, hscale);
                /*write_regs(client, regs);*/
                break;
        }
@@ -288,12 +287,11 @@ static int wis_tw9903_probe(struct i2c_client *client,
        dec->hue = 0;
        i2c_set_clientdata(client, dec);
 
-       printk(KERN_DEBUG
-               "wis-tw9903: initializing TW9903 at address %d on %s\n",
+       dev_dbg(&client->dev, "initializing TW9903 at address %d on %s\n",
                client->addr, adapter->name);
 
        if (write_regs(client, initial_registers) < 0) {
-               printk(KERN_ERR "wis-tw9903: error initializing TW9903\n");
+               dev_err(&client->dev, "error initializing TW9903\n");
                kfree(dec);
                return -ENODEV;
        }
index 05ac798f35f7d3aca908bc8d8989c0bd0756a845..582ea120a53122bce8dfcdafe7c95309aa2d6a71 100644 (file)
@@ -47,8 +47,8 @@ static int wis_uda1342_command(struct i2c_client *client,
                        write_reg(client, 0x00, 0x1241); /* select input 1 */
                        break;
                default:
-                       printk(KERN_ERR "wis-uda1342: input %d not supported\n",
-                                       *inp);
+                       dev_err(&client->dev, "input %d not supported\n",
+                               *inp);
                        break;
                }
                break;
@@ -67,8 +67,7 @@ static int wis_uda1342_probe(struct i2c_client *client,
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
 
-       printk(KERN_DEBUG
-               "wis-uda1342: initializing UDA1342 at address %d on %s\n",
+       dev_dbg(&client->dev, "initializing UDA1342 at address %d on %s\n",
                client->addr, adapter->name);
 
        write_reg(client, 0x00, 0x8000); /* reset registers */
index 951007a3fc96aa30e74632dc425d99f358dc4781..fa31ee7dd6a9e5f742dafb117426cd801d9318e2 100644 (file)
@@ -18,6 +18,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/threads.h>
@@ -72,20 +74,19 @@ static struct pci_dev *do_pci_probe(void)
        my_dev = pci_get_device(PCI_VENDOR_ID_ATI,
                                PCI_DEVICE_ID_ATI_264VT, NULL);
        if (my_dev) {
-               printk(KERN_ERR DRIVER_NAME ": Using device: %s\n",
-                      pci_name(my_dev));
+               pr_err("Using device: %s\n", pci_name(my_dev));
                pci_addr_phys = 0;
                if (my_dev->resource[0].flags & IORESOURCE_MEM) {
                        pci_addr_phys = my_dev->resource[0].start;
-                       printk(KERN_INFO DRIVER_NAME ": memory at 0x%08X\n",
+                       pr_info("memory at 0x%08X\n",
                               (unsigned int)pci_addr_phys);
                }
                if (pci_addr_phys == 0) {
-                       printk(KERN_ERR DRIVER_NAME ": no memory resource ?\n");
+                       pr_err("no memory resource ?\n");
                        return NULL;
                }
        } else {
-               printk(KERN_ERR DRIVER_NAME ": pci_probe failed\n");
+               pr_err("pci_probe failed\n");
                return NULL;
        }
        return my_dev;
@@ -140,7 +141,7 @@ int init_module(void)
 
        atir_minor = lirc_register_driver(&atir_driver);
        if (atir_minor < 0) {
-               printk(KERN_ERR DRIVER_NAME ": failed to register driver!\n");
+               pr_err("failed to register driver!\n");
                return atir_minor;
        }
        dprintk("driver is registered on minor %d\n", atir_minor);
@@ -159,7 +160,7 @@ static int atir_init_start(void)
 {
        pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400);
        if (pci_addr_lin == 0) {
-               printk(KERN_INFO DRIVER_NAME ": pci mem must be mapped\n");
+               pr_info("pci mem must be mapped\n");
                return 0;
        }
        return 1;
index 939a801c23e447a10c0e1ef7739e67320875549d..2faa391006db68165def2bc6badb0be69743d380 100644 (file)
@@ -223,8 +223,8 @@ static int unregister_from_lirc(struct igorplug *ir)
        int devnum;
 
        if (!ir) {
-               printk(KERN_ERR "%s: called with NULL device struct!\n",
-                      __func__);
+               dev_err(&ir->usbdev->dev,
+                       "%s: called with NULL device struct!\n", __func__);
                return -EINVAL;
        }
 
@@ -232,8 +232,8 @@ static int unregister_from_lirc(struct igorplug *ir)
        d = ir->d;
 
        if (!d) {
-               printk(KERN_ERR "%s: called with NULL lirc driver struct!\n",
-                      __func__);
+               dev_err(&ir->usbdev->dev,
+                       "%s: called with NULL lirc driver struct!\n", __func__);
                return -EINVAL;
        }
 
@@ -347,8 +347,8 @@ static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf)
                if (ir->buf_in[2] == 0)
                        send_fragment(ir, buf, DEVICE_HEADERLEN, ret);
                else {
-                       printk(KERN_WARNING DRIVER_NAME
-                              "[%d]: Device buffer overrun.\n", ir->devnum);
+                       dev_warn(&ir->usbdev->dev,
+                                "[%d]: Device buffer overrun.\n", ir->devnum);
                        /* HHHNNNNNNNNNNNOOOOOOOO H = header
                              <---[2]--->         N = newer
                           <---------ret--------> O = older */
index 2944fde89f44c55ec79229707d2fe1f61c170d50..343c622f938751b30ba09356734abd83b19b3176 100644 (file)
@@ -20,6 +20,8 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -205,12 +207,12 @@ static void deregister_from_lirc(struct imon_context *context)
 
        retval = lirc_unregister_driver(minor);
        if (retval)
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: unable to deregister from lirc(%d)",
-                      __func__, retval);
+               dev_err(&context->usbdev->dev,
+                       ": %s: unable to deregister from lirc(%d)",
+                       __func__, retval);
        else
-               printk(KERN_INFO MOD_NAME ": Deregistered iMON driver "
-                      "(minor:%d)\n", minor);
+               dev_info(&context->usbdev->dev,
+                        "Deregistered iMON driver (minor:%d)\n", minor);
 
 }
 
@@ -231,8 +233,7 @@ static int display_open(struct inode *inode, struct file *file)
        subminor = iminor(inode);
        interface = usb_find_interface(&imon_driver, subminor);
        if (!interface) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: could not find interface for minor %d\n",
+               pr_err("%s: could not find interface for minor %d\n",
                       __func__, subminor);
                retval = -ENODEV;
                goto exit;
@@ -282,8 +283,7 @@ static int display_close(struct inode *inode, struct file *file)
        context = file->private_data;
 
        if (!context) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      "%s: no context for device\n", __func__);
+               pr_err("%s: no context for device\n", __func__);
                return -ENODEV;
        }
 
@@ -391,8 +391,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
 
        context = file->private_data;
        if (!context) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      "%s: no context for device\n", __func__);
+               pr_err("%s: no context for device\n", __func__);
                return -ENODEV;
        }
 
@@ -521,8 +520,7 @@ static void ir_close(void *data)
 
        context = (struct imon_context *)data;
        if (!context) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      "%s: no context for device\n", __func__);
+               pr_err("%s: no context for device\n", __func__);
                return;
        }
 
@@ -1009,8 +1007,8 @@ static void imon_disconnect(struct usb_interface *interface)
 
        mutex_unlock(&driver_lock);
 
-       printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n",
-              __func__, ifnum);
+       dev_info(&interface->dev, "%s: iMON device (intf%d) disconnected\n",
+                __func__, ifnum);
 }
 
 static int imon_suspend(struct usb_interface *intf, pm_message_t message)
index ec14bc81851b38838de4abca6e83b9e8bd7aa4ee..41d110f8bc02e2775236315342d0b06a79a9bd35 100644 (file)
@@ -22,6 +22,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /*** Includes ***/
 
 #include <linux/module.h>
@@ -115,8 +117,7 @@ static void out(int offset, int value)
                parport_write_control(pport, value);
                break;
        case LIRC_LP_STATUS:
-               printk(KERN_INFO "%s: attempt to write to status register\n",
-                      LIRC_DRIVER_NAME);
+               pr_info("attempt to write to status register\n");
                break;
        }
 }
@@ -166,27 +167,23 @@ static unsigned int init_lirc_timer(void)
                if (default_timer == 0) {
                        /* autodetect timer */
                        newtimer = (1000000*count)/timeelapsed;
-                       printk(KERN_INFO "%s: %u Hz timer detected\n",
-                              LIRC_DRIVER_NAME, newtimer);
+                       pr_info("%u Hz timer detected\n", newtimer);
                        return newtimer;
                }  else {
                        newtimer = (1000000*count)/timeelapsed;
                        if (abs(newtimer - default_timer) > default_timer/10) {
                                /* bad timer */
-                               printk(KERN_NOTICE "%s: bad timer: %u Hz\n",
-                                      LIRC_DRIVER_NAME, newtimer);
-                               printk(KERN_NOTICE "%s: using default timer: "
-                                      "%u Hz\n",
-                                      LIRC_DRIVER_NAME, default_timer);
+                               pr_notice("bad timer: %u Hz\n", newtimer);
+                               pr_notice("using default timer: %u Hz\n",
+                                         default_timer);
                                return default_timer;
                        } else {
-                               printk(KERN_INFO "%s: %u Hz timer detected\n",
-                                      LIRC_DRIVER_NAME, newtimer);
+                               pr_info("%u Hz timer detected\n", newtimer);
                                return newtimer; /* use detected value */
                        }
                }
        } else {
-               printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME);
+               pr_notice("no timer detected\n");
                return 0;
        }
 }
@@ -194,13 +191,10 @@ static unsigned int init_lirc_timer(void)
 static int lirc_claim(void)
 {
        if (parport_claim(ppdevice) != 0) {
-               printk(KERN_WARNING "%s: could not claim port\n",
-                      LIRC_DRIVER_NAME);
-               printk(KERN_WARNING "%s: waiting for port becoming available"
-                      "\n", LIRC_DRIVER_NAME);
+               pr_warn("could not claim port\n");
+               pr_warn("waiting for port becoming available\n");
                if (parport_claim_or_block(ppdevice) < 0) {
-                       printk(KERN_NOTICE "%s: could not claim port, giving"
-                              " up\n", LIRC_DRIVER_NAME);
+                       pr_notice("could not claim port, giving up\n");
                        return 0;
                }
        }
@@ -219,7 +213,7 @@ static void rbuf_write(int signal)
        if (nwptr == rptr) {
                /* no new signals will be accepted */
                lost_irqs++;
-               printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME);
+               pr_notice("buffer overrun\n");
                return;
        }
        rbuf[wptr] = signal;
@@ -290,7 +284,7 @@ static void irq_handler(void *blah)
                if (signal > timeout
                    || (check_pselecd && (in(1) & LP_PSELECD))) {
                        signal = 0;
-                       printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME);
+                       pr_notice("timeout\n");
                        break;
                }
        } while (lirc_get_signal());
@@ -644,8 +638,7 @@ static int __init lirc_parallel_init(void)
 
        result = platform_driver_register(&lirc_parallel_driver);
        if (result) {
-               printk(KERN_NOTICE "platform_driver_register"
-                                       " returned %d\n", result);
+               pr_notice("platform_driver_register returned %d\n", result);
                return result;
        }
 
@@ -661,8 +654,7 @@ static int __init lirc_parallel_init(void)
 
        pport = parport_find_base(io);
        if (pport == NULL) {
-               printk(KERN_NOTICE "%s: no port at %x found\n",
-                      LIRC_DRIVER_NAME, io);
+               pr_notice("no port at %x found\n", io);
                result = -ENXIO;
                goto exit_device_put;
        }
@@ -670,8 +662,7 @@ static int __init lirc_parallel_init(void)
                                           pf, kf, irq_handler, 0, NULL);
        parport_put_port(pport);
        if (ppdevice == NULL) {
-               printk(KERN_NOTICE "%s: parport_register_device() failed\n",
-                      LIRC_DRIVER_NAME);
+               pr_notice("parport_register_device() failed\n");
                result = -ENXIO;
                goto exit_device_put;
        }
@@ -706,14 +697,12 @@ static int __init lirc_parallel_init(void)
        driver.dev = &lirc_parallel_dev->dev;
        driver.minor = lirc_register_driver(&driver);
        if (driver.minor < 0) {
-               printk(KERN_NOTICE "%s: register_chrdev() failed\n",
-                      LIRC_DRIVER_NAME);
+               pr_notice("register_chrdev() failed\n");
                parport_unregister_device(ppdevice);
                result = -EIO;
                goto exit_device_put;
        }
-       printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n",
-              LIRC_DRIVER_NAME, io, irq);
+       pr_info("installed using port 0x%04x irq %d\n", io, irq);
        return 0;
 
 exit_device_put:
index f4e4d9003f38130fd56a9668dddedb0d09324707..b3fe21e7a90dfdaceb38b2683706de90c9ac1dc3 100644 (file)
@@ -34,6 +34,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -171,7 +173,7 @@ static void delete_context(struct sasem_context *context)
        kfree(context);
 
        if (debug)
-               printk(KERN_INFO "%s: context deleted\n", __func__);
+               pr_info("%s: context deleted\n", __func__);
 }
 
 static void deregister_from_lirc(struct sasem_context *context)
@@ -181,11 +183,10 @@ static void deregister_from_lirc(struct sasem_context *context)
 
        retval = lirc_unregister_driver(minor);
        if (retval)
-               printk(KERN_ERR "%s: unable to deregister from lirc (%d)\n",
-                       __func__, retval);
+               pr_err("%s: unable to deregister from lirc (%d)\n",
+                      __func__, retval);
        else
-               printk(KERN_INFO "Deregistered Sasem driver (minor:%d)\n",
-                      minor);
+               pr_info("Deregistered Sasem driver (minor:%d)\n", minor);
 
 }
 
@@ -206,8 +207,7 @@ static int vfd_open(struct inode *inode, struct file *file)
        subminor = iminor(inode);
        interface = usb_find_interface(&sasem_driver, subminor);
        if (!interface) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: could not find interface for minor %d\n",
+               pr_err("%s: could not find interface for minor %d\n",
                       __func__, subminor);
                retval = -ENODEV;
                goto exit;
@@ -252,8 +252,7 @@ static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        context = (struct sasem_context *) file->private_data;
 
        if (!context) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: no context for device\n", __func__);
+               pr_err("%s: no context for device\n", __func__);
                return -ENODEV;
        }
 
@@ -266,7 +265,7 @@ static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                context->vfd_contrast = (unsigned int)arg;
                break;
        default:
-               printk(KERN_INFO "Unknown IOCTL command\n");
+               pr_info("Unknown IOCTL command\n");
                mutex_unlock(&context->ctx_lock);
                return -ENOIOCTLCMD;  /* not supported */
        }
@@ -287,8 +286,7 @@ static int vfd_close(struct inode *inode, struct file *file)
        context = (struct sasem_context *) file->private_data;
 
        if (!context) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: no context for device\n", __func__);
+               pr_err("%s: no context for device\n", __func__);
                return -ENODEV;
        }
 
@@ -299,7 +297,7 @@ static int vfd_close(struct inode *inode, struct file *file)
                retval = -EIO;
        } else {
                context->vfd_isopen = 0;
-               printk(KERN_INFO "VFD port closed\n");
+               dev_info(&context->dev->dev, "VFD port closed\n");
                if (!context->dev_present && !context->ir_isopen) {
 
                        /* Device disconnected before close and IR port is
@@ -373,16 +371,14 @@ static ssize_t vfd_write(struct file *file, const char *buf,
 
        context = (struct sasem_context *) file->private_data;
        if (!context) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: no context for device\n", __func__);
+               pr_err("%s: no context for device\n", __func__);
                return -ENODEV;
        }
 
        mutex_lock(&context->ctx_lock);
 
        if (!context->dev_present) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: no Sasem device present\n", __func__);
+               pr_err("%s: no Sasem device present\n", __func__);
                retval = -ENODEV;
                goto exit;
        }
@@ -519,7 +515,7 @@ static int ir_open(void *data)
                        __func__, retval);
        else {
                context->ir_isopen = 1;
-               printk(KERN_INFO "IR port opened\n");
+               dev_info(&context->dev->dev, "IR port opened\n");
        }
 
 exit:
@@ -538,8 +534,7 @@ static void ir_close(void *data)
 
        context = (struct sasem_context *)data;
        if (!context) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": %s: no context for device\n", __func__);
+               pr_err("%s: no context for device\n", __func__);
                return;
        }
 
@@ -547,7 +542,7 @@ static void ir_close(void *data)
 
        usb_kill_urb(context->rx_urb);
        context->ir_isopen = 0;
-       printk(KERN_INFO "IR port closed\n");
+       pr_info("IR port closed\n");
 
        if (!context->dev_present) {
 
@@ -584,8 +579,9 @@ static void incoming_packet(struct sasem_context *context,
        int i;
 
        if (len != 8) {
-               printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n",
-                    __func__, len);
+               dev_warn(&context->dev->dev,
+                        "%s: invalid incoming packet size (%d)\n",
+                        __func__, len);
                return;
        }
 
@@ -663,7 +659,7 @@ static void usb_rx_callback(struct urb *urb)
                break;
 
        default:
-               printk(KERN_WARNING "%s: status (%d): ignored",
+               dev_warn(&urb->dev->dev, "%s: status (%d): ignored",
                         __func__, urb->status);
                break;
        }
@@ -830,8 +826,9 @@ static int sasem_probe(struct usb_interface *interface,
                retval = lirc_minor;
                goto unlock;
        } else
-               printk(KERN_INFO "%s: Registered Sasem driver (minor:%d)\n",
-                       __func__, lirc_minor);
+               dev_info(&interface->dev,
+                        "%s: Registered Sasem driver (minor:%d)\n",
+                        __func__, lirc_minor);
 
        /* Needed while unregistering! */
        driver->minor = lirc_minor;
@@ -852,15 +849,18 @@ static int sasem_probe(struct usb_interface *interface,
        if (vfd_ep_found) {
 
                if (debug)
-                       printk(KERN_INFO "Registering VFD with sysfs\n");
+                       dev_info(&interface->dev,
+                                "Registering VFD with sysfs\n");
                if (usb_register_dev(interface, &sasem_class))
                        /* Not a fatal error, so ignore */
-                       printk(KERN_INFO "%s: could not get a minor number "
-                              "for VFD\n", __func__);
+                       dev_info(&interface->dev,
+                                "%s: could not get a minor number for VFD\n",
+                                __func__);
        }
 
-       printk(KERN_INFO "%s: Sasem device on usb<%d:%d> initialized\n",
-                       __func__, dev->bus->busnum, dev->devnum);
+       dev_info(&interface->dev,
+                "%s: Sasem device on usb<%d:%d> initialized\n",
+                __func__, dev->bus->busnum, dev->devnum);
 unlock:
        mutex_unlock(&context->ctx_lock);
 
@@ -891,7 +891,7 @@ exit:
 }
 
 /**
- * Callback function for USB core API: disonnect
+ * Callback function for USB core API: disconnect
  */
 static void sasem_disconnect(struct usb_interface *interface)
 {
@@ -903,7 +903,8 @@ static void sasem_disconnect(struct usb_interface *interface)
        context = usb_get_intfdata(interface);
        mutex_lock(&context->ctx_lock);
 
-       printk(KERN_INFO "%s: Sasem device disconnected\n", __func__);
+       dev_info(&interface->dev, "%s: Sasem device disconnected\n",
+                __func__);
 
        usb_set_intfdata(interface, NULL);
        context->dev_present = 0;
index b5d0088f3102a4fb52062a5a4d528634b77eaa7b..af08e677b60fd31cf94c687d85845838e7682e6a 100644 (file)
@@ -48,6 +48,8 @@
  * Steve Davies <steve@daviesfam.org>  July 2001
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
@@ -667,8 +669,7 @@ static irqreturn_t irq_handler(int i, void *blah)
                counter++;
                status = sinp(UART_MSR);
                if (counter > RS_ISR_PASS_LIMIT) {
-                       printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: "
-                              "We're caught!\n");
+                       pr_warn("AIEEEE: We're caught!\n");
                        break;
                }
                if ((status & hardware[type].signal_pin_change)
@@ -703,11 +704,10 @@ static irqreturn_t irq_handler(int i, void *blah)
                        dcd = (status & hardware[type].signal_pin) ? 1 : 0;
 
                        if (dcd == last_dcd) {
-                               printk(KERN_WARNING LIRC_DRIVER_NAME
-                               ": ignoring spike: %d %d %lx %lx %lx %lx\n",
-                               dcd, sense,
-                               tv.tv_sec, lasttv.tv_sec,
-                               tv.tv_usec, lasttv.tv_usec);
+                               pr_warn("ignoring spike: %d %d %lx %lx %lx %lx\n",
+                                       dcd, sense,
+                                       tv.tv_sec, lasttv.tv_sec,
+                                       tv.tv_usec, lasttv.tv_usec);
                                continue;
                        }
 
@@ -715,25 +715,20 @@ static irqreturn_t irq_handler(int i, void *blah)
                        if (tv.tv_sec < lasttv.tv_sec ||
                            (tv.tv_sec == lasttv.tv_sec &&
                             tv.tv_usec < lasttv.tv_usec)) {
-                               printk(KERN_WARNING LIRC_DRIVER_NAME
-                                      ": AIEEEE: your clock just jumped "
-                                      "backwards\n");
-                               printk(KERN_WARNING LIRC_DRIVER_NAME
-                                      ": %d %d %lx %lx %lx %lx\n",
-                                      dcd, sense,
-                                      tv.tv_sec, lasttv.tv_sec,
-                                      tv.tv_usec, lasttv.tv_usec);
+                               pr_warn("AIEEEE: your clock just jumped backwards\n");
+                               pr_warn("%d %d %lx %lx %lx %lx\n",
+                                       dcd, sense,
+                                       tv.tv_sec, lasttv.tv_sec,
+                                       tv.tv_usec, lasttv.tv_usec);
                                data = PULSE_MASK;
                        } else if (deltv > 15) {
                                data = PULSE_MASK; /* really long time */
                                if (!(dcd^sense)) {
                                        /* sanity check */
-                                       printk(KERN_WARNING LIRC_DRIVER_NAME
-                                              ": AIEEEE: "
-                                              "%d %d %lx %lx %lx %lx\n",
-                                              dcd, sense,
-                                              tv.tv_sec, lasttv.tv_sec,
-                                              tv.tv_usec, lasttv.tv_usec);
+                                       pr_warn("AIEEEE: %d %d %lx %lx %lx %lx\n",
+                                               dcd, sense,
+                                               tv.tv_sec, lasttv.tv_sec,
+                                               tv.tv_usec, lasttv.tv_usec);
                                        /*
                                         * detecting pulse while this
                                         * MUST be a space!
@@ -776,8 +771,7 @@ static int hardware_init_port(void)
        soutp(UART_IER, scratch);
        if (scratch2 != 0 || scratch3 != 0x0f) {
                /* we fail, there's nothing here */
-               printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test "
-                      "failed, cannot continue\n");
+               pr_err("port existence test failed, cannot continue\n");
                return -ENODEV;
        }
 
@@ -850,11 +844,9 @@ static int lirc_serial_probe(struct platform_device *dev)
                             LIRC_DRIVER_NAME, (void *)&hardware);
        if (result < 0) {
                if (result == -EBUSY)
-                       printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n",
-                              irq);
+                       dev_err(&dev->dev, "IRQ %d busy\n", irq);
                else if (result == -EINVAL)
-                       printk(KERN_ERR LIRC_DRIVER_NAME
-                              ": Bad irq number or handler\n");
+                       dev_err(&dev->dev, "Bad irq number or handler\n");
                return result;
        }
 
@@ -869,14 +861,11 @@ static int lirc_serial_probe(struct platform_device *dev)
                                    LIRC_DRIVER_NAME) == NULL))
           || ((iommap == 0)
               && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) {
-               printk(KERN_ERR  LIRC_DRIVER_NAME
-                      ": port %04x already in use\n", io);
-               printk(KERN_WARNING LIRC_DRIVER_NAME
-                      ": use 'setserial /dev/ttySX uart none'\n");
-               printk(KERN_WARNING LIRC_DRIVER_NAME
-                      ": or compile the serial port driver as module and\n");
-               printk(KERN_WARNING LIRC_DRIVER_NAME
-                      ": make sure this module is loaded first\n");
+               dev_err(&dev->dev, "port %04x already in use\n", io);
+               dev_warn(&dev->dev, "use 'setserial /dev/ttySX uart none'\n");
+               dev_warn(&dev->dev,
+                        "or compile the serial port driver as module and\n");
+               dev_warn(&dev->dev, "make sure this module is loaded first\n");
                result = -EBUSY;
                goto exit_free_irq;
        }
@@ -907,11 +896,11 @@ static int lirc_serial_probe(struct platform_device *dev)
                        msleep(40);
                }
                sense = (nlow >= nhigh ? 1 : 0);
-               printk(KERN_INFO LIRC_DRIVER_NAME  ": auto-detected active "
-                      "%s receiver\n", sense ? "low" : "high");
+               dev_info(&dev->dev, "auto-detected active %s receiver\n",
+                        sense ? "low" : "high");
        } else
-               printk(KERN_INFO LIRC_DRIVER_NAME  ": Manually using active "
-                      "%s receiver\n", sense ? "low" : "high");
+               dev_info(&dev->dev, "Manually using active %s receiver\n",
+                        sense ? "low" : "high");
 
        dprintk("Interrupt %d, port %04x obtained\n", irq, io);
        return 0;
@@ -1251,8 +1240,7 @@ static int __init lirc_serial_init_module(void)
        driver.dev = &lirc_serial_dev->dev;
        driver.minor = lirc_register_driver(&driver);
        if (driver.minor < 0) {
-               printk(KERN_ERR  LIRC_DRIVER_NAME
-                      ": register_chrdev failed!\n");
+               pr_err("register_chrdev failed!\n");
                lirc_serial_exit();
                return driver.minor;
        }
index a45799874a21cf7ded13745c508ec99410b09f25..63a554c36f751034d053a45a60262163c5500b23 100644 (file)
@@ -33,6 +33,8 @@
  *   parts cut'n'pasted from sa1100_ir.c (C) 2000 Russell King
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
@@ -495,7 +497,7 @@ static int init_chrdev(void)
        driver.dev = &lirc_sir_dev->dev;
        driver.minor = lirc_register_driver(&driver);
        if (driver.minor < 0) {
-               printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");
+               pr_err("init_chrdev() failed.\n");
                return -EIO;
        }
        return 0;
@@ -604,7 +606,7 @@ static irqreturn_t sir_interrupt(int irq, void *dev_id)
        }
 
        if (status & UTSR0_TFS)
-               printk(KERN_ERR "transmit fifo not full, shouldn't happen\n");
+               pr_err("transmit fifo not full, shouldn't happen\n");
 
        /* We must clear certain bits. */
        status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
@@ -787,7 +789,7 @@ static int init_hardware(void)
 #ifdef LIRC_ON_SA1100
 #ifdef CONFIG_SA1100_BITSY
        if (machine_is_bitsy()) {
-               printk(KERN_INFO "Power on IR module\n");
+               pr_info("Power on IR module\n");
                set_bitsy_egpio(EGPIO_BITSY_IR_ON);
        }
 #endif
@@ -885,8 +887,7 @@ static int init_hardware(void)
        udelay(1500);
 
        /* read previous control byte */
-       printk(KERN_INFO LIRC_DRIVER_NAME
-              ": 0x%02x\n", sinp(UART_RX));
+       pr_info("0x%02x\n", sinp(UART_RX));
 
        /* Set DLAB 1. */
        soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
@@ -964,8 +965,7 @@ static int init_port(void)
        /* get I/O port access and IRQ line */
 #ifndef LIRC_ON_SA1100
        if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
-               printk(KERN_ERR LIRC_DRIVER_NAME
-                      ": i/o port 0x%.4x already in use.\n", io);
+               pr_err("i/o port 0x%.4x already in use.\n", io);
                return -EBUSY;
        }
 #endif
@@ -975,15 +975,11 @@ static int init_port(void)
 #               ifndef LIRC_ON_SA1100
                release_region(io, 8);
 #               endif
-               printk(KERN_ERR LIRC_DRIVER_NAME
-                       ": IRQ %d already in use.\n",
-                       irq);
+               pr_err("IRQ %d already in use.\n", irq);
                return retval;
        }
 #ifndef LIRC_ON_SA1100
-       printk(KERN_INFO LIRC_DRIVER_NAME
-               ": I/O port 0x%.4x, IRQ %d.\n",
-               io, irq);
+       pr_info("I/O port 0x%.4x, IRQ %d.\n", io, irq);
 #endif
 
        init_timer(&timerlist);
@@ -1213,8 +1209,7 @@ static int init_lirc_sir(void)
        if (retval < 0)
                return retval;
        init_hardware();
-       printk(KERN_INFO LIRC_DRIVER_NAME
-               ": Installed.\n");
+       pr_info("Installed.\n");
        return 0;
 }
 
@@ -1243,23 +1238,20 @@ static int __init lirc_sir_init(void)
 
        retval = platform_driver_register(&lirc_sir_driver);
        if (retval) {
-               printk(KERN_ERR LIRC_DRIVER_NAME ": Platform driver register "
-                      "failed!\n");
+               pr_err("Platform driver register failed!\n");
                return -ENODEV;
        }
 
        lirc_sir_dev = platform_device_alloc("lirc_dev", 0);
        if (!lirc_sir_dev) {
-               printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device alloc "
-                      "failed!\n");
+               pr_err("Platform device alloc failed!\n");
                retval = -ENOMEM;
                goto pdev_alloc_fail;
        }
 
        retval = platform_device_add(lirc_sir_dev);
        if (retval) {
-               printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device add "
-                      "failed!\n");
+               pr_err("Platform device add failed!\n");
                retval = -ENODEV;
                goto pdev_add_fail;
        }
@@ -1292,7 +1284,7 @@ static void __exit lirc_sir_exit(void)
        drop_port();
        platform_device_unregister(lirc_sir_dev);
        platform_driver_unregister(&lirc_sir_driver);
-       printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
+       pr_info("Uninstalled.\n");
 }
 
 module_init(lirc_sir_init);
index 56210f0fc5ec162a59b466418487b2ad4bfecce6..58ab61b1f1d94b2c19309e91c5d4ea1b3fcf9d81 100644 (file)
@@ -231,15 +231,15 @@ static void run_p2m_test(struct solo_dev *solo_dev)
        u32 size = SOLO_JPEG_EXT_ADDR(solo_dev) + SOLO_JPEG_EXT_SIZE(solo_dev);
        int i, d;
 
-       printk(KERN_WARNING "%s: Testing %u bytes of external ram\n",
-              SOLO6X10_NAME, size);
+       dev_warn(&solo_dev->pdev->dev, "Testing %u bytes of external ram\n",
+                size);
 
        for (i = 0; i < size; i += TEST_CHUNK_SIZE)
                for (d = 0; d < 4; d++)
                        errs += p2m_test(solo_dev, d, i, TEST_CHUNK_SIZE);
 
-       printk(KERN_WARNING "%s: Found %llu errors during p2m test\n",
-              SOLO6X10_NAME, errs);
+       dev_warn(&solo_dev->pdev->dev, "Found %llu errors during p2m test\n",
+                errs);
 
        return;
 }
index f8f0da952288d127963bdd3c19887864c141f494..4977e869d5b78786a05f32c2db57dca6e3400882 100644 (file)
@@ -1619,6 +1619,8 @@ static int solo_s_ext_ctrls(struct file *file, void *priv,
                                solo_enc->osd_text[OSD_TEXT_MAX] = '\0';
                                if (!err)
                                        err = solo_osd_print(solo_enc);
+                               else
+                                       err = -EFAULT;
                        }
                        break;
                default:
@@ -1654,6 +1656,8 @@ static int solo_g_ext_ctrls(struct file *file, void *priv,
                                err = copy_to_user(ctrl->string,
                                                   solo_enc->osd_text,
                                                   OSD_TEXT_MAX);
+                               if (err)
+                                       err = -EFAULT;
                        }
                        break;
                default:
index 2038a8a3f8aace34f54732195c465a9dd87a57e3..56b9ce4472fc0bc04e25666c0373251dc9267d71 100644 (file)
@@ -9,6 +9,7 @@ struct ppi_info;
 struct bcap_route {
        u32 input;
        u32 output;
+       u32 ppi_control;
 };
 
 struct bfin_capture_config {
@@ -30,8 +31,8 @@ struct bfin_capture_config {
        unsigned long ppi_control;
        /* ppi interrupt mask */
        u32 int_mask;
-       /* horizontal blanking clocks */
-       int blank_clocks;
+       /* horizontal blanking pixels */
+       int blank_pixels;
 };
 
 #endif
index 8f72f8a0b3d08f0bf81094dfe52ba608bf51f123..65c467576b31e12ca70bc4191b717aedc41480d5 100644 (file)
 #define _PPI_H_
 
 #include <linux/interrupt.h>
+#include <asm/blackfin.h>
+#include <asm/bfin_ppi.h>
 
+/* EPPI */
 #ifdef EPPI_EN
 #define PORT_EN EPPI_EN
+#define PORT_DIR EPPI_DIR
 #define DMA32 0
 #define PACK_EN PACKEN
 #endif
 
+/* EPPI3 */
+#ifdef EPPI0_CTL2
+#define PORT_EN EPPI_CTL_EN
+#define PORT_DIR EPPI_CTL_DIR
+#define PACK_EN EPPI_CTL_PACKEN
+#define DMA32 0
+#define DLEN_8 EPPI_CTL_DLEN08
+#define DLEN_16 EPPI_CTL_DLEN16
+#endif
+
 struct ppi_if;
 
 struct ppi_params {
-       int width;
-       int height;
-       int bpp;
-       unsigned long ppi_control;
-       u32 int_mask;
-       int blank_clocks;
+       u32 width;              /* width in pixels */
+       u32 height;             /* height in lines */
+       u32 hdelay;             /* delay after the HSYNC in pixels */
+       u32 vdelay;             /* delay after the VSYNC in lines */
+       u32 line;               /* total pixels per line */
+       u32 frame;              /* total lines per frame */
+       u32 hsync;              /* HSYNC length in pixels */
+       u32 vsync;              /* VSYNC length in lines */
+       int bpp;                /* bits per pixel */
+       int dlen;               /* data length for ppi in bits */
+       u32 ppi_control;        /* ppi configuration */
+       u32 int_mask;           /* interrupt mask */
 };
 
 struct ppi_ops {
@@ -51,6 +71,7 @@ struct ppi_ops {
 enum ppi_type {
        PPI_TYPE_PPI,
        PPI_TYPE_EPPI,
+       PPI_TYPE_EPPI3,
 };
 
 struct ppi_info {
index 5ab0d8d41f6827b6cd582e669e536de3b106ee69..42628fcfe1bd890eb20ebea9ec2073fa5bdd8137 100644 (file)
@@ -26,7 +26,9 @@
 
 #include <media/davinci/vpbe_types.h>
 
-#define VPBE_OSD_SUBDEV_NAME "vpbe-osd"
+#define DM644X_VPBE_OSD_SUBDEV_NAME    "dm644x,vpbe-osd"
+#define DM365_VPBE_OSD_SUBDEV_NAME     "dm365,vpbe-osd"
+#define DM355_VPBE_OSD_SUBDEV_NAME     "dm355,vpbe-osd"
 
 /**
  * enum osd_layer
@@ -387,7 +389,6 @@ struct osd_state {
 };
 
 struct osd_platform_data {
-       enum vpbe_version vpbe_type;
        int  field_inv_wa_enable;
 };
 
index cc78c2eb16da25a689ece25ad1dfc931c6dcf211..476fafc2f522997a0cf81d5d75aca11edb6d3701 100644 (file)
@@ -20,7 +20,9 @@
 #include <media/v4l2-subdev.h>
 #include <media/davinci/vpbe_types.h>
 
-#define VPBE_VENC_SUBDEV_NAME "vpbe-venc"
+#define DM644X_VPBE_VENC_SUBDEV_NAME   "dm644x,vpbe-venc"
+#define DM365_VPBE_VENC_SUBDEV_NAME    "dm365,vpbe-venc"
+#define DM355_VPBE_VENC_SUBDEV_NAME    "dm355,vpbe-venc"
 
 /* venc events */
 #define VENC_END_OF_FRAME      BIT(0)
@@ -28,7 +30,6 @@
 #define VENC_SECOND_FIELD      BIT(2)
 
 struct venc_platform_data {
-       enum vpbe_version venc_type;
        int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
                            int field);
        int (*setup_clock)(enum vpbe_enc_timings_type type,
index b586495bcd53cfa9d676847415431e1914d6dfbd..153473daaa32fc9d559ef47661692e3668074f05 100644 (file)
@@ -105,4 +105,20 @@ enum vpss_wbl_sel {
 };
 /* clear wbl overflow flag for DM6446 */
 int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel);
+
+/* set sync polarity*/
+void vpss_set_sync_pol(struct vpss_sync_pol sync);
+/* set the PG_FRAME_SIZE register */
+void vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size);
+/*
+ * vpss_check_and_clear_interrupt - check and clear interrupt
+ * @irq - common enumerator for IRQ
+ *
+ * Following return values used:-
+ * 0 - interrupt occurred and cleared
+ * 1 - interrupt not occurred
+ * 2 - interrupt status not available
+ */
+int vpss_dma_complete_interrupt(void);
+
 #endif
index 74f55a3f14eb80905186e927bd1d5f34bef070c6..f74ee6f897114d6decd58e579c81e6f3aa4c0566 100644 (file)
@@ -182,6 +182,7 @@ void rc_map_init(void);
 #define RC_MAP_TEVII_NEC                 "rc-tevii-nec"
 #define RC_MAP_TIVO                      "rc-tivo"
 #define RC_MAP_TOTAL_MEDIA_IN_HAND       "rc-total-media-in-hand"
+#define RC_MAP_TOTAL_MEDIA_IN_HAND_02    "rc-total-media-in-hand-02"
 #define RC_MAP_TREKSTOR                  "rc-trekstor"
 #define RC_MAP_TT_1500                   "rc-tt-1500"
 #define RC_MAP_TWINHAN_VP1027_DVBS       "rc-twinhan1027"
index 1a0b2db4c5d318c80b135d5a69b7f4b34659327c..ec7c9c00b256948f41c00d7c8315f59fa0e5e0d4 100644 (file)
@@ -225,4 +225,6 @@ bool v4l2_detect_gtf(unsigned frame_height, unsigned hfreq, unsigned vsync,
 
 struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait);
 
+void v4l2_get_timestamp(struct timeval *tv);
+
 #endif /* V4L2_COMMON_H_ */
index 7e82d2b193d5625702594fe59f1484e1b09c3d06..d3eef01da648d49387d6efe41bb2cae66bd6dac6 100644 (file)
@@ -125,7 +125,7 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
                  struct vm_area_struct *vma);
 
-struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops);
+struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops);
 void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev);
 
 struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
index 7d64e0e1a18b2543b7bc35ad20e202e6b1282d60..b9b7bea04537c59c7adb344217238575e74be2c6 100644 (file)
@@ -47,8 +47,9 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
        V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
 
-       /* YUV (including grey) - next is 0x2014 */
+       /* YUV (including grey) - next is 0x2017 */
        V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
+       V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
        V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
        V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
        V4L2_MBUS_FMT_YUYV8_1_5X8 = 0x2004,
@@ -65,14 +66,20 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
        V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
        V4L2_MBUS_FMT_YVYU8_1X16 = 0x2012,
+       V4L2_MBUS_FMT_YDYUYDYV8_1X16 = 0x2014,
        V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
        V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
+       V4L2_MBUS_FMT_YUV10_1X30 = 0x2016,
 
-       /* Bayer - next is 0x3015 */
+       /* Bayer - next is 0x3019 */
        V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
        V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013,
        V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
        V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014,
+       V4L2_MBUS_FMT_SBGGR10_ALAW8_1X8 = 0x3015,
+       V4L2_MBUS_FMT_SGBRG10_ALAW8_1X8 = 0x3016,
+       V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8 = 0x3017,
+       V4L2_MBUS_FMT_SRGGB10_ALAW8_1X8 = 0x3018,
        V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
        V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
        V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
index 3cf3e946e331ee6ee006b03b5d569dc24719438b..94cbe26e9f0074787222665202f4be83629ba73e 100644 (file)
@@ -334,6 +334,9 @@ struct v4l2_pix_format {
 /* Palette formats */
 #define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
 
+/* Chrominance formats */
+#define V4L2_PIX_FMT_UV8     v4l2_fourcc('U', 'V', '8', ' ') /*  8  UV 4:4 */
+
 /* Luminance+Chrominance formats */
 #define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y', 'V', 'U', '9') /*  9  YVU 4:1:0     */
 #define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
@@ -386,6 +389,11 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12  GBGB.. RGRG.. */
 #define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12  GRGR.. BGBG.. */
 #define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12  RGRG.. GBGB.. */
+       /* 10bit raw bayer a-law compressed to 8 bits */
+#define V4L2_PIX_FMT_SBGGR10ALAW8 v4l2_fourcc('a', 'B', 'A', '8')
+#define V4L2_PIX_FMT_SGBRG10ALAW8 v4l2_fourcc('a', 'G', 'A', '8')
+#define V4L2_PIX_FMT_SGRBG10ALAW8 v4l2_fourcc('a', 'g', 'A', '8')
+#define V4L2_PIX_FMT_SRGGB10ALAW8 v4l2_fourcc('a', 'R', 'A', '8')
        /* 10bit raw bayer DPCM compressed to 8 bits */
 #define V4L2_PIX_FMT_SBGGR10DPCM8 v4l2_fourcc('b', 'B', 'A', '8')
 #define V4L2_PIX_FMT_SGBRG10DPCM8 v4l2_fourcc('b', 'G', 'A', '8')
@@ -693,6 +701,10 @@ struct v4l2_buffer {
 /* Cache handling flags */
 #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE      0x0800
 #define V4L2_BUF_FLAG_NO_CACHE_CLEAN           0x1000
+/* Timestamp type */
+#define V4L2_BUF_FLAG_TIMESTAMP_MASK           0xe000
+#define V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN                0x0000
+#define V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC      0x2000
 
 /**
  * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor