]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Oct 2012 01:04:42 +0000 (10:04 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Oct 2012 01:04:42 +0000 (10:04 +0900)
Pull third pile of VFS updates from Al Viro:
 "Stuff from Jeff Layton, mostly.  Sanitizing interplay between audit
  and namei, removing a lot of insanity from audit_inode() mess and
  getting things ready for his ESTALE patchset."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  procfs: don't need a PATH_MAX allocation to hold a string representation of an int
  vfs: embed struct filename inside of names_cache allocation if possible
  audit: make audit_inode take struct filename
  vfs: make path_openat take a struct filename pointer
  vfs: turn do_path_lookup into wrapper around struct filename variant
  audit: allow audit code to satisfy getname requests from its names_list
  vfs: define struct filename and have getname() return it
  vfs: unexport getname and putname symbols
  acct: constify the name arg to acct_on
  vfs: allocate page instead of names_cache buffer in mount_block_root
  audit: overhaul __audit_inode_child to accomodate retrying
  audit: optimize audit_compare_dname_path
  audit: make audit_compare_dname_path use parent_len helper
  audit: remove dirlen argument to audit_compare_dname_path
  audit: set the name_len in audit_inode for parent lookups
  audit: add a new "type" field to audit_names struct
  audit: reverse arguments to audit_inode_child
  audit: no need to walk list in audit_inode if name is NULL
  audit: pass in dentry to audit_copy_inode wherever possible
  audit: remove unnecessary NULL ptr checks from do_path_lookup

256 files changed:
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/controls.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/subdev-formats.xml
Documentation/DocBook/media/v4l/vidioc-qbuf.xml
Documentation/DocBook/media/v4l/vidioc-querybuf.xml
Documentation/arm/Booting
Documentation/video4linux/v4l2-controls.txt
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/include/asm/assembler.h
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/glue-cache.h
arch/arm/include/asm/opcodes-virt.h
arch/arm/include/asm/ptrace.h
arch/arm/include/asm/vfpmacros.h
arch/arm/include/asm/virt.h [new file with mode: 0644]
arch/arm/kernel/Makefile
arch/arm/kernel/head.S
arch/arm/kernel/hyp-stub.S [new file with mode: 0644]
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/suspend.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-davinci/include/mach/mux.h
arch/arm/mach-davinci/include/mach/psc.h
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mm/Kconfig
arch/arm/mm/cache-fa.S
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-mohawk.S
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
arch/arm/plat-nomadik/include/plat/pincfg.h
arch/arm/plat-samsung/setup-mipiphy.c
arch/ia64/Kconfig
arch/ia64/kernel/time.c
arch/powerpc/Kconfig
arch/powerpc/kernel/time.c
arch/s390/Kconfig
arch/s390/kernel/time.c
arch/x86/include/asm/vgtod.h
arch/x86/kernel/setup.c
arch/x86/kernel/vsyscall_64.c
arch/x86/vdso/vclock_gettime.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
drivers/media/dvb-core/dvb_frontend.c
drivers/media/dvb-core/dvb_frontend.h
drivers/media/dvb-frontends/a8293.c
drivers/media/dvb-frontends/af9013.c
drivers/media/dvb-frontends/af9033.c
drivers/media/dvb-frontends/bcm3510.c
drivers/media/dvb-frontends/cx24110.c
drivers/media/dvb-frontends/cxd2820r_core.c
drivers/media/dvb-frontends/drxd_hard.c
drivers/media/dvb-frontends/ds3000.c
drivers/media/dvb-frontends/dvb_dummy_fe.c
drivers/media/dvb-frontends/isl6405.c
drivers/media/dvb-frontends/isl6421.c
drivers/media/dvb-frontends/itd1000.c
drivers/media/dvb-frontends/lg2160.c
drivers/media/dvb-frontends/lnbp21.c
drivers/media/dvb-frontends/lnbp22.c
drivers/media/dvb-frontends/s5h1432.c
drivers/media/dvb-frontends/s921.c
drivers/media/dvb-frontends/si21xx.c
drivers/media/dvb-frontends/sp8870.c
drivers/media/dvb-frontends/sp887x.c
drivers/media/dvb-frontends/stb6100.c
drivers/media/dvb-frontends/stv0299.c
drivers/media/dvb-frontends/stv0900_core.c
drivers/media/dvb-frontends/tda665x.c
drivers/media/dvb-frontends/tda8083.c
drivers/media/i2c/cx25840/cx25840-core.c
drivers/media/i2c/m5mols/m5mols.h
drivers/media/i2c/m5mols/m5mols_capture.c
drivers/media/i2c/m5mols/m5mols_core.c
drivers/media/i2c/m5mols/m5mols_reg.h
drivers/media/i2c/mt9p031.c
drivers/media/i2c/mt9t001.c
drivers/media/i2c/mt9v032.c
drivers/media/i2c/soc_camera/ov2640.c
drivers/media/i2c/ths7303.c
drivers/media/i2c/tvp514x.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/bt8xx/bttvp.h
drivers/media/pci/bt8xx/dst_ca.c
drivers/media/pci/cx23885/altera-ci.c
drivers/media/pci/cx23885/cimax2.c
drivers/media/pci/cx23885/cx23885-cards.c
drivers/media/pci/cx23885/cx23885-video.c
drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
drivers/media/pci/cx25821/cx25821-video-upstream.c
drivers/media/pci/cx88/cx88-blackbird.c
drivers/media/pci/cx88/cx88-dvb.c
drivers/media/pci/cx88/cx88-mpeg.c
drivers/media/pci/cx88/cx88-tvaudio.c
drivers/media/pci/cx88/cx88-video.c
drivers/media/pci/saa7134/saa7134-video.c
drivers/media/platform/Kconfig
drivers/media/platform/davinci/vpbe.c
drivers/media/platform/davinci/vpbe_display.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_capture.h
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/davinci/vpif_display.h
drivers/media/platform/exynos-gsc/gsc-regs.c
drivers/media/platform/fsl-viu.c
drivers/media/platform/mem2mem_testdev.c
drivers/media/platform/omap3isp/ispreg.h
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-m2m.c
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-g2d/g2d.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-mfc/Makefile
drivers/media/platform/s5p-mfc/regs-mfc-v6.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/regs-mfc.h
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_common.h
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h [moved from drivers/media/platform/s5p-mfc/s5p_mfc_shm.h with 76% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
drivers/media/platform/s5p-mfc/s5p_mfc_shm.c [deleted file]
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/radio/si470x/radio-si470x-usb.c
drivers/media/radio/si4713-i2c.c
drivers/media/rc/ene_ir.c
drivers/media/rc/iguanair.c
drivers/media/rc/ir-lirc-codec.c
drivers/media/rc/keymaps/rc-msi-digivox-ii.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/redrat3.c
drivers/media/rc/winbond-cir.c
drivers/media/tuners/mt2063.c
drivers/media/tuners/mt2063.h
drivers/media/tuners/tda18271-common.c
drivers/media/usb/dvb-usb-v2/af9015.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb/a800.c
drivers/media/usb/dvb-usb/cinergyT2-core.c
drivers/media/usb/dvb-usb/dibusb-common.c
drivers/media/usb/dvb-usb/digitv.c
drivers/media/usb/dvb-usb/dtt200u.c
drivers/media/usb/dvb-usb/m920x.c
drivers/media/usb/dvb-usb/technisat-usb2.c
drivers/media/usb/em28xx/em28xx-cards.c
drivers/media/usb/em28xx/em28xx-dvb.c
drivers/media/usb/stk1160/stk1160-core.c
drivers/media/usb/stk1160/stk1160-v4l.c
drivers/media/usb/stk1160/stk1160.h
drivers/media/usb/uvc/uvc_queue.c
drivers/media/usb/uvc/uvc_video.c
drivers/media/usb/uvc/uvcvideo.h
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/pinctrl/pinctrl-nomadik-db8500.c
drivers/pinctrl/pinctrl-nomadik-db8540.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-nomadik.h
drivers/tty/hvc/hvc_xen.c
drivers/xen/xenbus/xenbus_xs.c
include/linux/alarmtimer.h
include/linux/clocksource.h
include/linux/dvb/version.h
include/linux/jiffies.h
include/linux/platform_data/mipi-csis.h
include/linux/timekeeper_internal.h [new file with mode: 0644]
include/linux/v4l2-controls.h
include/linux/v4l2-mediabus.h
include/linux/videodev2.h
include/media/davinci/vpbe.h
include/media/davinci/vpbe_types.h
include/media/davinci/vpbe_venc.h
include/media/davinci/vpif_types.h
include/media/s5p_fimc.h
include/media/v4l2-ctrls.h
include/media/v4l2-subdev.h
include/xen/interface/hvm/hvm_op.h
init/Kconfig
kernel/irq/irqdomain.c
kernel/rcutree.c
kernel/rcutree.h
kernel/sched/core.c
kernel/time.c
kernel/time/Kconfig
kernel/time/alarmtimer.c
kernel/time/jiffies.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/timer.c
mm/slab_common.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/usb/quirks-table.h

index c6ae4c9d0e0c6f0ae6f9661f916bb73e3d7fc89f..4fdf6b562d1cedb819c258f99820edfa4fafc7b3 100644 (file)
@@ -2582,6 +2582,10 @@ ioctls.</para>
         <listitem>
          <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
         </listitem>
+        <listitem>
+         <para>Vendor and device specific media bus pixel formats.
+           <xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
index 272a5f71850934e23a3c6e7ca7b5d8cc60b9784c..7fe5be1d3bbb14f58eb5ea60f32fa43b17bda894 100644 (file)
@@ -1586,7 +1586,6 @@ frame counter of the frame that is currently displayed (decoded). This value is
 the decoder is started.</entry>
              </row>
 
-
              <row><entry></entry></row>
              <row>
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE</constant>&nbsp;</entry>
@@ -2269,6 +2268,14 @@ encoder or editing process may produce.".
 Applicable to the MPEG1, MPEG2, MPEG4 encoders.</entry>
              </row>
 
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-vbv-delay">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VBV_DELAY</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Sets the initial delay in milliseconds for
+VBV buffer control.</entry>
+             </row>
+
              <row><entry></entry></row>
              <row>
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE</constant>&nbsp;</entry>
@@ -2334,6 +2341,265 @@ Applicable to the MPEG4 decoder.</entry>
              </row><row><entry spanname="descr">vop_time_increment value for MPEG4. Applicable to the MPEG4 encoder.</entry>
              </row>
 
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enable generation of frame packing supplemental enhancement information in the encoded bitstream.
+The frame packing SEI message contains the arrangement of L and R planes for 3D viewing. Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Sets current frame as frame0 in frame packing SEI.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-sei-fp-arrangement-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_sei_fp_arrangement_type</entry>
+             </row>
+             <row><entry spanname="descr">Frame packing arrangement type for H264 SEI.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHEKERBOARD</constant>&nbsp;</entry>
+                     <entry>Pixels are alternatively from L and R.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN</constant>&nbsp;</entry>
+                     <entry>L and R are interlaced by column.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW</constant>&nbsp;</entry>
+                     <entry>L and R are interlaced by row.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE</constant>&nbsp;</entry>
+                     <entry>L is on the left, R on the right.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM</constant>&nbsp;</entry>
+                     <entry>L is on top, R on bottom.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL</constant>&nbsp;</entry>
+                     <entry>One view per frame.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enables flexible macroblock ordering in the encoded bitstream. It is a technique
+used for restructuring the ordering of macroblocks in pictures. Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-fmo-map-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_fmo_map_type</entry>
+             </row>
+             <row><entry spanname="descr">When using FMO, the map type divides the image in different scan patterns of macroblocks.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES</constant>&nbsp;</entry>
+                     <entry>Slices are interleaved one after other with macroblocks in run length order.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES</constant>&nbsp;</entry>
+                     <entry>Scatters the macroblocks based on a mathematical function known to both encoder and decoder.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER</constant>&nbsp;</entry>
+                     <entry>Macroblocks arranged in rectangular areas or regions of interest.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT</constant>&nbsp;</entry>
+                     <entry>Slice groups grow in a cyclic way from centre to outwards.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN</constant>&nbsp;</entry>
+                     <entry>Slice groups grow in raster scan pattern from left to right.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN</constant>&nbsp;</entry>
+                     <entry>Slice groups grow in wipe scan pattern from top to bottom.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT</constant>&nbsp;</entry>
+                     <entry>User defined map type.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Number of slice groups in FMO.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-fmo-change-direction">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_fmo_change_dir</entry>
+             </row>
+             <row><entry spanname="descr">Specifies a direction of the slice group change for raster and wipe maps.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT</constant>&nbsp;</entry>
+                     <entry>Raster scan or wipe right.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT</constant>&nbsp;</entry>
+                     <entry>Reverse raster scan or wipe left.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the size of the first slice group for raster and wipe map.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the number of consecutive macroblocks for the interleaved map.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enables arbitrary slice ordering in encoded bitstream.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Specifies the slice order in ASO. Applicable to the H264 encoder.
+The supplied 32-bit integer is interpreted as follows (bit
+0 = least significant bit):</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry>Bit 0:15</entry>
+                     <entry>Slice ID</entry>
+                   </row>
+                   <row>
+                     <entry>Bit 16:32</entry>
+                     <entry>Slice position or order</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enables H264 hierarchical coding.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-hierarchical-coding-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_hierarchical_coding_type</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the hierarchical coding type.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B</constant>&nbsp;</entry>
+                     <entry>Hierarchical B coding.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P</constant>&nbsp;</entry>
+                     <entry>Hierarchical P coding.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the number of hierarchical coding layers.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Specifies a user defined QP for each layer. Applicable to the H264 encoder.
+The supplied 32-bit integer is interpreted as follows (bit
+0 = least significant bit):</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry>Bit 0:15</entry>
+                     <entry>QP value</entry>
+                   </row>
+                   <row>
+                     <entry>Bit 16:32</entry>
+                     <entry>Layer number</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
            </tbody>
          </tgroup>
        </table>
@@ -4267,6 +4533,16 @@ interface and may change in the future.</para>
            pixels / second.
            </entry>
          </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN</constant></entry>
+           <entry>menu</entry>
+         </row>
+         <row id="v4l2-test-pattern">
+           <entry spanname="descr"> Some capture/display/sensor devices have
+           the capability to generate test pattern images. These hardware
+           specific test patterns can be used to test if a device is working
+           properly.</entry>
+         </row>
          <row><entry></entry></row>
        </tbody>
       </tgroup>
index 97f785add841c602d179a2b131060994deeaa26d..b5d1cbdc558bdfa5cfbd6e451425dabc5456b0ce 100644 (file)
@@ -677,8 +677,10 @@ memory, set by the application. See <xref linkend="userp" /> for details.
            <entry><structfield>length</structfield></entry>
            <entry></entry>
            <entry>Size of the buffer (not the payload) in bytes for the
-           single-planar API. For the multi-planar API should contain the
-           number of elements in the <structfield>planes</structfield> array.
+           single-planar API. For the multi-planar API the application sets
+           this to the number of elements in the <structfield>planes</structfield>
+           array. The driver will fill in the actual number of valid elements in
+           that array.
            </entry>
          </row>
          <row>
index 5274c24d11e0a94ce55a05d166580f5cda50196f..a990b34d911a123f775f20001f9e9629947276b2 100644 (file)
@@ -1,11 +1,13 @@
-    <refentry id="V4L2-PIX-FMT-NV12M">
+    <refentry>
       <refmeta>
-       <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12')</refentrytitle>
+       <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12'), V4L2_PIX_FMT_NV21M ('NM21'), V4L2_PIX_FMT_NV12MT_16X16</refentrytitle>
        &manvol;
       </refmeta>
       <refnamediv>
-       <refname> <constant>V4L2_PIX_FMT_NV12M</constant></refname>
-       <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> with planes
+       <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>
+       <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> and <constant>V4L2_PIX_FMT_NV21</constant> with planes
          non contiguous in memory. </refpurpose>
       </refnamediv>
       <refsect1>
@@ -22,7 +24,12 @@ The CbCr plane is the same width, in bytes, as the Y plane (and of the image),
 but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example,
 Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
 Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
-Y'<subscript>10</subscript>, Y'<subscript>11</subscript>. </para>
+Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
+<constant>V4L2_PIX_FMT_NV12MT_16X16</constant> is the tiled version of
+<constant>V4L2_PIX_FMT_NV12M</constant> with 16x16 macroblock tiles. Here pixels
+are arranged in 16x16 2D tiles and tiles are arranged in linear order in memory.
+<constant>V4L2_PIX_FMT_NV21M</constant> is the same as <constant>V4L2_PIX_FMT_NV12M</constant>
+except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
 
        <para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
 used only in drivers and applications that support the multi-planar API,
index 1ddbfabe31953b34fa8f51a8dc7c515daca39a06..bf94f417592cac290670f4e65ace3a54fc1eb173 100644 (file)
@@ -758,6 +758,11 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
                <entry>'AVC1'</entry>
                <entry>H264 video elementary stream without start codes.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-H264-MVC">
+               <entry><constant>V4L2_PIX_FMT_H264_MVC</constant></entry>
+               <entry>'MVC'</entry>
+               <entry>H264 MVC video elementary stream.</entry>
+         </row>
          <row id="V4L2-PIX-FMT-H263">
                <entry><constant>V4L2_PIX_FMT_H263</constant></entry>
                <entry>'H263'</entry>
@@ -793,6 +798,11 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
                <entry>'VC1L'</entry>
                <entry>VC1, SMPTE 421M Annex L compliant stream.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-VP8">
+               <entry><constant>V4L2_PIX_FMT_VP8</constant></entry>
+               <entry>'VP8'</entry>
+               <entry>VP8 video elementary stream.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
@@ -996,6 +1006,34 @@ the other bits are set to 0.</entry>
            <entry>Old 6-bit greyscale format. Only the most significant 6 bits of each byte are used,
 the other bits are set to 0.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-S5C-UYVY-JPG">
+           <entry><constant>V4L2_PIX_FMT_S5C_UYVY_JPG</constant></entry>
+           <entry>'S5CI'</entry>
+           <entry>Two-planar format used by Samsung S5C73MX cameras. The
+first plane contains interleaved JPEG and UYVY image data, followed by meta data
+in form of an array of offsets to the UYVY data blocks. The actual pointer array
+follows immediately the interleaved JPEG/UYVY data, the number of entries in
+this array equals the height of the UYVY image. Each entry is a 4-byte unsigned
+integer in big endian order and it's an offset to a single pixel line of the
+UYVY image. The first plane can start either with JPEG or UYVY data chunk. The
+size of a single UYVY block equals the UYVY image's width multiplied by 2. The
+size of a JPEG chunk depends on the image and can vary with each line.
+<para>The second plane, at an offset of 4084 bytes, contains a 4-byte offset to
+the pointer array in the first plane. This offset is followed by a 4-byte value
+indicating size of the pointer array. All numbers in the second plane are also
+in big endian order. Remaining data in the second plane is undefined. The
+information in the second plane allows to easily find location of the pointer
+array, which can be different for each frame. The size of the pointer array is
+constant for given UYVY image height.</para>
+<para>In order to extract UYVY and JPEG frames an application can initially set
+a data pointer to the start of first plane and then add an offset from the first
+entry of the pointers table. Such a pointer indicates start of an UYVY image
+pixel line. Whole UYVY line can be copied to a separate buffer. These steps
+should be repeated for each line, i.e. the number of entries in the pointer
+array. Anything what's in between the UYVY lines is JPEG data and should be
+concatenated to form the JPEG stream. </para>
+</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 49c532ebbbbefe3a6aac004dd4192936ec14e880..a0a936455faef1c68d59f5997b8697b7ad1e2d65 100644 (file)
        </tgroup>
       </table>
     </section>
+
+    <section id="v4l2-mbus-vendor-spec-fmts">
+      <title>Vendor and Device Specific Formats</title>
+
+      <note>
+       <title>Experimental</title>
+       <para>This is an <link linkend="experimental">experimental</link>
+interface and may change in the future.</para>
+      </note>
+
+      <para>This section lists complex data formats that are either vendor or
+       device specific.
+      </para>
+
+      <para>The following table lists the existing vendor and device specific
+       formats.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-vendor-specific">
+       <title>Vendor and device specific formats</title>
+       <tgroup cols="3">
+         <colspec colname="id" align="left" />
+         <colspec colname="code" align="left"/>
+         <colspec colname="remarks" align="left"/>
+         <thead>
+           <row>
+             <entry>Identifier</entry>
+             <entry>Code</entry>
+             <entry>Comments</entry>
+           </row>
+         </thead>
+         <tbody valign="top">
+           <row id="V4L2-MBUS-FMT-S5C-UYVY-JPEG-1X8">
+             <entry>V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8</entry>
+             <entry>0x5001</entry>
+             <entry>
+               Interleaved raw UYVY and JPEG image format with embedded
+               meta-data used by Samsung S3C73MX camera sensors.
+             </entry>
+           </row>
+         </tbody>
+       </tgroup>
+      </table>
+    </section>
+
   </section>
 </section>
index 6a821a65a5aec9ce1e196261c5149b666f2e4c2e..2d37abefce13e90144941af12cc2baa71f78a700 100644 (file)
@@ -121,8 +121,7 @@ remaining fields or returns an error code. The driver may also set
 field. It indicates a non-critical (recoverable) streaming error. In such case
 the application may continue as normal, but should be aware that data in the
 dequeued buffer might be corrupted. When using the multi-planar API, the
-planes array does not have to be passed; the <structfield>m.planes</structfield>
-member must be set to NULL in that case.</para>
+planes array must be passed in as well.</para>
 
     <para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
 buffer is in the outgoing queue. When the
index 6e414d7b6df759f83f45ad34256c5ace012a6543..a597155c052d723b7b5c5867f67c564dd2eacebe 100644 (file)
@@ -48,8 +48,8 @@
   <refsect1>
     <title>Description</title>
 
-    <para>This ioctl is part of the <link linkend="mmap">memory
-mapping</link> I/O method. It can be used to query the status of a
+    <para>This ioctl is part of the <link linkend="mmap">streaming
+</link> I/O method. It can be used to query the status of a
 buffer at any time after buffers have been allocated with the
 &VIDIOC-REQBUFS; ioctl.</para>
 
@@ -71,6 +71,7 @@ the structure.</para>
 
     <para>In the <structfield>flags</structfield> field the
 <constant>V4L2_BUF_FLAG_MAPPED</constant>,
+<constant>V4L2_BUF_FLAG_PREPARED</constant>,
 <constant>V4L2_BUF_FLAG_QUEUED</constant> and
 <constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
 <structfield>memory</structfield> field will be set to the current
@@ -79,8 +80,10 @@ contains the offset of the buffer from the start of the device memory,
 the <structfield>length</structfield> field its size. For the multi-planar API,
 fields <structfield>m.mem_offset</structfield> and
 <structfield>length</structfield> in the <structfield>m.planes</structfield>
-array elements will be used instead. The driver may or may not set the remaining
-fields and flags, they are meaningless in this context.</para>
+array elements will be used instead and the <structfield>length</structfield>
+field of &v4l2-buffer; is set to the number of filled-in array elements.
+The driver may or may not set the remaining fields and flags, they are
+meaningless in this context.</para>
 
     <para>The <structname>v4l2_buffer</structname> structure is
     specified in <xref linkend="buffer" />.</para>
index a341d87d276eb1bf3904aec38896f87174b36561..0c1f475fdf36e140d28bcdc26d880546f8a8bdc4 100644 (file)
@@ -154,13 +154,33 @@ In either case, the following conditions must be met:
 
 - CPU mode
   All forms of interrupts must be disabled (IRQs and FIQs)
-  The CPU must be in SVC mode.  (A special exception exists for Angel)
+
+  For CPUs which do not include the ARM virtualization extensions, the
+  CPU must be in SVC mode.  (A special exception exists for Angel)
+
+  CPUs which include support for the virtualization extensions can be
+  entered in HYP mode in order to enable the kernel to make full use of
+  these extensions.  This is the recommended boot method for such CPUs,
+  unless the virtualisations are already in use by a pre-installed
+  hypervisor.
+
+  If the kernel is not entered in HYP mode for any reason, it must be
+  entered in SVC mode.
 
 - Caches, MMUs
   The MMU must be off.
   Instruction cache may be on or off.
   Data cache must be off.
 
+  If the kernel is entered in HYP mode, the above requirements apply to
+  the HYP mode configuration in addition to the ordinary PL1 (privileged
+  kernel modes) configuration.  In addition, all traps into the
+  hypervisor must be disabled, and PL1 access must be granted for all
+  peripherals and CPU resources for which this is architecturally
+  possible.  Except for entering in HYP mode, the system configuration
+  should be such that a kernel which does not include support for the
+  virtualization extensions can boot correctly without extra help.
+
 - The boot loader is expected to call the kernel image by jumping
   directly to the first instruction of the kernel image.
 
index 54270df99d5c2f1794c4fcd537eec05fd525d031..cfe52c798d743b0979a31c414948a5c72c491e46 100644 (file)
@@ -136,11 +136,25 @@ Or alternatively for integer menu controls, by calling v4l2_ctrl_new_int_menu:
                        const struct v4l2_ctrl_ops *ops,
                        u32 id, s32 max, s32 def, const s64 *qmenu_int);
 
+Standard menu controls with a driver specific menu are added by calling
+v4l2_ctrl_new_std_menu_items:
+
+       struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
+               struct v4l2_ctrl_handler *hdl,
+               const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
+               s32 skip_mask, s32 def, const char * const *qmenu);
+
 These functions are typically called right after the v4l2_ctrl_handler_init:
 
        static const s64 exp_bias_qmenu[] = {
               -2, -1, 0, 1, 2
        };
+       static const char * const test_pattern[] = {
+               "Disabled",
+               "Vertical Bars",
+               "Solid Black",
+               "Solid White",
+       };
 
        v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
        v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
@@ -156,6 +170,9 @@ These functions are typically called right after the v4l2_ctrl_handler_init:
                        ARRAY_SIZE(exp_bias_qmenu) - 1,
                        ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,
                        exp_bias_qmenu);
+       v4l2_ctrl_new_std_menu_items(&foo->ctrl_handler, &foo_ctrl_ops,
+                       V4L2_CID_TEST_PATTERN, ARRAY_SIZE(test_pattern) - 1, 0,
+                       0, test_pattern);
        ...
        if (foo->ctrl_handler.error) {
                int err = foo->ctrl_handler.error;
@@ -185,6 +202,13 @@ v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and takes
 as the last argument an array of signed 64-bit integers that form an exact
 menu item list.
 
+The v4l2_ctrl_new_std_menu_items function is very similar to
+v4l2_ctrl_new_std_menu but takes an extra parameter qmenu, which is the driver
+specific menu for an otherwise standard menu control. A good example for this
+control is the test pattern control for capture/display/sensors devices that
+have the capability to generate test patterns. These test patterns are hardware
+specific, so the contents of the menu will vary from device to device.
+
 Note that if something fails, the function will return NULL or an error and
 set ctrl_handler->error to the error code. If ctrl_handler->error was already
 set, then it will just return and do nothing. This is also true for
index d0d441c429ae3e4e6c438fad1c51c7079c6eda5b..f79a08efe000aa490c1c010715cd0147baa869c0 100644 (file)
@@ -1,6 +1,7 @@
 ashldi3.S
 font.c
 lib1funcs.S
+hyp-stub.S
 piggy.gzip
 piggy.lzo
 piggy.lzma
index bb267562e7ed9a763218c83eaeb2c5c8645debb9..a517153a13eabdad582b6b6f75080cf93f699595 100644 (file)
@@ -30,6 +30,10 @@ FONTC        = $(srctree)/drivers/video/console/font_acorn_8x8.c
 OBJS           += string.o
 CFLAGS_string.o        := -Os
 
+ifeq ($(CONFIG_ARM_VIRT_EXT),y)
+OBJS           += hyp-stub.o
+endif
+
 #
 # Architecture dependencies
 #
@@ -126,7 +130,7 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
 ccflags-y := -fpic -fno-builtin -I$(obj)
-asflags-y := -Wa,-march=all
+asflags-y := -Wa,-march=all -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
 KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \
@@ -198,3 +202,6 @@ $(obj)/font.c: $(FONTC)
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
        @sed "$(SEDFLAGS)" < $< > $@
+
+$(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
+       $(call cmd,shipped)
index bc67cbff39448ff84a3f0c14cd22876975ee1965..90275f036cd14517affdb724ea4c6adf5194b72c 100644 (file)
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 /*
  * Debugging stuff
@@ -132,7 +133,12 @@ start:
                .word   start                   @ absolute load/run zImage address
                .word   _edata                  @ zImage end address
  THUMB(                .thumb                  )
-1:             mov     r7, r1                  @ save architecture ID
+1:
+               mrs     r9, cpsr
+#ifdef CONFIG_ARM_VIRT_EXT
+               bl      __hyp_stub_install      @ get into SVC mode, reversibly
+#endif
+               mov     r7, r1                  @ save architecture ID
                mov     r8, r2                  @ save atags pointer
 
 #ifndef __ARM_ARCH_2__
@@ -148,9 +154,9 @@ start:
  ARM(          swi     0x123456        )       @ angel_SWI_ARM
  THUMB(                svc     0xab            )       @ angel_SWI_THUMB
 not_angel:
-               mrs     r2, cpsr                @ turn off interrupts to
-               orr     r2, r2, #0xc0           @ prevent angel from running
-               msr     cpsr_c, r2
+               safe_svcmode_maskall r0
+               msr     spsr_cxsf, r9           @ Save the CPU boot mode in
+                                               @ SPSR
 #else
                teqp    pc, #0x0c000003         @ turn off interrupts
 #endif
@@ -350,6 +356,20 @@ dtb_check_done:
                adr     r5, restart
                bic     r5, r5, #31
 
+/* Relocate the hyp vector base if necessary */
+#ifdef CONFIG_ARM_VIRT_EXT
+               mrs     r0, spsr
+               and     r0, r0, #MODE_MASK
+               cmp     r0, #HYP_MODE
+               bne     1f
+
+               bl      __hyp_get_vectors
+               sub     r0, r0, r5
+               add     r0, r0, r10
+               bl      __hyp_set_vectors
+1:
+#endif
+
                sub     r9, r6, r5              @ size to copy
                add     r9, r9, #31             @ rounded up to a multiple
                bic     r9, r9, #31             @ ... of 32 bytes
@@ -458,11 +478,29 @@ not_relocated:    mov     r0, #0
                bl      decompress_kernel
                bl      cache_clean_flush
                bl      cache_off
-               mov     r0, #0                  @ must be zero
                mov     r1, r7                  @ restore architecture number
                mov     r2, r8                  @ restore atags pointer
- ARM(          mov     pc, r4  )               @ call kernel
- THUMB(                bx      r4      )               @ entry point is always ARM
+
+#ifdef CONFIG_ARM_VIRT_EXT
+               mrs     r0, spsr                @ Get saved CPU boot mode
+               and     r0, r0, #MODE_MASK
+               cmp     r0, #HYP_MODE           @ if not booted in HYP mode...
+               bne     __enter_kernel          @ boot kernel directly
+
+               adr     r12, .L__hyp_reentry_vectors_offset
+               ldr     r0, [r12]
+               add     r0, r0, r12
+
+               bl      __hyp_set_vectors
+               __HVC(0)                        @ otherwise bounce to hyp mode
+
+               b       .                       @ should never be reached
+
+               .align  2
+.L__hyp_reentry_vectors_offset:        .long   __hyp_reentry_vectors - .
+#else
+               b       __enter_kernel
+#endif
 
                .align  2
                .type   LC0, #object
@@ -1196,6 +1234,25 @@ memdump: mov     r12, r0
 #endif
 
                .ltorg
+
+#ifdef CONFIG_ARM_VIRT_EXT
+.align 5
+__hyp_reentry_vectors:
+               W(b)    .                       @ reset
+               W(b)    .                       @ undef
+               W(b)    .                       @ svc
+               W(b)    .                       @ pabort
+               W(b)    .                       @ dabort
+               W(b)    __enter_kernel          @ hyp
+               W(b)    .                       @ irq
+               W(b)    .                       @ fiq
+#endif /* CONFIG_ARM_VIRT_EXT */
+
+__enter_kernel:
+               mov     r0, #0                  @ must be 0
+ ARM(          mov     pc, r4  )               @ call kernel
+ THUMB(                bx      r4      )               @ entry point is always ARM
+
 reloc_code_end:
 
                .align
index 5c8b3bf4d8252f1013af6fea25848ce9c41dcfeb..2ef95813fce00b887dbd05020b35675870a7c929 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/domain.h>
+#include <asm/opcodes-virt.h>
 
 #define IOMEM(x)       (x)
 
        .endm
 #endif
 
+/*
+ * Helper macro to enter SVC mode cleanly and mask interrupts. reg is
+ * a scratch register for the macro to overwrite.
+ *
+ * This macro is intended for forcing the CPU into SVC mode at boot time.
+ * you cannot return to the original mode.
+ *
+ * Beware, it also clobers LR.
+ */
+.macro safe_svcmode_maskall reg:req
+       mrs     \reg , cpsr
+       mov     lr , \reg
+       and     lr , lr , #MODE_MASK
+       cmp     lr , #HYP_MODE
+       orr     \reg , \reg , #PSR_I_BIT | PSR_F_BIT
+       bic     \reg , \reg , #MODE_MASK
+       orr     \reg , \reg , #SVC_MODE
+THUMB( orr     \reg , \reg , #PSR_T_BIT        )
+       bne     1f
+       orr     \reg, \reg, #PSR_A_BIT
+       adr     lr, BSYM(2f)
+       msr     spsr_cxsf, \reg
+       __MSR_ELR_HYP(14)
+       __ERET
+1:     msr     cpsr_c, \reg
+2:
+.endm
+
 /*
  * STRT/LDRT access macros with ARM and Thumb-2 variants
  */
index e4448e16046dd32ab69ca17ef65a6b21745a3e0b..e1489c54cd12b4dcb8b997e8e327e2875b183b0c 100644 (file)
  *
  *             Unconditionally clean and invalidate the entire cache.
  *
+ *     flush_kern_louis()
+ *
+ *             Flush data cache levels up to the level of unification
+ *             inner shareable and invalidate the I-cache.
+ *             Only needed from v7 onwards, falls back to flush_cache_all()
+ *             for all other processor versions.
+ *
  *     flush_user_all()
  *
  *             Clean and invalidate all user space cache entries
 struct cpu_cache_fns {
        void (*flush_icache_all)(void);
        void (*flush_kern_all)(void);
+       void (*flush_kern_louis)(void);
        void (*flush_user_all)(void);
        void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
 
@@ -119,6 +127,7 @@ extern struct cpu_cache_fns cpu_cache;
 
 #define __cpuc_flush_icache_all                cpu_cache.flush_icache_all
 #define __cpuc_flush_kern_all          cpu_cache.flush_kern_all
+#define __cpuc_flush_kern_louis                cpu_cache.flush_kern_louis
 #define __cpuc_flush_user_all          cpu_cache.flush_user_all
 #define __cpuc_flush_user_range                cpu_cache.flush_user_range
 #define __cpuc_coherent_kern_range     cpu_cache.coherent_kern_range
@@ -139,6 +148,7 @@ extern struct cpu_cache_fns cpu_cache;
 
 extern void __cpuc_flush_icache_all(void);
 extern void __cpuc_flush_kern_all(void);
+extern void __cpuc_flush_kern_louis(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
@@ -204,6 +214,11 @@ static inline void __flush_icache_all(void)
        __flush_icache_preferred();
 }
 
+/*
+ * Flush caches up to Level of Unification Inner Shareable
+ */
+#define flush_cache_louis()            __cpuc_flush_kern_louis()
+
 #define flush_cache_all()              __cpuc_flush_kern_all()
 
 static inline void vivt_flush_cache_mm(struct mm_struct *mm)
index 4f8d2c0dc4419f702449132e46ae7f89bcf2865a..cca9f15704ed82bb2726ce8898611be42d28b5ff 100644 (file)
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all                __glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all          __glue(_CACHE,_flush_kern_cache_all)
+#define __cpuc_flush_kern_louis                __glue(_CACHE,_flush_kern_cache_louis)
 #define __cpuc_flush_user_all          __glue(_CACHE,_flush_user_cache_all)
 #define __cpuc_flush_user_range                __glue(_CACHE,_flush_user_cache_range)
 #define __cpuc_coherent_kern_range     __glue(_CACHE,_coherent_kern_range)
index b85665a96f8e329e2dc2494da1afb831f80f07e4..efcfdf92d9d5991ac618bf2ae608be27c44dc493 100644 (file)
        0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF)     \
 )
 
+#define __ERET __inst_arm_thumb32(                                     \
+       0xE160006E,                                                     \
+       0xF3DE8F00                                                      \
+)
+
+#define __MSR_ELR_HYP(regnum)  __inst_arm_thumb32(                     \
+       0xE12EF300 | regnum,                                            \
+       0xF3808E30 | (regnum << 16)                                     \
+)
+
 #endif /* ! __ASM_ARM_OPCODES_VIRT_H */
index 44fe998269d9d4288c9e542543ff12290a589087..142d6ae4123150453d99aa9566767555afaa76f4 100644 (file)
@@ -44,6 +44,7 @@
 #define IRQ_MODE       0x00000012
 #define SVC_MODE       0x00000013
 #define ABT_MODE       0x00000017
+#define HYP_MODE       0x0000001a
 #define UND_MODE       0x0000001b
 #define SYSTEM_MODE    0x0000001f
 #define MODE32_BIT     0x00000010
index a7aadbd9a6dd2a1cbe18de85d6998c0ce0d8f53f..6a6f1e485f41a2b9402534c435b79c183cb5cdb2 100644 (file)
@@ -28,7 +28,7 @@
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
        tst     \tmp, #HWCAP_VFPv3D16
-       ldceq   p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
+       ldceql  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
        addne   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
@@ -52,7 +52,7 @@
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
        tst     \tmp, #HWCAP_VFPv3D16
-       stceq   p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
+       stceql  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
        addne   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
new file mode 100644 (file)
index 0000000..86164df
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 Linaro Limited.
+ *
+ * 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.
+ */
+
+#ifndef VIRT_H
+#define VIRT_H
+
+#include <asm/ptrace.h>
+
+/*
+ * Flag indicating that the kernel was not entered in the same mode on every
+ * CPU.  The zImage loader stashes this value in an SPSR, so we need an
+ * architecturally defined flag bit here (the N flag, as it happens)
+ */
+#define BOOT_CPU_MODE_MISMATCH (1<<31)
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_ARM_VIRT_EXT
+/*
+ * __boot_cpu_mode records what mode the primary CPU was booted in.
+ * A correctly-implemented bootloader must start all CPUs in the same mode:
+ * if it fails to do this, the flag BOOT_CPU_MODE_MISMATCH is set to indicate
+ * that some CPU(s) were booted in a different mode.
+ *
+ * This allows the kernel to flag an error when the secondaries have come up.
+ */
+extern int __boot_cpu_mode;
+
+void __hyp_set_vectors(unsigned long phys_vector_base);
+unsigned long __hyp_get_vectors(void);
+#else
+#define __boot_cpu_mode        (SVC_MODE)
+#endif
+
+#ifndef ZIMAGE
+void hyp_mode_check(void);
+
+/* Reports the availability of HYP mode */
+static inline bool is_hyp_mode_available(void)
+{
+       return ((__boot_cpu_mode & MODE_MASK) == HYP_MODE &&
+               !(__boot_cpu_mode & BOOT_CPU_MODE_MISMATCH));
+}
+
+/* Check if the bootloader has booted CPUs in different modes */
+static inline bool is_hyp_mode_mismatched(void)
+{
+       return !!(__boot_cpu_mode & BOOT_CPU_MODE_MISMATCH);
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* ! VIRT_H */
index 5dfef9d97ed92b960d8d359997a20108759d60c8..5bbec7b8183e46e0d5ba4f078ba146789f409be1 100644 (file)
@@ -81,4 +81,6 @@ head-y                        := head$(MMUEXT).o
 obj-$(CONFIG_DEBUG_LL) += debug.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
+obj-$(CONFIG_ARM_VIRT_EXT)     += hyp-stub.o
+
 extra-y := $(head-y) vmlinux.lds
index 9874d074119118f1d42abeee662beaa3433ca052..4eee351f4668e2bbee54c3771a5389ce8900c10c 100644 (file)
@@ -83,8 +83,12 @@ ENTRY(stext)
  THUMB(        .thumb                  )       @ switch to Thumb now.
  THUMB(1:                      )
 
-       setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
-                                               @ and irqs disabled
+#ifdef CONFIG_ARM_VIRT_EXT
+       bl      __hyp_stub_install
+#endif
+       @ ensure svc mode and all interrupts masked
+       safe_svcmode_maskall r9
+
        mrc     p15, 0, r9, c0, c0              @ get processor id
        bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
        movs    r10, r5                         @ invalid processor (r5=0)?
@@ -326,7 +330,11 @@ ENTRY(secondary_startup)
         * the processor type - there is no need to check the machine type
         * as it has already been validated by the primary processor.
         */
-       setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
+#ifdef CONFIG_ARM_VIRT_EXT
+       bl      __hyp_stub_install
+#endif
+       safe_svcmode_maskall r9
+
        mrc     p15, 0, r9, c0, c0              @ get processor id
        bl      __lookup_processor_type
        movs    r10, r5                         @ invalid processor?
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
new file mode 100644 (file)
index 0000000..65b2417
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012 Linaro Limited.
+ *
+ * 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 <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/virt.h>
+
+#ifndef ZIMAGE
+/*
+ * For the kernel proper, we need to find out the CPU boot mode long after
+ * boot, so we need to store it in a writable variable.
+ *
+ * This is not in .bss, because we set it sufficiently early that the boot-time
+ * zeroing of .bss would clobber it.
+ */
+.data
+ENTRY(__boot_cpu_mode)
+       .long   0
+.text
+
+       /*
+        * Save the primary CPU boot mode. Requires 3 scratch registers.
+        */
+       .macro  store_primary_cpu_mode  reg1, reg2, reg3
+       mrs     \reg1, cpsr
+       and     \reg1, \reg1, #MODE_MASK
+       adr     \reg2, .L__boot_cpu_mode_offset
+       ldr     \reg3, [\reg2]
+       str     \reg1, [\reg2, \reg3]
+       .endm
+
+       /*
+        * Compare the current mode with the one saved on the primary CPU.
+        * If they don't match, record that fact. The Z bit indicates
+        * if there's a match or not.
+        * Requires 3 additionnal scratch registers.
+        */
+       .macro  compare_cpu_mode_with_primary mode, reg1, reg2, reg3
+       adr     \reg2, .L__boot_cpu_mode_offset
+       ldr     \reg3, [\reg2]
+       ldr     \reg1, [\reg2, \reg3]
+       cmp     \mode, \reg1            @ matches primary CPU boot mode?
+       orrne   r7, r7, #BOOT_CPU_MODE_MISMATCH
+       strne   r7, [r5, r6]            @ record what happened and give up
+       .endm
+
+#else  /* ZIMAGE */
+
+       .macro  store_primary_cpu_mode  reg1:req, reg2:req, reg3:req
+       .endm
+
+/*
+ * The zImage loader only runs on one CPU, so we don't bother with mult-CPU
+ * consistency checking:
+ */
+       .macro  compare_cpu_mode_with_primary mode, reg1, reg2, reg3
+       cmp     \mode, \mode
+       .endm
+
+#endif /* ZIMAGE */
+
+/*
+ * Hypervisor stub installation functions.
+ *
+ * These must be called with the MMU and D-cache off.
+ * They are not ABI compliant and are only intended to be called from the kernel
+ * entry points in head.S.
+ */
+@ Call this from the primary CPU
+ENTRY(__hyp_stub_install)
+       store_primary_cpu_mode  r4, r5, r6
+ENDPROC(__hyp_stub_install)
+
+       @ fall through...
+
+@ Secondary CPUs should call here
+ENTRY(__hyp_stub_install_secondary)
+       mrs     r4, cpsr
+       and     r4, r4, #MODE_MASK
+
+       /*
+        * If the secondary has booted with a different mode, give up
+        * immediately.
+        */
+       compare_cpu_mode_with_primary   r4, r5, r6, r7
+       bxne    lr
+
+       /*
+        * Once we have given up on one CPU, we do not try to install the
+        * stub hypervisor on the remaining ones: because the saved boot mode
+        * is modified, it can't compare equal to the CPSR mode field any
+        * more.
+        *
+        * Otherwise...
+        */
+
+       cmp     r4, #HYP_MODE
+       bxne    lr                      @ give up if the CPU is not in HYP mode
+
+/*
+ * Configure HSCTLR to set correct exception endianness/instruction set
+ * state etc.
+ * Turn off all traps
+ * Eventually, CPU-specific code might be needed -- assume not for now
+ *
+ * This code relies on the "eret" instruction to synchronize the
+ * various coprocessor accesses.
+ */
+       @ Now install the hypervisor stub:
+       adr     r7, __hyp_stub_vectors
+       mcr     p15, 4, r7, c12, c0, 0  @ set hypervisor vector base (HVBAR)
+
+       @ Disable all traps, so we don't get any nasty surprise
+       mov     r7, #0
+       mcr     p15, 4, r7, c1, c1, 0   @ HCR
+       mcr     p15, 4, r7, c1, c1, 2   @ HCPTR
+       mcr     p15, 4, r7, c1, c1, 3   @ HSTR
+
+THUMB( orr     r7, #(1 << 30)  )       @ HSCTLR.TE
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       orr     r7, #(1 << 9)           @ HSCTLR.EE
+#endif
+       mcr     p15, 4, r7, c1, c0, 0   @ HSCTLR
+
+       mrc     p15, 4, r7, c1, c1, 1   @ HDCR
+       and     r7, #0x1f               @ Preserve HPMN
+       mcr     p15, 4, r7, c1, c1, 1   @ HDCR
+
+#if !defined(ZIMAGE) && defined(CONFIG_ARM_ARCH_TIMER)
+       @ make CNTP_* and CNTPCT accessible from PL1
+       mrc     p15, 0, r7, c0, c1, 1   @ ID_PFR1
+       lsr     r7, #16
+       and     r7, #0xf
+       cmp     r7, #1
+       bne     1f
+       mrc     p15, 4, r7, c14, c1, 0  @ CNTHCTL
+       orr     r7, r7, #3              @ PL1PCEN | PL1PCTEN
+       mcr     p15, 4, r7, c14, c1, 0  @ CNTHCTL
+1:
+#endif
+
+       bic     r7, r4, #MODE_MASK
+       orr     r7, r7, #SVC_MODE
+THUMB( orr     r7, r7, #PSR_T_BIT      )
+       msr     spsr_cxsf, r7           @ This is SPSR_hyp.
+
+       __MSR_ELR_HYP(14)               @ msr elr_hyp, lr
+       __ERET                          @ return, switching to SVC mode
+                                       @ The boot CPU mode is left in r4.
+ENDPROC(__hyp_stub_install_secondary)
+
+__hyp_stub_do_trap:
+       cmp     r0, #-1
+       mrceq   p15, 4, r0, c12, c0, 0  @ get HVBAR
+       mcrne   p15, 4, r0, c12, c0, 0  @ set HVBAR
+       __ERET
+ENDPROC(__hyp_stub_do_trap)
+
+/*
+ * __hyp_set_vectors: Call this after boot to set the initial hypervisor
+ * vectors as part of hypervisor installation.  On an SMP system, this should
+ * be called on each CPU.
+ *
+ * r0 must be the physical address of the new vector table (which must lie in
+ * the bottom 4GB of physical address space.
+ *
+ * r0 must be 32-byte aligned.
+ *
+ * Before calling this, you must check that the stub hypervisor is installed
+ * everywhere, by waiting for any secondary CPUs to be brought up and then
+ * checking that BOOT_CPU_MODE_HAVE_HYP(__boot_cpu_mode) is true.
+ *
+ * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or
+ * something else went wrong... in such cases, trying to install a new
+ * hypervisor is unlikely to work as desired.
+ *
+ * When you call into your shiny new hypervisor, sp_hyp will contain junk,
+ * so you will need to set that to something sensible at the new hypervisor's
+ * initialisation entry point.
+ */
+ENTRY(__hyp_get_vectors)
+       mov     r0, #-1
+ENDPROC(__hyp_get_vectors)
+       @ fall through
+ENTRY(__hyp_set_vectors)
+       __HVC(0)
+       bx      lr
+ENDPROC(__hyp_set_vectors)
+
+#ifndef ZIMAGE
+.align 2
+.L__boot_cpu_mode_offset:
+       .long   __boot_cpu_mode - .
+#endif
+
+.align 5
+__hyp_stub_vectors:
+__hyp_stub_reset:      W(b)    .
+__hyp_stub_und:                W(b)    .
+__hyp_stub_svc:                W(b)    .
+__hyp_stub_pabort:     W(b)    .
+__hyp_stub_dabort:     W(b)    .
+__hyp_stub_trap:       W(b)    __hyp_stub_do_trap
+__hyp_stub_irq:                W(b)    .
+__hyp_stub_fiq:                W(b)    .
+ENDPROC(__hyp_stub_vectors)
+
index febafa0f552d6a75e2bc51755054a8b6e68cf5a8..da1d1aa20ad957ccd7021815014d12530de4f3a1 100644 (file)
@@ -53,6 +53,7 @@
 #include <asm/traps.h>
 #include <asm/unwind.h>
 #include <asm/memblock.h>
+#include <asm/virt.h>
 
 #include "atags.h"
 #include "tcm.h"
@@ -703,6 +704,21 @@ static int __init meminfo_cmp(const void *_a, const void *_b)
        return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
 }
 
+void __init hyp_mode_check(void)
+{
+#ifdef CONFIG_ARM_VIRT_EXT
+       if (is_hyp_mode_available()) {
+               pr_info("CPU: All CPU(s) started in HYP mode.\n");
+               pr_info("CPU: Virtualization extensions available.\n");
+       } else if (is_hyp_mode_mismatched()) {
+               pr_warn("CPU: WARNING: CPU(s) started in wrong/inconsistent modes (primary CPU mode 0x%x)\n",
+                       __boot_cpu_mode & MODE_MASK);
+               pr_warn("CPU: This may indicate a broken bootloader or firmware.\n");
+       } else
+               pr_info("CPU: All CPU(s) started in SVC mode.\n");
+#endif
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        struct machine_desc *mdesc;
@@ -748,6 +764,10 @@ void __init setup_arch(char **cmdline_p)
                smp_init_cpus();
        }
 #endif
+
+       if (!is_smp())
+               hyp_mode_check();
+
        reserve_crashkernel();
 
        tcm_init();
index d100eacdb7983f8e490a8dc88d4f830b7fab3b8c..8e20754dd31d5946f5297aae2023ae2c8d5cd572 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
 #include <asm/smp_plat.h>
+#include <asm/virt.h>
 #include <asm/mach/arch.h>
 
 /*
@@ -202,8 +203,11 @@ int __cpuinit __cpu_disable(void)
        /*
         * Flush user cache and TLB mappings, and then remove this CPU
         * from the vm mask set of all processes.
+        *
+        * Caches are flushed to the Level of Unification Inner Shareable
+        * to write-back dirty lines to unified caches shared by all CPUs.
         */
-       flush_cache_all();
+       flush_cache_louis();
        local_flush_tlb_all();
 
        clear_tasks_mm_cpumask(cpu);
@@ -355,6 +359,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
               num_online_cpus(),
               bogosum / (500000/HZ),
               (bogosum / (5000/HZ)) % 100);
+
+       hyp_mode_check();
 }
 
 void __init smp_prepare_boot_cpu(void)
index 1794cc3b0f1836583fec297ee484c554fdefffcd..358bca3a995ed37ec66da93ec40841abd99fa804 100644 (file)
@@ -17,6 +17,8 @@ extern void cpu_resume_mmu(void);
  */
 void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
 {
+       u32 *ctx = ptr;
+
        *save_ptr = virt_to_phys(ptr);
 
        /* This must correspond to the LDM in cpu_resume() assembly */
@@ -26,7 +28,20 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
 
        cpu_do_suspend(ptr);
 
-       flush_cache_all();
+       flush_cache_louis();
+
+       /*
+        * flush_cache_louis does not guarantee that
+        * save_ptr and ptr are cleaned to main memory,
+        * just up to the Level of Unification Inner Shareable.
+        * Since the context pointer and context itself
+        * are to be retrieved with the MMU off that
+        * data must be cleaned from all cache levels
+        * to main memory using "area" cache primitives.
+       */
+       __cpuc_flush_dcache_area(ctx, ptrsz);
+       __cpuc_flush_dcache_area(save_ptr, sizeof(*save_ptr));
+
        outer_clean_range(*save_ptr, *save_ptr + ptrsz);
        outer_clean_range(virt_to_phys(save_ptr),
                          virt_to_phys(save_ptr) + sizeof(*save_ptr));
index ab99c3c3b752689e50db5720e2d36beb23ee2b21..026b4b277ae5d54e4d911f69c91c7bfee21ea68d 100644 (file)
@@ -186,6 +186,13 @@ config DA850_UI_RMII
          NOTE: Please take care while choosing this option, MII PHY will
          not be functional if RMII mode is selected.
 
+config DA850_UI_SD_VIDEO_PORT
+       bool "Video Port Interface"
+       help
+         Say Y if you want to use Video Port Interface (VPIF) on the
+         DA850/OMAP-L138 EVM. The Video decoders/encoders are found on the
+         UI daughter card that is supplied with the EVM.
+
 endchoice
 
 config DA850_WL12XX
index 1295e616ceee7e32a5b31d62b3cf52a4286578b3..32ee3f89596738d988a00105c0358d4ff1a61f1b 100644 (file)
@@ -45,6 +45,9 @@
 #include <linux/platform_data/mtd-davinci-aemif.h>
 #include <linux/platform_data/spi-davinci.h>
 
+#include <media/tvp514x.h>
+#include <media/adv7343.h>
+
 #define DA850_EVM_PHY_ID               "davinci_mdio-0:00"
 #define DA850_LCD_PWR_PIN              GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN               GPIO_TO_PIN(2, 15)
@@ -452,6 +455,15 @@ static void da850_evm_ui_keys_init(unsigned gpio)
        }
 }
 
+#ifdef CONFIG_DA850_UI_SD_VIDEO_PORT
+static inline void da850_evm_setup_video_port(int video_sel)
+{
+       gpio_set_value_cansleep(video_sel, 0);
+}
+#else
+static inline void da850_evm_setup_video_port(int video_sel) { }
+#endif
+
 static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
                                                unsigned ngpio, void *c)
 {
@@ -497,6 +509,8 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
 
        da850_evm_setup_emac_rmii(sel_a);
 
+       da850_evm_setup_video_port(sel_c);
+
        return 0;
 
 exp_setup_keys_fail:
@@ -1149,6 +1163,169 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#if defined(CONFIG_DA850_UI_SD_VIDEO_PORT)
+
+#define TVP5147_CH0            "tvp514x-0"
+#define TVP5147_CH1            "tvp514x-1"
+
+/* VPIF capture configuration */
+static struct tvp514x_platform_data tvp5146_pdata = {
+               .clk_polarity = 0,
+               .hs_polarity  = 1,
+               .vs_polarity  = 1,
+};
+
+#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
+
+static const struct vpif_input da850_ch0_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "Composite",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_CVBS_VI2B,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH0,
+       },
+};
+
+static const struct vpif_input da850_ch1_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "S-Video",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_SVIDEO_VI2C_VI1C,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH1,
+       },
+};
+
+static struct vpif_subdev_info da850_vpif_capture_sdev_info[] = {
+       {
+               .name = TVP5147_CH0,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5d),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+       {
+               .name = TVP5147_CH1,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5c),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+};
+
+static struct vpif_capture_config da850_vpif_capture_config = {
+       .subdev_info = da850_vpif_capture_sdev_info,
+       .subdev_count = ARRAY_SIZE(da850_vpif_capture_sdev_info),
+       .chan_config[0] = {
+               .inputs = da850_ch0_inputs,
+               .input_count = ARRAY_SIZE(da850_ch0_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .chan_config[1] = {
+               .inputs = da850_ch1_inputs,
+               .input_count = ARRAY_SIZE(da850_ch1_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .card_name = "DA850/OMAP-L138 Video Capture",
+};
+
+/* VPIF display configuration */
+static struct vpif_subdev_info da850_vpif_subdev[] = {
+       {
+               .name = "adv7343",
+               .board_info = {
+                       I2C_BOARD_INFO("adv7343", 0x2a),
+               },
+       },
+};
+
+static const struct vpif_output da850_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
+};
+
+static struct vpif_display_config da850_vpif_display_config = {
+       .subdevinfo   = da850_vpif_subdev,
+       .subdev_count = ARRAY_SIZE(da850_vpif_subdev),
+       .chan_config[0] = {
+               .outputs = da850_ch0_outputs,
+               .output_count = ARRAY_SIZE(da850_ch0_outputs),
+       },
+       .card_name    = "DA850/OMAP-L138 Video Display",
+};
+
+static __init void da850_vpif_init(void)
+{
+       int ret;
+
+       ret = da850_register_vpif();
+       if (ret)
+               pr_warn("da850_evm_init: VPIF setup failed: %d\n", ret);
+
+       ret = davinci_cfg_reg_list(da850_vpif_capture_pins);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF capture mux setup failed: %d\n",
+                       ret);
+
+       ret = da850_register_vpif_capture(&da850_vpif_capture_config);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF capture setup failed: %d\n", ret);
+
+       ret = davinci_cfg_reg_list(da850_vpif_display_pins);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF display mux setup failed: %d\n",
+                       ret);
+
+       ret = da850_register_vpif_display(&da850_vpif_display_config);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF display setup failed: %d\n", ret);
+}
+
+#else
+static __init void da850_vpif_init(void) {}
+#endif
+
 #ifdef CONFIG_DA850_WL12XX
 
 static void wl12xx_set_power(int index, bool power_on)
@@ -1375,6 +1552,8 @@ static __init void da850_evm_init(void)
                pr_warning("da850_evm_init: suspend registration failed: %d\n",
                                ret);
 
+       da850_vpif_init();
+
        ret = da8xx_register_spi(1, da850evm_spi_info,
                                 ARRAY_SIZE(da850evm_spi_info));
        if (ret)
index ca72fc4b8ccaac489b3e5e4e800e84e73730149e..f22572cee49d89ade236851a04fdf2ba94fed2e6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/phy.h>
 #include <linux/clk.h>
 #include <linux/videodev2.h>
+#include <linux/v4l2-dv-timings.h>
 #include <linux/export.h>
 
 #include <media/tvp514x.h>
@@ -620,7 +621,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
        {
                .name           = "ntsc",
                .timings_type   = VPBE_ENC_STD,
-               .timings        = {V4L2_STD_525_60},
+               .std_id         = V4L2_STD_525_60,
                .interlaced     = 1,
                .xres           = 720,
                .yres           = 480,
@@ -632,7 +633,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
        {
                .name           = "pal",
                .timings_type   = VPBE_ENC_STD,
-               .timings        = {V4L2_STD_625_50},
+               .std_id         = V4L2_STD_625_50,
                .interlaced     = 1,
                .xres           = 720,
                .yres           = 576,
@@ -647,8 +648,8 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
 static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
        {
                .name           = "480p59_94",
-               .timings_type   = VPBE_ENC_DV_PRESET,
-               .timings        = {V4L2_DV_480P59_94},
+               .timings_type   = VPBE_ENC_CUSTOM_TIMINGS,
+               .dv_timings     = V4L2_DV_BT_CEA_720X480P59_94,
                .interlaced     = 0,
                .xres           = 720,
                .yres           = 480,
@@ -659,8 +660,8 @@ static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
        },
        {
                .name           = "576p50",
-               .timings_type   = VPBE_ENC_DV_PRESET,
-               .timings        = {V4L2_DV_576P50},
+               .timings_type   = VPBE_ENC_CUSTOM_TIMINGS,
+               .dv_timings     = V4L2_DV_BT_CEA_720X576P50,
                .interlaced     = 0,
                .xres           = 720,
                .yres           = 576,
@@ -698,7 +699,7 @@ static struct vpbe_output dm644xevm_vpbe_outputs[] = {
                        .index          = 1,
                        .name           = "Component",
                        .type           = V4L2_OUTPUT_TYPE_ANALOG,
-                       .capabilities   = V4L2_OUT_CAP_PRESETS,
+                       .capabilities   = V4L2_OUT_CAP_DV_TIMINGS,
                },
                .subdev_name    = VPBE_VENC_SUBDEV_NAME,
                .default_mode   = "480p59_94",
index 9944367b4931b9a630a5bd91db7d6e784aebf75f..1dbf85beed1baaf55718a7f00debd3416327e66d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/i2c/pcf857x.h>
 
 #include <media/tvp514x.h>
+#include <media/adv7343.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -496,18 +497,49 @@ static struct vpif_subdev_info dm646x_vpif_subdev[] = {
        },
 };
 
-static const char *output[] = {
-       "Composite",
-       "Component",
-       "S-Video",
+static const struct vpif_output dm6467_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "Component",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPONENT_ID,
+       },
+       {
+               .output = {
+                       .index = 2,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
 };
 
 static struct vpif_display_config dm646x_vpif_display_config = {
        .set_clock      = set_vpif_clock,
        .subdevinfo     = dm646x_vpif_subdev,
        .subdev_count   = ARRAY_SIZE(dm646x_vpif_subdev),
-       .output         = output,
-       .output_count   = ARRAY_SIZE(output),
+       .chan_config[0] = {
+               .outputs = dm6467_ch0_outputs,
+               .output_count = ARRAY_SIZE(dm6467_ch0_outputs),
+       },
        .card_name      = "DM646x EVM",
 };
 
@@ -601,15 +633,6 @@ static struct vpif_subdev_info vpif_capture_sdev_info[] = {
                        I2C_BOARD_INFO("tvp5146", 0x5d),
                        .platform_data = &tvp5146_pdata,
                },
-               .input = INPUT_CVBS_VI2B,
-               .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
-               .can_route = 1,
-               .vpif_if = {
-                       .if_type = VPIF_IF_BT656,
-                       .hd_pol = 1,
-                       .vd_pol = 1,
-                       .fid_pol = 0,
-               },
        },
        {
                .name   = TVP5147_CH1,
@@ -617,15 +640,6 @@ static struct vpif_subdev_info vpif_capture_sdev_info[] = {
                        I2C_BOARD_INFO("tvp5146", 0x5c),
                        .platform_data = &tvp5146_pdata,
                },
-               .input = INPUT_SVIDEO_VI2C_VI1C,
-               .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
-               .can_route = 1,
-               .vpif_if = {
-                       .if_type = VPIF_IF_BT656,
-                       .hd_pol = 1,
-                       .vd_pol = 1,
-                       .fid_pol = 0,
-               },
        },
 };
 
@@ -635,9 +649,12 @@ static const struct vpif_input dm6467_ch0_inputs[] = {
                        .index = 0,
                        .name = "Composite",
                        .type = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
                        .std = TVP514X_STD_ALL,
                },
                .subdev_name = TVP5147_CH0,
+               .input_route = INPUT_CVBS_VI2B,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
        },
 };
 
@@ -647,9 +664,12 @@ static const struct vpif_input dm6467_ch1_inputs[] = {
                        .index = 0,
                        .name = "S-Video",
                        .type = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
                        .std = TVP514X_STD_ALL,
                },
                .subdev_name = TVP5147_CH1,
+               .input_route = INPUT_SVIDEO_VI2C_VI1C,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
        },
 };
 
@@ -661,10 +681,22 @@ static struct vpif_capture_config dm646x_vpif_capture_cfg = {
        .chan_config[0] = {
                .inputs = dm6467_ch0_inputs,
                .input_count = ARRAY_SIZE(dm6467_ch0_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol = 1,
+                       .vd_pol = 1,
+                       .fid_pol = 0,
+               },
        },
        .chan_config[1] = {
                .inputs = dm6467_ch1_inputs,
                .input_count = ARRAY_SIZE(dm6467_ch1_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol = 1,
+                       .vd_pol = 1,
+                       .fid_pol = 0,
+               },
        },
 };
 
index e517e1036b093562269dc8301448eea0aae9573d..b90c172d55413dc6e301ba15afff70f721d3c704 100644 (file)
@@ -347,6 +347,13 @@ static struct clk spi1_clk = {
        .flags          = DA850_CLK_ASYNC3,
 };
 
+static struct clk vpif_clk = {
+       .name           = "vpif",
+       .parent         = &pll0_sysclk2,
+       .lpsc           = DA850_LPSC1_VPIF,
+       .gpsc           = 1,
+};
+
 static struct clk sata_clk = {
        .name           = "sata",
        .parent         = &pll0_sysclk2,
@@ -397,6 +404,7 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "usb20",        &usb20_clk),
        CLK("spi_davinci.0",    NULL,           &spi0_clk),
        CLK("spi_davinci.1",    NULL,           &spi1_clk),
+       CLK("vpif",             NULL,           &vpif_clk),
        CLK("ahci",             NULL,           &sata_clk),
        CLK(NULL,               NULL,           NULL),
 };
@@ -573,6 +581,46 @@ static const struct mux_config da850_pins[] = {
        MUX_CFG(DA850, GPIO6_10,        13,     20,     15,     8,      false)
        MUX_CFG(DA850, GPIO6_13,        13,     8,      15,     8,      false)
        MUX_CFG(DA850, RTC_ALARM,       0,      28,     15,     2,      false)
+       /* VPIF Capture */
+       MUX_CFG(DA850, VPIF_DIN0,       15,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN1,       15,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN2,       14,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN3,       14,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN4,       14,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN5,       14,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN6,       14,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN7,       14,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN8,       16,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN9,       16,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN10,      15,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN11,      15,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN12,      15,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN13,      15,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN14,      15,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN15,      15,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN0,     14,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN1,     14,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN2,     19,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN3,     19,     16,     15,     1,      false)
+       /* VPIF Display */
+       MUX_CFG(DA850, VPIF_DOUT0,      17,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT1,      17,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT2,      16,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT3,      16,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT4,      16,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT5,      16,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT6,      16,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT7,      16,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT8,      18,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT9,      18,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT10,     17,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT11,     17,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT12,     17,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT13,     17,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT14,     17,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT15,     17,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKO2,      19,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKO3,      19,     20,     15,     1,      false)
 #endif
 };
 
@@ -595,6 +643,26 @@ const short da850_lcdcntl_pins[] __initconst = {
        -1
 };
 
+const short da850_vpif_capture_pins[] __initdata = {
+       DA850_VPIF_DIN0, DA850_VPIF_DIN1, DA850_VPIF_DIN2, DA850_VPIF_DIN3,
+       DA850_VPIF_DIN4, DA850_VPIF_DIN5, DA850_VPIF_DIN6, DA850_VPIF_DIN7,
+       DA850_VPIF_DIN8, DA850_VPIF_DIN9, DA850_VPIF_DIN10, DA850_VPIF_DIN11,
+       DA850_VPIF_DIN12, DA850_VPIF_DIN13, DA850_VPIF_DIN14, DA850_VPIF_DIN15,
+       DA850_VPIF_CLKIN0, DA850_VPIF_CLKIN1, DA850_VPIF_CLKIN2,
+       DA850_VPIF_CLKIN3,
+       -1
+};
+
+const short da850_vpif_display_pins[] __initdata = {
+       DA850_VPIF_DOUT0, DA850_VPIF_DOUT1, DA850_VPIF_DOUT2, DA850_VPIF_DOUT3,
+       DA850_VPIF_DOUT4, DA850_VPIF_DOUT5, DA850_VPIF_DOUT6, DA850_VPIF_DOUT7,
+       DA850_VPIF_DOUT8, DA850_VPIF_DOUT9, DA850_VPIF_DOUT10,
+       DA850_VPIF_DOUT11, DA850_VPIF_DOUT12, DA850_VPIF_DOUT13,
+       DA850_VPIF_DOUT14, DA850_VPIF_DOUT15, DA850_VPIF_CLKO2,
+       DA850_VPIF_CLKO3,
+       -1
+};
+
 /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
 static u8 da850_default_priorities[DA850_N_CP_INTC_IRQ] = {
        [IRQ_DA8XX_COMMTX]              = 7,
@@ -1064,6 +1132,90 @@ no_ddrpll_mem:
        return ret;
 }
 
+/* VPIF resource, platform data */
+static u64 da850_vpif_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource da850_vpif_resource[] = {
+       {
+               .start = DA8XX_VPIF_BASE,
+               .end   = DA8XX_VPIF_BASE + 0xfff,
+               .flags = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device da850_vpif_dev = {
+       .name           = "vpif",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_resource),
+};
+
+static struct resource da850_vpif_display_resource[] = {
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device da850_vpif_display_dev = {
+       .name           = "vpif_display",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_display_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_display_resource),
+};
+
+static struct resource da850_vpif_capture_resource[] = {
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device da850_vpif_capture_dev = {
+       .name           = "vpif_capture",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_capture_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_capture_resource),
+};
+
+int __init da850_register_vpif(void)
+{
+       return platform_device_register(&da850_vpif_dev);
+}
+
+int __init da850_register_vpif_display(struct vpif_display_config
+                                               *display_config)
+{
+       da850_vpif_display_dev.dev.platform_data = display_config;
+       return platform_device_register(&da850_vpif_display_dev);
+}
+
+int __init da850_register_vpif_capture(struct vpif_capture_config
+                                                       *capture_config)
+{
+       da850_vpif_capture_dev.dev.platform_data = capture_config;
+       return platform_device_register(&da850_vpif_capture_dev);
+}
+
 static struct davinci_soc_info davinci_soc_info_da850 = {
        .io_desc                = da850_io_desc,
        .io_desc_num            = ARRAY_SIZE(da850_io_desc),
index 0755d466221a6aad1b3c93056f5e39e314cfc034..cd0c8b1e1ecfad4a868b9aae3f6180a1b1794ed1 100644 (file)
@@ -701,7 +701,7 @@ static struct resource dm644x_venc_resources[] = {
 #define DM644X_VPSS_DACCLKEN                  BIT(4)
 
 static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
-                                  unsigned int mode)
+                                  unsigned int pclock)
 {
        int ret = 0;
        u32 v = DM644X_VPSS_VENCLKEN;
@@ -711,27 +711,18 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
                v |= DM644X_VPSS_DACCLKEN;
                writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
                break;
-       case VPBE_ENC_DV_PRESET:
-               switch (mode) {
-               case V4L2_DV_480P59_94:
-               case V4L2_DV_576P50:
+       case VPBE_ENC_CUSTOM_TIMINGS:
+               if (pclock <= 27000000) {
                        v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
                             DM644X_VPSS_DACCLKEN;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
-                       break;
-               case V4L2_DV_720P60:
-               case V4L2_DV_1080I60:
-               case V4L2_DV_1080P30:
+               } else {
                        /*
                         * For HD, use external clock source since
                         * HD requires higher clock rate
                         */
                        v |= DM644X_VPSS_MUXSEL_VPBECLK_MODE;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
-                       break;
-               default:
-                       ret = -EINVAL;
-                       break;
                }
                break;
        default:
index c9ee723c56f35a78628dc0a4a78c08bd63a4f6c3..aaccdc4528fcce2f3110d2d4385dc1c5239ceebb 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/davinci_emac.h>
 #include <linux/spi/spi.h>
 #include <linux/platform_data/davinci_asp.h>
+#include <linux/videodev2.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
@@ -26,6 +27,8 @@
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_data/spi-davinci.h>
 
+#include <media/davinci/vpif_types.h>
+
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
 
@@ -63,6 +66,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_PLL0_BASE                0x01c11000
 #define DA8XX_TIMER64P0_BASE   0x01c20000
 #define DA8XX_TIMER64P1_BASE   0x01c21000
+#define DA8XX_VPIF_BASE                0x01e17000
 #define DA8XX_GPIO_BASE                0x01e26000
 #define DA8XX_PSC1_BASE                0x01e27000
 #define DA8XX_AEMIF_CS2_BASE   0x60000000
@@ -92,6 +96,11 @@ int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 int da850_register_pm(struct platform_device *pdev);
 int __init da850_register_sata(unsigned long refclkpn);
+int __init da850_register_vpif(void);
+int __init da850_register_vpif_display
+                       (struct vpif_display_config *display_config);
+int __init da850_register_vpif_capture
+                       (struct vpif_capture_config *capture_config);
 void da8xx_restart(char mode, const char *cmd);
 
 extern struct platform_device da8xx_serial_device;
@@ -126,6 +135,8 @@ extern const short da830_ecap1_pins[];
 extern const short da830_ecap2_pins[];
 extern const short da830_eqep0_pins[];
 extern const short da830_eqep1_pins[];
+extern const short da850_vpif_capture_pins[];
+extern const short da850_vpif_display_pins[];
 
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c1_pins[];
index a7e92fca32e6719457167f1c2f9efbdd2921df73..9e95b8a1edb62964cc473c1947bc61ebc6ca0402 100644 (file)
@@ -928,6 +928,48 @@ enum davinci_da850_index {
        DA850_GPIO6_10,
        DA850_GPIO6_13,
        DA850_RTC_ALARM,
+
+       /* VPIF Capture */
+       DA850_VPIF_DIN0,
+       DA850_VPIF_DIN1,
+       DA850_VPIF_DIN2,
+       DA850_VPIF_DIN3,
+       DA850_VPIF_DIN4,
+       DA850_VPIF_DIN5,
+       DA850_VPIF_DIN6,
+       DA850_VPIF_DIN7,
+       DA850_VPIF_DIN8,
+       DA850_VPIF_DIN9,
+       DA850_VPIF_DIN10,
+       DA850_VPIF_DIN11,
+       DA850_VPIF_DIN12,
+       DA850_VPIF_DIN13,
+       DA850_VPIF_DIN14,
+       DA850_VPIF_DIN15,
+       DA850_VPIF_CLKIN0,
+       DA850_VPIF_CLKIN1,
+       DA850_VPIF_CLKIN2,
+       DA850_VPIF_CLKIN3,
+
+       /* VPIF Display */
+       DA850_VPIF_DOUT0,
+       DA850_VPIF_DOUT1,
+       DA850_VPIF_DOUT2,
+       DA850_VPIF_DOUT3,
+       DA850_VPIF_DOUT4,
+       DA850_VPIF_DOUT5,
+       DA850_VPIF_DOUT6,
+       DA850_VPIF_DOUT7,
+       DA850_VPIF_DOUT8,
+       DA850_VPIF_DOUT9,
+       DA850_VPIF_DOUT10,
+       DA850_VPIF_DOUT11,
+       DA850_VPIF_DOUT12,
+       DA850_VPIF_DOUT13,
+       DA850_VPIF_DOUT14,
+       DA850_VPIF_DOUT15,
+       DA850_VPIF_CLKO2,
+       DA850_VPIF_CLKO3,
 };
 
 enum davinci_tnetv107x_index {
index 405318e35bf63f8422dc5263088d2a9cbe64a212..40a0027838e81601427fbb2bc7ff04311e5300ad 100644 (file)
 #define DA830_LPSC1_McASP1             8
 #define DA850_LPSC1_SATA               8
 #define DA830_LPSC1_McASP2             9
+#define DA850_LPSC1_VPIF               9
 #define DA8XX_LPSC1_SPI1               10
 #define DA8XX_LPSC1_I2C                        11
 #define DA8XX_LPSC1_UART1              12
index 85fc2feb0af08e75d45c49f7d2a6b368c962ccd3..c05d7aa84031b70a601598fd0a5542dfbf3056f3 100644 (file)
@@ -378,10 +378,10 @@ static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
 };
 static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
        REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"), /* USB */
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
        REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
@@ -1180,9 +1180,7 @@ static struct platform_device cam_8m_12v_fixed_rdev = {
 static struct s5p_platform_mipi_csis mipi_csis_platdata = {
        .clk_rate       = 166000000UL,
        .lanes          = 2,
-       .alignment      = 32,
        .hs_settle      = 12,
-       .phy_enable     = s5p_csis_phy_enable,
 };
 
 #define GPIO_CAM_MEGA_RST      EXYNOS4_GPY3(7) /* ISP_RESET */
@@ -1226,7 +1224,6 @@ static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
                .bus_type       = FIMC_MIPI_CSI2,
                .board_info     = &m5mols_board_info,
                .clk_frequency  = 24000000UL,
-               .csi_data_align = 32,
        },
 };
 
index c11a62e23dccc3cab1ec7c1f15096de12f26e808..9adf491674ea18f350039da0dfbd20e6c825d690 100644 (file)
@@ -97,12 +97,12 @@ static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
 };
 
 static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
        REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
        REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
 };
 static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
        REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
index 08b81fd995053a8ae3ee0cdcee918c3489021d1b..ebc9dd339a3899ae6170a24a0ddf2c1e44b1281d 100644 (file)
@@ -209,7 +209,7 @@ static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
        REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
        REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
        REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"),
 };
 
 static struct regulator_init_data lp3974_ldo3_data = {
@@ -273,7 +273,7 @@ static struct regulator_init_data lp3974_ldo6_data = {
 };
 
 static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"),
 };
 
 static struct regulator_init_data lp3974_ldo7_data = {
@@ -942,9 +942,7 @@ static struct platform_device cam_s_if_fixed_reg_dev = {
 static struct s5p_platform_mipi_csis mipi_csis_platdata = {
        .clk_rate       = 166000000UL,
        .lanes          = 2,
-       .alignment      = 32,
        .hs_settle      = 12,
-       .phy_enable     = s5p_csis_phy_enable,
 };
 
 #define GPIO_CAM_LEVEL_EN(n)   EXYNOS4_GPE4(n + 3)
@@ -1008,7 +1006,6 @@ static struct s5p_fimc_isp_info universal_camera_sensors[] = {
                .board_info     = &m5mols_board_info,
                .i2c_bus_num    = 0,
                .clk_frequency  = 24000000UL,
-               .csi_data_align = 32,
        },
 };
 
index 101b9681c08c238a4487afca05df11fff15c9d23..c9a4963b5c3d3363210a53d11cc55d63d77965fd 100644 (file)
@@ -624,6 +624,23 @@ config ARM_THUMBEE
          Say Y here if you have a CPU with the ThumbEE extension and code to
          make use of it. Say N for code that can run on CPUs without ThumbEE.
 
+config ARM_VIRT_EXT
+       bool "Native support for the ARM Virtualization Extensions"
+       depends on MMU && CPU_V7
+       help
+         Enable the kernel to make use of the ARM Virtualization
+         Extensions to install hypervisors without run-time firmware
+         assistance.
+
+         A compliant bootloader is required in order to make maximum
+         use of this feature.  Refer to Documentation/arm/Booting for
+         details.
+
+         It is safe to enable this option even if the kernel may not be
+         booted in HYP mode, may not have support for the
+         virtualization extensions, or may be booted with a
+         non-compliant bootloader.
+
 config SWP_EMULATE
        bool "Emulate SWP/SWPB instructions"
        depends on !CPU_USE_DOMAINS && CPU_V7
index 072016371093546cc95519289b30a66b381d79a9..e505befe51b54b77e850049f38633c5d1c2c20af 100644 (file)
@@ -240,6 +240,9 @@ ENTRY(fa_dma_unmap_area)
        mov     pc, lr
 ENDPROC(fa_dma_unmap_area)
 
+       .globl  fa_flush_kern_cache_louis
+       .equ    fa_flush_kern_cache_louis, fa_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 52e35f32eefb293589ce6c8ce11b4871cf178c62..8a3fadece8d3739b9d3199c5fa7d6de45bf385f4 100644 (file)
@@ -128,6 +128,9 @@ ENTRY(v3_dma_map_area)
 ENDPROC(v3_dma_unmap_area)
 ENDPROC(v3_dma_map_area)
 
+       .globl  v3_flush_kern_cache_louis
+       .equ    v3_flush_kern_cache_louis, v3_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 022135d2b7e4394313e1bad6ad3deb67ab8e4e14..43e5d77be677a329f497f9829364f392b254fa75 100644 (file)
@@ -140,6 +140,9 @@ ENTRY(v4_dma_map_area)
 ENDPROC(v4_dma_unmap_area)
 ENDPROC(v4_dma_map_area)
 
+       .globl  v4_flush_kern_cache_louis
+       .equ    v4_flush_kern_cache_louis, v4_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 8f1eeae340c84b6b948d3ca4a4f0af91250facb3..cd49453214070f24b8cab5c64b583c5aff8309e0 100644 (file)
@@ -251,6 +251,9 @@ ENTRY(v4wb_dma_unmap_area)
        mov     pc, lr
 ENDPROC(v4wb_dma_unmap_area)
 
+       .globl  v4wb_flush_kern_cache_louis
+       .equ    v4wb_flush_kern_cache_louis, v4wb_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index b34a5f908a82345bd6f4c4eb8b20f44f587cad48..11e5e5838bc59eb8d99e2e5d5d74830e86c652f0 100644 (file)
@@ -196,6 +196,9 @@ ENTRY(v4wt_dma_map_area)
 ENDPROC(v4wt_dma_unmap_area)
 ENDPROC(v4wt_dma_map_area)
 
+       .globl  v4wt_flush_kern_cache_louis
+       .equ    v4wt_flush_kern_cache_louis, v4wt_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 4b10760c56d6fe081dd9ab0988119d2378cd9369..d8fd4d4bd3d45ecdc66ad2c74885795df9681ea7 100644 (file)
@@ -326,6 +326,9 @@ ENTRY(v6_dma_unmap_area)
        mov     pc, lr
 ENDPROC(v6_dma_unmap_area)
 
+       .globl  v6_flush_kern_cache_louis
+       .equ    v6_flush_kern_cache_louis, v6_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 3b172275262e2c87070af4047a1123c2a6a1a6aa..cd956647c21a800d69ed3215a774b086fed008a1 100644 (file)
@@ -33,6 +33,24 @@ ENTRY(v7_flush_icache_all)
        mov     pc, lr
 ENDPROC(v7_flush_icache_all)
 
+ /*
+ *     v7_flush_dcache_louis()
+ *
+ *     Flush the D-cache up to the Level of Unification Inner Shareable
+ *
+ *     Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
+ */
+
+ENTRY(v7_flush_dcache_louis)
+       dmb                                     @ ensure ordering with previous memory accesses
+       mrc     p15, 1, r0, c0, c0, 1           @ read clidr, r0 = clidr
+       ands    r3, r0, #0xe00000               @ extract LoUIS from clidr
+       mov     r3, r3, lsr #20                 @ r3 = LoUIS * 2
+       moveq   pc, lr                          @ return if level == 0
+       mov     r10, #0                         @ r10 (starting level) = 0
+       b       flush_levels                    @ start flushing cache levels
+ENDPROC(v7_flush_dcache_louis)
+
 /*
  *     v7_flush_dcache_all()
  *
@@ -49,7 +67,7 @@ ENTRY(v7_flush_dcache_all)
        mov     r3, r3, lsr #23                 @ left align loc bit field
        beq     finished                        @ if loc is 0, then no need to clean
        mov     r10, #0                         @ start clean at cache level 0
-loop1:
+flush_levels:
        add     r2, r10, r10, lsr #1            @ work out 3x current cache level
        mov     r1, r0, lsr r2                  @ extract cache type bits from clidr
        and     r1, r1, #7                      @ mask of the bits for current cache only
@@ -71,9 +89,9 @@ loop1:
        clz     r5, r4                          @ find bit position of way size increment
        ldr     r7, =0x7fff
        ands    r7, r7, r1, lsr #13             @ extract max number of the index size
-loop2:
+loop1:
        mov     r9, r4                          @ create working copy of max way size
-loop3:
+loop2:
  ARM(  orr     r11, r10, r9, lsl r5    )       @ factor way and cache number into r11
  THUMB(        lsl     r6, r9, r5              )
  THUMB(        orr     r11, r10, r6            )       @ factor way and cache number into r11
@@ -82,13 +100,13 @@ loop3:
  THUMB(        orr     r11, r11, r6            )       @ factor index number into r11
        mcr     p15, 0, r11, c7, c14, 2         @ clean & invalidate by set/way
        subs    r9, r9, #1                      @ decrement the way
-       bge     loop3
-       subs    r7, r7, #1                      @ decrement the index
        bge     loop2
+       subs    r7, r7, #1                      @ decrement the index
+       bge     loop1
 skip:
        add     r10, r10, #2                    @ increment cache number
        cmp     r3, r10
-       bgt     loop1
+       bgt     flush_levels
 finished:
        mov     r10, #0                         @ swith back to cache level 0
        mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
@@ -120,6 +138,24 @@ ENTRY(v7_flush_kern_cache_all)
        mov     pc, lr
 ENDPROC(v7_flush_kern_cache_all)
 
+ /*
+ *     v7_flush_kern_cache_louis(void)
+ *
+ *     Flush the data cache up to Level of Unification Inner Shareable.
+ *     Invalidate the I-cache to the point of unification.
+ */
+ENTRY(v7_flush_kern_cache_louis)
+ ARM(  stmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
+ THUMB(        stmfd   sp!, {r4-r7, r9-r11, lr}        )
+       bl      v7_flush_dcache_louis
+       mov     r0, #0
+       ALT_SMP(mcr     p15, 0, r0, c7, c1, 0)  @ invalidate I-cache inner shareable
+       ALT_UP(mcr      p15, 0, r0, c7, c5, 0)  @ I+BTB cache invalidate
+ ARM(  ldmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
+ THUMB(        ldmfd   sp!, {r4-r7, r9-r11, lr}        )
+       mov     pc, lr
+ENDPROC(v7_flush_kern_cache_louis)
+
 /*
  *     v7_flush_cache_all()
  *
index 0650bb87c1e3a68feb64f465bf547c2e3de52771..2bb61e703d6c4d042cbbb86e6c655cbc0e94d762 100644 (file)
@@ -368,6 +368,9 @@ ENTRY(arm1020_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1020_dma_unmap_area)
 
+       .globl  arm1020_flush_kern_cache_louis
+       .equ    arm1020_flush_kern_cache_louis, arm1020_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1020
 
index 4188478325a6398fbe8ada36c109694b81f177ea..8f96aa40f5107987edf065c451d4d0879e5e108c 100644 (file)
@@ -354,6 +354,9 @@ ENTRY(arm1020e_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1020e_dma_unmap_area)
 
+       .globl  arm1020e_flush_kern_cache_louis
+       .equ    arm1020e_flush_kern_cache_louis, arm1020e_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1020e
 
index 33c68824bff0999d6f718eb065f1c5b1daad9cac..8ebe4a469a22534c9a828681d57552a546fb820b 100644 (file)
@@ -343,6 +343,9 @@ ENTRY(arm1022_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1022_dma_unmap_area)
 
+       .globl  arm1022_flush_kern_cache_louis
+       .equ    arm1022_flush_kern_cache_louis, arm1022_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1022
 
index fbc1d5fc24dcd0b5df37e4f508b4ea7fb9c4bafc..093fc7e520c341fb270b45e3ef2f4fbed694ae3c 100644 (file)
@@ -337,6 +337,9 @@ ENTRY(arm1026_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1026_dma_unmap_area)
 
+       .globl  arm1026_flush_kern_cache_louis
+       .equ    arm1026_flush_kern_cache_louis, arm1026_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1026
 
index 1a8c138eb8975697b8d15dee01f71ad2e9e5917c..2c3b9421ab5eca938dfe9289fc39472259ada3c1 100644 (file)
@@ -319,6 +319,9 @@ ENTRY(arm920_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm920_dma_unmap_area)
 
+       .globl  arm920_flush_kern_cache_louis
+       .equ    arm920_flush_kern_cache_louis, arm920_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm920
 #endif
index 4c44d7e1c3ca214f4debab4538928ef68113bafd..4464c49d7449b386b04c017f33fdeb79ef718f05 100644 (file)
@@ -321,6 +321,9 @@ ENTRY(arm922_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm922_dma_unmap_area)
 
+       .globl  arm922_flush_kern_cache_louis
+       .equ    arm922_flush_kern_cache_louis, arm922_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm922
 #endif
index ec5b1180994fb7b01779a8c457737f803f613e75..281eb9b9c1d654061e0bc8d2e6d350f6d7a3b2ff 100644 (file)
@@ -376,6 +376,9 @@ ENTRY(arm925_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm925_dma_unmap_area)
 
+       .globl  arm925_flush_kern_cache_louis
+       .equ    arm925_flush_kern_cache_louis, arm925_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm925
 
index c31e62c606c0b6eebf5390c2de640a7fb63ad949..f1803f7e29728460965675b6722a978d0cc33dcd 100644 (file)
@@ -339,6 +339,9 @@ ENTRY(arm926_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm926_dma_unmap_area)
 
+       .globl  arm926_flush_kern_cache_louis
+       .equ    arm926_flush_kern_cache_louis, arm926_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm926
 
index a613a7dd71465c994f6d57093954d9110aee12e4..8da189d4a4021a9184d1c78ac4cda76209406f02 100644 (file)
@@ -267,6 +267,9 @@ ENTRY(arm940_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm940_dma_unmap_area)
 
+       .globl  arm940_flush_kern_cache_louis
+       .equ    arm940_flush_kern_cache_louis, arm940_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm940
 
index 9f4f2999fdd076e5c13aceaa9e5f3734c6ec65ba..f666cf34075a1a8e7e496fd9c0a09657a0627040 100644 (file)
@@ -310,6 +310,9 @@ ENTRY(arm946_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm946_dma_unmap_area)
 
+       .globl  arm946_flush_kern_cache_louis
+       .equ    arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm946
 
index 23a8e4c7f2bdc5c8a2431e3aba75eea54e08a6b7..4106b09e0c29ad07530e095ca361e84f92489d32 100644 (file)
@@ -415,6 +415,9 @@ ENTRY(feroceon_dma_unmap_area)
        mov     pc, lr
 ENDPROC(feroceon_dma_unmap_area)
 
+       .globl  feroceon_flush_kern_cache_louis
+       .equ    feroceon_flush_kern_cache_louis, feroceon_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions feroceon
 
@@ -431,6 +434,7 @@ ENDPROC(feroceon_dma_unmap_area)
        range_alias flush_icache_all
        range_alias flush_user_cache_all
        range_alias flush_kern_cache_all
+       range_alias flush_kern_cache_louis
        range_alias flush_user_cache_range
        range_alias coherent_kern_range
        range_alias coherent_user_range
index 2d8ff3ad86d3e1a2b9d9abd83a1bdd3ab42eba3a..b29a2265af01b56f4c911b4c74fdd2cfadc3f892 100644 (file)
@@ -299,6 +299,7 @@ ENTRY(\name\()_processor_functions)
 ENTRY(\name\()_cache_fns)
        .long   \name\()_flush_icache_all
        .long   \name\()_flush_kern_cache_all
+       .long   \name\()_flush_kern_cache_louis
        .long   \name\()_flush_user_cache_all
        .long   \name\()_flush_user_cache_range
        .long   \name\()_coherent_kern_range
index fbb2124a547d125266d35cbce88348506c1eab65..82f9cdc751d6421d01bcb4eca3de51dd211f1868 100644 (file)
@@ -303,6 +303,9 @@ ENTRY(mohawk_dma_unmap_area)
        mov     pc, lr
 ENDPROC(mohawk_dma_unmap_area)
 
+       .globl  mohawk_flush_kern_cache_louis
+       .equ    mohawk_flush_kern_cache_louis, mohawk_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions mohawk
 
index c2e2b66f72b5cd08648085c28ffc5d8c2ee8359a..846d279f31764d7803fc6144df9517087286c768 100644 (file)
@@ -172,7 +172,7 @@ __v7_ca15mp_setup:
 __v7_setup:
        adr     r12, __v7_setup_stack           @ the local stack
        stmia   r12, {r0-r5, r7, r9, r11, lr}
-       bl      v7_flush_dcache_all
+       bl      v7_flush_dcache_louis
        ldmia   r12, {r0-r5, r7, r9, r11, lr}
 
        mrc     p15, 0, r0, c0, c0, 0           @ read main ID register
index b0d57869da2d95f1af47702bf039f3ef90ad5f02..eb93d6487f3598fcb0cc6e92c0f3e23faa36fb11 100644 (file)
@@ -337,6 +337,9 @@ ENTRY(xsc3_dma_unmap_area)
        mov     pc, lr
 ENDPROC(xsc3_dma_unmap_area)
 
+       .globl  xsc3_flush_kern_cache_louis
+       .equ    xsc3_flush_kern_cache_louis, xsc3_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions xsc3
 
index 4ffebaa595eec597d37e556bd66edc4af28f2a20..25510361aa181e7200d6f69a64d41ff6b8f8a8a6 100644 (file)
@@ -410,6 +410,9 @@ ENTRY(xscale_dma_unmap_area)
        mov     pc, lr
 ENDPROC(xscale_dma_unmap_area)
 
+       .globl  xscale_flush_kern_cache_louis
+       .equ    xscale_flush_kern_cache_louis, xscale_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions xscale
 
@@ -439,6 +442,7 @@ ENDPROC(xscale_dma_unmap_area)
        a0_alias flush_icache_all
        a0_alias flush_user_cache_all
        a0_alias flush_kern_cache_all
+       a0_alias flush_kern_cache_louis
        a0_alias flush_user_cache_range
        a0_alias coherent_kern_range
        a0_alias coherent_user_range
index 826de74bfdd127a8ca5b763aa79336ccfda75dd8..c08a54d9d8897dd686462787d8d205206e00da84 100644 (file)
 #define NMK_GPIO_ALT_B 2
 #define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
 
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1        ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2        ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3        ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4        ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
 /* Pull up/down values */
 enum nmk_gpio_pull {
        NMK_GPIO_PULL_NONE,
index 9c949c7c98a73e810558a542cb85608cad152f3c..3b8ec60af351500a5cbcb80c970b8026c7d8477d 100644 (file)
@@ -25,6 +25,8 @@
  *     bit 19..20 - SLPM direction
  *     bit 21..22 - SLPM Value (if output)
  *     bit 23..25 - PDIS value (if input)
+ *     bit     26 - Gpio mode
+ *     bit     27 - Sleep mode
  *
  * to facilitate the definition, the following macros are provided
  *
index 683c466c0e6a7242200a5f637a981ef011577bf8..147459327601ce50c85269b9b6143f2d072c60cd 100644 (file)
 #include <linux/spinlock.h>
 #include <mach/regs-clock.h>
 
-static int __s5p_mipi_phy_control(struct platform_device *pdev,
-                                 bool on, u32 reset)
+static int __s5p_mipi_phy_control(int id, bool on, u32 reset)
 {
        static DEFINE_SPINLOCK(lock);
        void __iomem *addr;
        unsigned long flags;
-       int pid;
        u32 cfg;
 
-       if (!pdev)
+       id = max(0, id);
+       if (id > 1)
                return -EINVAL;
 
-       pid = (pdev->id == -1) ? 0 : pdev->id;
-
-       if (pid != 0 && pid != 1)
-               return -EINVAL;
-
-       addr = S5P_MIPI_DPHY_CONTROL(pid);
+       addr = S5P_MIPI_DPHY_CONTROL(id);
 
        spin_lock_irqsave(&lock, flags);
 
@@ -52,12 +46,12 @@ static int __s5p_mipi_phy_control(struct platform_device *pdev,
        return 0;
 }
 
-int s5p_csis_phy_enable(struct platform_device *pdev, bool on)
+int s5p_csis_phy_enable(int id, bool on)
 {
-       return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN);
+       return __s5p_mipi_phy_control(id, on, S5P_MIPI_DPHY_SRESETN);
 }
 
 int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
 {
-       return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN);
+       return __s5p_mipi_phy_control(pdev->id, on, S5P_MIPI_DPHY_MRESETN);
 }
index 3c720ef6c32de0f8d57b2439ae5f76a2346cc02e..4c10e607c908cb59a444c8f7f185eeab323bfa1d 100644 (file)
@@ -39,7 +39,7 @@ config IA64
        select ARCH_TASK_STRUCT_ALLOCATOR
        select ARCH_THREAD_INFO_ALLOCATOR
        select ARCH_CLOCKSOURCE_DATA
-       select GENERIC_TIME_VSYSCALL
+       select GENERIC_TIME_VSYSCALL_OLD
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
index 80ff9acc5edfeb674e889a4f263553877a07f4b4..f6388216080d72fbd4547beb6e229a0e02cf7eff 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/efi.h>
 #include <linux/timex.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/platform_device.h>
 
 #include <asm/machvec.h>
@@ -454,7 +454,7 @@ void update_vsyscall_tz(void)
 {
 }
 
-void update_vsyscall(struct timespec *wall, struct timespec *wtm,
+void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
                        struct clocksource *c, u32 mult)
 {
        write_seqcount_begin(&fsyscall_gtod_data.seq);
index 78d6588b6e8622efd2860627b7deb8f0af389be0..969f3d9ded91941cb4323052df4f465764259608 100644 (file)
@@ -137,7 +137,7 @@ config PPC
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_CMOS_UPDATE
-       select GENERIC_TIME_VSYSCALL
+       select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
index c9986fd400d89947966d4e94746f8d8c9913b7a2..ce4cb772dc7833f502e8521fe57ed6eb646c46d5 100644 (file)
@@ -73,7 +73,7 @@
 /* powerpc clocksource/clockevent code */
 
 #include <linux/clockchips.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 
 static cycle_t rtc_read(struct clocksource *);
 static struct clocksource clocksource_rtc = {
@@ -727,7 +727,7 @@ static cycle_t timebase_read(struct clocksource *cs)
        return (cycle_t)get_tb();
 }
 
-void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
                        struct clocksource *clock, u32 mult)
 {
        u64 new_tb_to_xs, new_stamp_xsec;
index 99d2d790d1528c256c2fe6c2099fdc0809988382..e5dac123618519051f776b78b74c869d2267d693 100644 (file)
@@ -131,7 +131,7 @@ config S390
        select HAVE_UID16 if 32BIT
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_SMP_IDLE_THREAD
-       select GENERIC_TIME_VSYSCALL
+       select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
        select KTIME_SCALAR if 32BIT
        select HAVE_ARCH_SECCOMP_FILTER
index 2db1011b8b1974a3de5b387b7ee2d68ca6fc18b9..7fcd690d42c753bfd027d00b05da12e35cf711cd 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/notifier.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/clockchips.h>
 #include <linux/gfp.h>
 #include <linux/kprobes.h>
@@ -219,7 +219,7 @@ struct clocksource * __init clocksource_default_clock(void)
        return &clocksource_tod;
 }
 
-void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
                        struct clocksource *clock, u32 mult)
 {
        if (clock != &clocksource_tod)
index 8b38be2de9e15a7cf149b3c088aac074f1be0463..46e24d36b7da12dc641e4718d0d80e42ca923751 100644 (file)
@@ -17,8 +17,8 @@ struct vsyscall_gtod_data {
 
        /* open coded 'struct timespec' */
        time_t          wall_time_sec;
-       u32             wall_time_nsec;
-       u32             monotonic_time_nsec;
+       u64             wall_time_snsec;
+       u64             monotonic_time_snsec;
        time_t          monotonic_time_sec;
 
        struct timezone sys_tz;
index d609be046b5749991c01919561055072d717f970..a2bb18e02839489dcbf9dbc1e3d348f5fb176c34 100644 (file)
@@ -68,6 +68,7 @@
 #include <linux/percpu.h>
 #include <linux/crash_dump.h>
 #include <linux/tboot.h>
+#include <linux/jiffies.h>
 
 #include <video/edid.h>
 
@@ -1032,6 +1033,8 @@ void __init setup_arch(char **cmdline_p)
        mcheck_init();
 
        arch_init_ideal_nops();
+
+       register_refined_jiffies(CLOCK_TICK_RATE);
 }
 
 #ifdef CONFIG_X86_32
index 8d141b30904657871358a4fb8deb927c7a022257..3a3e8c9e280dcac9ba655491b4300c1d698bfb5a 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/jiffies.h>
 #include <linux/sysctl.h>
 #include <linux/topology.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/getcpu.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
@@ -82,32 +82,41 @@ void update_vsyscall_tz(void)
        vsyscall_gtod_data.sys_tz = sys_tz;
 }
 
-void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
-                       struct clocksource *clock, u32 mult)
+void update_vsyscall(struct timekeeper *tk)
 {
-       struct timespec monotonic;
+       struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
 
-       write_seqcount_begin(&vsyscall_gtod_data.seq);
+       write_seqcount_begin(&vdata->seq);
 
        /* copy vsyscall data */
-       vsyscall_gtod_data.clock.vclock_mode    = clock->archdata.vclock_mode;
-       vsyscall_gtod_data.clock.cycle_last     = clock->cycle_last;
-       vsyscall_gtod_data.clock.mask           = clock->mask;
-       vsyscall_gtod_data.clock.mult           = mult;
-       vsyscall_gtod_data.clock.shift          = clock->shift;
-
-       vsyscall_gtod_data.wall_time_sec        = wall_time->tv_sec;
-       vsyscall_gtod_data.wall_time_nsec       = wall_time->tv_nsec;
+       vdata->clock.vclock_mode        = tk->clock->archdata.vclock_mode;
+       vdata->clock.cycle_last         = tk->clock->cycle_last;
+       vdata->clock.mask               = tk->clock->mask;
+       vdata->clock.mult               = tk->mult;
+       vdata->clock.shift              = tk->shift;
+
+       vdata->wall_time_sec            = tk->xtime_sec;
+       vdata->wall_time_snsec          = tk->xtime_nsec;
+
+       vdata->monotonic_time_sec       = tk->xtime_sec
+                                       + tk->wall_to_monotonic.tv_sec;
+       vdata->monotonic_time_snsec     = tk->xtime_nsec
+                                       + (tk->wall_to_monotonic.tv_nsec
+                                               << tk->shift);
+       while (vdata->monotonic_time_snsec >=
+                                       (((u64)NSEC_PER_SEC) << tk->shift)) {
+               vdata->monotonic_time_snsec -=
+                                       ((u64)NSEC_PER_SEC) << tk->shift;
+               vdata->monotonic_time_sec++;
+       }
 
-       monotonic = timespec_add(*wall_time, *wtm);
-       vsyscall_gtod_data.monotonic_time_sec   = monotonic.tv_sec;
-       vsyscall_gtod_data.monotonic_time_nsec  = monotonic.tv_nsec;
+       vdata->wall_time_coarse.tv_sec  = tk->xtime_sec;
+       vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
 
-       vsyscall_gtod_data.wall_time_coarse     = __current_kernel_time();
-       vsyscall_gtod_data.monotonic_time_coarse =
-               timespec_add(vsyscall_gtod_data.wall_time_coarse, *wtm);
+       vdata->monotonic_time_coarse    = timespec_add(vdata->wall_time_coarse,
+                                                       tk->wall_to_monotonic);
 
-       write_seqcount_end(&vsyscall_gtod_data.seq);
+       write_seqcount_end(&vdata->seq);
 }
 
 static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
index 885eff49d6abe61c2bdfc3c6673acb69678f161b..4df6c373421a435dfeac34d68407ce10602d688d 100644 (file)
@@ -80,7 +80,7 @@ notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz)
 }
 
 
-notrace static inline long vgetns(void)
+notrace static inline u64 vgetsns(void)
 {
        long v;
        cycles_t cycles;
@@ -91,21 +91,24 @@ notrace static inline long vgetns(void)
        else
                return 0;
        v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
-       return (v * gtod->clock.mult) >> gtod->clock.shift;
+       return v * gtod->clock.mult;
 }
 
 /* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
 notrace static int __always_inline do_realtime(struct timespec *ts)
 {
-       unsigned long seq, ns;
+       unsigned long seq;
+       u64 ns;
        int mode;
 
+       ts->tv_nsec = 0;
        do {
                seq = read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
-               ts->tv_nsec = gtod->wall_time_nsec;
-               ns = vgetns();
+               ns = gtod->wall_time_snsec;
+               ns += vgetsns();
+               ns >>= gtod->clock.shift;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
 
        timespec_add_ns(ts, ns);
@@ -114,15 +117,18 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
 
 notrace static int do_monotonic(struct timespec *ts)
 {
-       unsigned long seq, ns;
+       unsigned long seq;
+       u64 ns;
        int mode;
 
+       ts->tv_nsec = 0;
        do {
                seq = read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->monotonic_time_sec;
-               ts->tv_nsec = gtod->monotonic_time_nsec;
-               ns = vgetns();
+               ns = gtod->monotonic_time_snsec;
+               ns += vgetsns();
+               ns >>= gtod->clock.shift;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
        timespec_add_ns(ts, ns);
 
index bf788d34530df5fbb93e60bb64023d80f7bbedf3..e3497f240eabb869e6cda863036689e6b093899d 100644 (file)
@@ -987,7 +987,16 @@ static void xen_write_cr4(unsigned long cr4)
 
        native_write_cr4(cr4);
 }
-
+#ifdef CONFIG_X86_64
+static inline unsigned long xen_read_cr8(void)
+{
+       return 0;
+}
+static inline void xen_write_cr8(unsigned long val)
+{
+       BUG_ON(val);
+}
+#endif
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
        int ret;
@@ -1156,6 +1165,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_cr4_safe = native_read_cr4_safe,
        .write_cr4 = xen_write_cr4,
 
+#ifdef CONFIG_X86_64
+       .read_cr8 = xen_read_cr8,
+       .write_cr8 = xen_write_cr8,
+#endif
+
        .wbinvd = native_wbinvd,
 
        .read_msr = native_read_msr_safe,
@@ -1164,6 +1178,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
 
+       .read_tscp = native_read_tscp,
+
        .iret = xen_iret,
        .irq_enable_sysexit = xen_sysexit,
 #ifdef CONFIG_X86_64
index fd28d86fe3d2c979c5c9ac0e5ab95bf3d977a224..6226c99729b963594a2e133290cbf8f3c6e681b8 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <linux/seq_file.h>
+#include <linux/crash_dump.h>
 
 #include <trace/events/xen.h>
 
@@ -2381,6 +2382,43 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
 EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
 
 #ifdef CONFIG_XEN_PVHVM
+#ifdef CONFIG_PROC_VMCORE
+/*
+ * This function is used in two contexts:
+ * - the kdump kernel has to check whether a pfn of the crashed kernel
+ *   was a ballooned page. vmcore is using this function to decide
+ *   whether to access a pfn of the crashed kernel.
+ * - the kexec kernel has to check whether a pfn was ballooned by the
+ *   previous kernel. If the pfn is ballooned, handle it properly.
+ * Returns 0 if the pfn is not backed by a RAM page, the caller may
+ * handle the pfn special in this case.
+ */
+static int xen_oldmem_pfn_is_ram(unsigned long pfn)
+{
+       struct xen_hvm_get_mem_type a = {
+               .domid = DOMID_SELF,
+               .pfn = pfn,
+       };
+       int ram;
+
+       if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a))
+               return -ENXIO;
+
+       switch (a.mem_type) {
+               case HVMMEM_mmio_dm:
+                       ram = 0;
+                       break;
+               case HVMMEM_ram_rw:
+               case HVMMEM_ram_ro:
+               default:
+                       ram = 1;
+                       break;
+       }
+
+       return ram;
+}
+#endif
+
 static void xen_hvm_exit_mmap(struct mm_struct *mm)
 {
        struct xen_hvm_pagetable_dying a;
@@ -2411,6 +2449,9 @@ void __init xen_hvm_init_mmu_ops(void)
 {
        if (is_pagetable_dying_supported())
                pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
+#ifdef CONFIG_PROC_VMCORE
+       register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram);
+#endif
 }
 #endif
 
index 8f58f241c10dfa7047f92423cb917c67d908f4b1..7e92793260f0deffbf6bdb0a3024a95f3bf59ff5 100644 (file)
@@ -966,6 +966,8 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
                break;
        }
 
+       c->lna = LNA_AUTO;
+
        return 0;
 }
 
@@ -1054,6 +1056,8 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
        _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
        _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
+
+       _DTV_CMD(DTV_LNA, 0, 0),
 };
 
 static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
@@ -1440,6 +1444,10 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
                tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d;
                break;
 
+       case DTV_LNA:
+               tvp->u.data = c->lna;
+               break;
+
        default:
                return -EINVAL;
        }
@@ -1731,10 +1739,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
        case DTV_INTERLEAVING:
                c->interleaving = tvp->u.data;
                break;
-       case DTV_LNA:
-               if (fe->ops.set_lna)
-                       r = fe->ops.set_lna(fe, tvp->u.data);
-               break;
 
        /* ISDB-T Support here */
        case DTV_ISDBT_PARTIAL_RECEPTION:
@@ -1806,6 +1810,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
                fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data;
                break;
 
+       case DTV_LNA:
+               c->lna = tvp->u.data;
+               if (fe->ops.set_lna)
+                       r = fe->ops.set_lna(fe);
+               break;
+
        default:
                return -EINVAL;
        }
@@ -2309,7 +2319,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                fepriv->tune_mode_flags = (unsigned long) parg;
                err = 0;
                break;
-       };
+       }
 
        return err;
 }
index 44a445cee74f53b2fe5aa010323bd09308f293b1..97112cd88a177f4ad66fafa8bd66e540aaf86dcf 100644 (file)
@@ -303,7 +303,7 @@ struct dvb_frontend_ops {
        int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
        int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
        int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
-       int (*set_lna)(struct dvb_frontend *, int);
+       int (*set_lna)(struct dvb_frontend *);
 
        /* These callbacks are for devices that implement their own
         * tuning algorithms, rather than a simple swzigzag
@@ -391,6 +391,8 @@ struct dtv_frontend_properties {
        u8                      atscmh_sccc_code_mode_b;
        u8                      atscmh_sccc_code_mode_c;
        u8                      atscmh_sccc_code_mode_d;
+
+       u32                     lna;
 };
 
 struct dvb_frontend {
index cff44a389b404c1c492fe7e25d7925a29b076d05..74fbb5d58bed73a28d2c1f7356f0b732b78b67a5 100644 (file)
@@ -90,7 +90,7 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
        default:
                ret = -EINVAL;
                goto err;
-       };
+       }
 
        ret = a8293_wr(priv, &priv->reg[0], 1);
        if (ret)
index e9f04a36577b582849f5f5d9ae29f7466462dac0..a204f2828820412f94152928f9ba20e9126b25e6 100644 (file)
@@ -241,7 +241,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
                                KBUILD_MODNAME, gpio);
                ret = -EINVAL;
                goto err;
-       };
+       }
 
        switch (gpio) {
        case 0:
@@ -253,7 +253,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
        default:
                pos = 4;
                break;
-       };
+       }
 
        ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval);
        if (ret)
@@ -726,7 +726,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
        default:
                dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__);
                auto_mode = 1;
-       };
+       }
 
        switch (c->modulation) {
        case QAM_AUTO:
index 8162d939c4b2d460a2d12111b256e6600dc19f6f..464ad878490bb5026dcd5a2ffd9ae95004c17366 100644 (file)
@@ -408,7 +408,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
 {
        struct af9033_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int ret, i, spec_inv;
+       int ret, i, spec_inv, sampling_freq;
        u8 tmp, buf[3], bandwidth_reg_val;
        u32 if_frequency, freq_cw, adc_freq;
 
@@ -465,18 +465,20 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
                else
                        if_frequency = 0;
 
-               while (if_frequency > (adc_freq / 2))
-                       if_frequency -= adc_freq;
+               sampling_freq = if_frequency;
 
-               if (if_frequency >= 0)
+               while (sampling_freq > (adc_freq / 2))
+                       sampling_freq -= adc_freq;
+
+               if (sampling_freq >= 0)
                        spec_inv *= -1;
                else
-                       if_frequency *= -1;
+                       sampling_freq *= -1;
 
-               freq_cw = af9033_div(state, if_frequency, adc_freq, 23ul);
+               freq_cw = af9033_div(state, sampling_freq, adc_freq, 23ul);
 
                if (spec_inv == -1)
-                       freq_cw *= -1;
+                       freq_cw = 0x800000 - freq_cw;
 
                /* get adc multiplies */
                ret = af9033_rd_reg(state, 0x800045, &tmp);
index 033cd7ad3ca2cb9d76f7bace048fdb1f72974bdd..1b77909c0c7116c3cff03b6788912a29c2f240f3 100644 (file)
@@ -527,7 +527,7 @@ static int bcm3510_set_frontend(struct dvb_frontend *fe)
                        cmd.ACQUIRE1.IF_FREQ = 0x0;
                default:
                        return -EINVAL;
-       };
+       }
        cmd.ACQUIRE0.OFFSET = 0;
        cmd.ACQUIRE0.NTSCSWEEP = 1;
        cmd.ACQUIRE0.FA = 1;
index 3180f5b2a6a60d8bf3930876e788b3217efa8814..0cd6927e654c110b804def49677b71f8b26cc1a9 100644 (file)
@@ -218,7 +218,7 @@ static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
           } else
                   return -EOPNOTSUPP;
 /* fixme (low): which is the correct return code? */
-       };
+       }
        return 0;
 }
 
@@ -275,7 +275,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
                cx24110_writereg(state,0x07,tmp|0x3);
                cx24110_writereg(state,0x06,0x78);
                fclk=90999000UL;
-       };
+       }
        dprintk("cx24110 debug: fclk %d Hz\n",fclk);
        /* we need to divide two integers with approx. 27 bits in 32 bit
           arithmetic giving a 25 bit result */
@@ -362,7 +362,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
 
        for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
                cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
-       };
+       }
 
        return 0;
 }
index 42648643693e0ab1fe06bb6975a0d40f8db54968..9b658c1cf39a48b77edd9341140bae751e80a527 100644 (file)
@@ -688,7 +688,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
 {
        struct cxd2820r_priv *priv;
        int ret;
-       u8 tmp, gpio[GPIO_COUNT];
+       u8 tmp;
 
        priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
        if (!priv) {
@@ -735,6 +735,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
                 * Use static GPIO configuration if GPIOLIB is undefined.
                 * This is fallback condition.
                 */
+               u8 gpio[GPIO_COUNT];
                gpio[0] = (*gpio_chip_base >> 0) & 0x07;
                gpio[1] = (*gpio_chip_base >> 3) & 0x07;
                gpio[2] = 0;
index f380eb43e9d5a66137fcff49615c1342040d158a..6d9853750d2b6dd96080dc68fb0dc1496626ddf4 100644 (file)
@@ -991,7 +991,7 @@ static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult)
                if (nrRetries > DRXD_MAX_RETRIES) {
                        status = -1;
                        break;
-               };
+               }
                status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0);
        } while (waitCmd != 0);
 
index 4c8ac2657c4af0d602c0d776a8b98a03efcfdc21..5b639087ce45623f7a2f1be7e1b6216c1bc686a8 100644 (file)
@@ -30,6 +30,7 @@
 #include "ds3000.h"
 
 static int debug;
+static int force_fw_upload;
 
 #define dprintk(args...) \
        do { \
@@ -392,11 +393,13 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
 
        dprintk("%s()\n", __func__);
 
-       if (ds3000_readreg(state, 0xb2) <= 0)
+       ret = ds3000_readreg(state, 0xb2);
+       if (ret < 0)
                return ret;
 
-       if (state->skip_fw_load)
-               return 0;
+       if (state->skip_fw_load || !force_fw_upload)
+               return 0;       /* Firmware already uploaded, skipping */
+
        /* Load firmware */
        /* request the firmware, this will block until someone uploads it */
        printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
@@ -1306,6 +1309,9 @@ static struct dvb_frontend_ops ds3000_ops = {
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 
+module_param(force_fw_upload, int, 0644);
+MODULE_PARM_DESC(force_fw_upload, "Force firmware upload (default:0)");
+
 MODULE_DESCRIPTION("DVB Frontend module for Montage Technology "
                        "DS3000/TS2020 hardware");
 MODULE_AUTHOR("Konstantin Dimitrov");
index dcfc902c8678be0c64b04989f549639e8114fa47..d5acc304786bf9b3531212b60501da308ff0937e 100644 (file)
@@ -121,16 +121,13 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (!state)
+               return NULL;
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
@@ -141,16 +138,13 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (!state)
+               return NULL;
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
@@ -161,16 +155,13 @@ struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (!state)
+               return NULL;
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
index 33d33f4d8867a409d15e32bbc4d45991efdd14c9..0c642a5bf8235462da1a26d3b407a58432dc6138 100644 (file)
@@ -77,7 +77,7 @@ static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
                        break;
                default:
                        return -EINVAL;
-               };
+               }
        }
        isl6405->config |= isl6405->override_or;
        isl6405->config &= isl6405->override_and;
index 684c8ec166cbc7bfbdaed883a18c664ec59dd428..0cb3f0f74c9c9040b48f586212fae0680ad02145 100644 (file)
@@ -63,7 +63,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        isl6421->config |= isl6421->override_or;
        isl6421->config &= isl6421->override_and;
index 316457584fe7a6fe7a18ae430fe1c194393dbf7c..c1c3400b2173508d3ce2ba77b236d16c2eec48c9 100644 (file)
@@ -231,7 +231,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
        state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
        itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln);
 
-       itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
+       itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */
        itd1000_write_reg(state, PLLNL, plln & 0xff);
        itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
        itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
index cc11260e99df96f7ce19837e6ba268811aa825cf..5fd14f840ab0ffcd38cc32656a24fae3684c62c0 100644 (file)
@@ -1421,8 +1421,8 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
               config ? config->i2c_addr : 0);
 
        state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
-       if (state == NULL)
-               goto fail;
+       if (!state)
+               return NULL;
 
        state->cfg = config;
        state->i2c_adap = i2c_adap;
@@ -1449,10 +1449,6 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
        state->frontend.dtv_property_cache.atscmh_parade_id = 1;
 
        return &state->frontend;
-fail:
-       lg_warn("unable to detect LG216x hardware\n");
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL(lg2160_attach);
 
index 13437259eeac211d69ef8c0cd8f4c96ce9103998..f3ba7b5faa2ed9fdfcda57391dfdaac73a189287 100644 (file)
@@ -65,7 +65,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        lnbp21->config |= lnbp21->override_or;
        lnbp21->config &= lnbp21->override_and;
@@ -108,7 +108,7 @@ static int lnbp21_set_tone(struct dvb_frontend *fe,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        lnbp21->config |= lnbp21->override_or;
        lnbp21->config &= lnbp21->override_and;
index 84ad0390a4a12db9a6c201f2749bed749b97011b..c463da7f6dcceb53b77a7cd5f3360238d8ebde59 100644 (file)
@@ -73,7 +73,7 @@ static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
        return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
index 8352ce1c95563798c06f86e4b0f68bec85c6cd7f..6ec16a24374172f9eb3052e9b1c27e6463be95bb 100644 (file)
@@ -351,8 +351,8 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
        printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n");
        /* allocate memory for the internal state */
        state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (!state)
+               return NULL;
 
        /* setup the state */
        state->config = config;
@@ -367,10 +367,6 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
        state->frontend.demodulator_priv = state;
 
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL(s5h1432_attach);
 
index cd2288c07147a7614d7d37ef0022400e6b05d318..a271ac3eaec04dc4e85c62a616837bfb4f27ff4f 100644 (file)
@@ -487,9 +487,9 @@ struct dvb_frontend *s921_attach(const struct s921_config *config,
                kzalloc(sizeof(struct s921_state), GFP_KERNEL);
 
        dprintk("\n");
-       if (state == NULL) {
+       if (!state) {
                rc("Unable to kzalloc\n");
-               goto rcor;
+               return NULL;
        }
 
        /* setup the state */
@@ -502,11 +502,6 @@ struct dvb_frontend *s921_attach(const struct s921_config *config,
        state->frontend.demodulator_priv = state;
 
        return &state->frontend;
-
-rcor:
-       kfree(state);
-
-       return NULL;
 }
 EXPORT_SYMBOL(s921_attach);
 
index a68a64800df77ff7123ae6d18434820d6c95a2b4..73b47cc6a13b3b8c2f6ca85d0ee1d9eee71120c1 100644 (file)
@@ -343,7 +343,7 @@ static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
                        return -ETIMEDOUT;
                }
                msleep(10);
-       };
+       }
 
        return 0;
 }
@@ -472,7 +472,7 @@ static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
                break;
        default:
                return -EINVAL;
-       };
+       }
 }
 
 static int si21xx_init(struct dvb_frontend *fe)
index e37274c8f14e004c6058c64d053304704f8196ee..2aa8ef76eba259efba6490590f5201f0882e5805 100644 (file)
@@ -188,7 +188,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->hierarchy) {
        case HIERARCHY_NONE:
@@ -207,7 +207,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->code_rate_HP) {
        case FEC_1_2:
@@ -229,7 +229,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        if (known_parameters)
                *reg0xc05 |= (2 << 1);  /* use specified parameters */
index f4096ccb226e4b76146e001a4d78db1f52d7d756..1bb81b5ae6e0c69516ed4b7a65c9bef1280459ab 100644 (file)
@@ -229,7 +229,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->hierarchy) {
        case HIERARCHY_NONE:
@@ -248,7 +248,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->code_rate_HP) {
        case FEC_1_2:
@@ -270,7 +270,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        if (known_parameters)
                *reg0xc05 |= (2 << 1);  /* use specified parameters */
index 2e93e65d2cdb0e336f881d8b0b5efbd50fd1bbce..45f9523f968f903d463d56f5baf927662b7ffbc0 100644 (file)
@@ -575,8 +575,8 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
        struct stb6100_state *state = NULL;
 
        state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (!state)
+               return NULL;
 
        state->config           = config;
        state->i2c              = i2c;
@@ -587,10 +587,6 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
 
        printk("%s: Attaching STB6100 \n", __func__);
        return fe;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static int stb6100_release(struct dvb_frontend *fe)
index 057b5f8effc0dec16c24f3753329bf8ed354e8bb..92a6075cd82f343f0f91fcd0b6cb13b4f07972fd 100644 (file)
@@ -199,7 +199,7 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
                        return -ETIMEDOUT;
                }
                msleep(10);
-       };
+       }
 
        return 0;
 }
@@ -216,7 +216,7 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
                        return -ETIMEDOUT;
                }
                msleep(10);
-       };
+       }
 
        return 0;
 }
@@ -387,7 +387,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        if (state->config->op0_off)
                reg0x0c &= ~0x10;
index 7f1badaf0d03044b2c2e4779ed746e2d03bbae0c..262dfa503c2a3e2db6cca50a5028d57ca46736df 100644 (file)
@@ -1552,8 +1552,8 @@ static int stv0900_status(struct stv0900_internal *intp,
                bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000)
                        * (tsbitrate1_val << 8 | tsbitrate0_val);
                bitrate /= 16384;
-               dprintk("TS bitrate = %d Mbit/sec \n", bitrate);
-       };
+               dprintk("TS bitrate = %d Mbit/sec\n", bitrate);
+       }
 
        return locked;
 }
index 2c1c759a4f42f2ee1b073bba1b4d127da1d00f6b..63cc12378d9aac4cfc7c2ad23be3e851ce9e361e 100644 (file)
@@ -228,8 +228,8 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
        struct dvb_tuner_info *info;
 
        state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
-       if (state == NULL)
-               goto exit;
+       if (!state)
+               return NULL;
 
        state->config           = config;
        state->i2c              = i2c;
@@ -246,10 +246,6 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
        printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
 
        return fe;
-
-exit:
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL(tda665x_attach);
 
index 15912c96926adde19a7fbb7c50663efb146ccdf3..9d08350fe4b035cca635d3368d75591897e4e035 100644 (file)
@@ -175,7 +175,7 @@ static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
               !(tda8083_readreg(state, 0x02) & 0x80))
        {
                msleep(50);
-       };
+       }
 }
 
 static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone)
@@ -215,7 +215,7 @@ static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_c
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        tda8083_wait_diseqc_fifo (state, 100);
 
index d8eac3e30a7ea99217e5b149de79752e73f594cf..2cee69e34184304b7824752aadfd14d4b1d205b8 100644 (file)
@@ -599,7 +599,7 @@ static void cx23885_initialize(struct i2c_client *client)
                cx25840_write4(client, 0x114, 0x01bf0c9e);
                cx25840_write4(client, 0x110, 0x000a030c);
                break;
-       };
+       }
 
        /* ADC2 input select */
        cx25840_write(client, 0x102, 0x10);
index 86c815be348cbe9214de2f87d1915b01a2452555..90a6c520f115587f96d5e0174c01dd55480bd768 100644 (file)
 #ifndef M5MOLS_H
 #define M5MOLS_H
 
+#include <linux/sizes.h>
 #include <media/v4l2-subdev.h>
 #include "m5mols_reg.h"
 
+
+/* An amount of data transmitted in addition to the value
+ * determined by CAPP_JPEG_SIZE_MAX register.
+ */
+#define M5MOLS_JPEG_TAGS_SIZE          0x20000
+#define M5MOLS_MAIN_JPEG_SIZE_MAX      (5 * SZ_1M)
+
 extern int m5mols_debug;
 
 enum m5mols_restype {
@@ -67,12 +75,14 @@ struct m5mols_exif {
 /**
  * struct m5mols_capture - Structure for the capture capability
  * @exif: EXIF information
+ * @buf_size: internal JPEG frame buffer size, in bytes
  * @main: size in bytes of the main image
  * @thumb: size in bytes of the thumb image, if it was accompanied
  * @total: total size in bytes of the produced image
  */
 struct m5mols_capture {
        struct m5mols_exif exif;
+       unsigned int buf_size;
        u32 main;
        u32 thumb;
        u32 total;
index cb243bd278ceecce60163b6eed41ce8cb2d5c019..ab34ccedf31ea7a1a72adfe9d3324103de92b7f7 100644 (file)
@@ -105,6 +105,7 @@ static int m5mols_capture_info(struct m5mols_info *info)
 
 int m5mols_start_capture(struct m5mols_info *info)
 {
+       unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE;
        struct v4l2_subdev *sd = &info->sd;
        int ret;
 
@@ -120,6 +121,8 @@ int m5mols_start_capture(struct m5mols_info *info)
                ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
        if (!ret)
                ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
+       if (!ret)
+               ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize);
        if (!ret)
                ret = m5mols_set_mode(info, REG_CAPTURE);
        if (!ret)
index 2f490ef26c388e2b868369dd189299430288efa3..8131d651de9ef11ea5c10d8e4111e9c8e4468896 100644 (file)
@@ -599,6 +599,51 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return ret;
 }
 
+static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+                                struct v4l2_mbus_frame_desc *fd)
+{
+       struct m5mols_info *info = to_m5mols(sd);
+
+       if (pad != 0 || fd == NULL)
+               return -EINVAL;
+
+       mutex_lock(&info->lock);
+       /*
+        * .get_frame_desc is only used for compressed formats,
+        * thus we always return the capture frame parameters here.
+        */
+       fd->entry[0].length = info->cap.buf_size;
+       fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
+       mutex_unlock(&info->lock);
+
+       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+       fd->num_entries = 1;
+
+       return 0;
+}
+
+static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+                                struct v4l2_mbus_frame_desc *fd)
+{
+       struct m5mols_info *info = to_m5mols(sd);
+       struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
+
+       if (pad != 0 || fd == NULL)
+               return -EINVAL;
+
+       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+       fd->num_entries = 1;
+       fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
+                                     mf->width * mf->height,
+                                     M5MOLS_MAIN_JPEG_SIZE_MAX);
+       mutex_lock(&info->lock);
+       info->cap.buf_size = fd->entry[0].length;
+       mutex_unlock(&info->lock);
+
+       return 0;
+}
+
+
 static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_fh *fh,
                                 struct v4l2_subdev_mbus_code_enum *code)
@@ -615,6 +660,8 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
        .enum_mbus_code = m5mols_enum_mbus_code,
        .get_fmt        = m5mols_get_fmt,
        .set_fmt        = m5mols_set_fmt,
+       .get_frame_desc = m5mols_get_frame_desc,
+       .set_frame_desc = m5mols_set_frame_desc,
 };
 
 /**
index 14d4be72aeff67b09c9dafc98416490b1acc3412..58d8027508dfe338a7b4497b2fe77793cdf3312e 100644 (file)
 #define REG_JPEG               0x10
 
 #define CAPP_MAIN_IMAGE_SIZE   I2C_REG(CAT_CAPT_PARM, 0x01, 1)
+#define CAPP_JPEG_SIZE_MAX     I2C_REG(CAT_CAPT_PARM, 0x0f, 4)
 #define CAPP_JPEG_RATIO                I2C_REG(CAT_CAPT_PARM, 0x17, 1)
 
 #define CAPP_MCC_MODE          I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
index 2c0f4077c4916215da4cff1580b79fbce27c4fe6..e32833262d32a6323c75f74e47dc89c9663d3ff4 100644 (file)
@@ -574,7 +574,6 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
 #define V4L2_CID_BLC_AUTO              (V4L2_CID_USER_BASE | 0x1002)
 #define V4L2_CID_BLC_TARGET_LEVEL      (V4L2_CID_USER_BASE | 0x1003)
 #define V4L2_CID_BLC_ANALOG_OFFSET     (V4L2_CID_USER_BASE | 0x1004)
@@ -739,18 +738,6 @@ static const char * const mt9p031_test_pattern_menu[] = {
 
 static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
        {
-               .ops            = &mt9p031_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
-               .type           = V4L2_CTRL_TYPE_MENU,
-               .name           = "Test Pattern",
-               .min            = 0,
-               .max            = ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
-               .step           = 0,
-               .def            = 0,
-               .flags          = 0,
-               .menu_skip_mask = 0,
-               .qmenu          = mt9p031_test_pattern_menu,
-       }, {
                .ops            = &mt9p031_ctrl_ops,
                .id             = V4L2_CID_BLC_AUTO,
                .type           = V4L2_CTRL_TYPE_BOOLEAN,
@@ -950,7 +937,7 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->model = did->driver_data;
        mt9p031->reset = -1;
 
-       v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5);
+       v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6);
 
        v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
                          V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
@@ -966,6 +953,10 @@ static int mt9p031_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
                          V4L2_CID_PIXEL_RATE, pdata->target_freq,
                          pdata->target_freq, 1, pdata->target_freq);
+       v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+                         V4L2_CID_TEST_PATTERN,
+                         ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0,
+                         0, mt9p031_test_pattern_menu);
 
        for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
                v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
index 6d343adf891d1a5497b4cb4a4ecebaaf9328d1d0..2e189d8b71bb218725b76d894172420d30bdfe6a 100644 (file)
@@ -371,7 +371,7 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_TEST_PATTERN_COLOR    (V4L2_CID_USER_BASE | 0x1001)
 #define V4L2_CID_BLACK_LEVEL_AUTO      (V4L2_CID_USER_BASE | 0x1002)
 #define V4L2_CID_BLACK_LEVEL_OFFSET    (V4L2_CID_USER_BASE | 0x1003)
 #define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004)
@@ -487,12 +487,11 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
                                     ctrl->val >> 16);
 
        case V4L2_CID_TEST_PATTERN:
-               ret = mt9t001_set_output_control(mt9t001,
+               return mt9t001_set_output_control(mt9t001,
                        ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
                        ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
-               if (ret < 0)
-                       return ret;
 
+       case V4L2_CID_TEST_PATTERN_COLOR:
                return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
 
        case V4L2_CID_BLACK_LEVEL_AUTO:
@@ -533,12 +532,17 @@ static struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
        .s_ctrl = mt9t001_s_ctrl,
 };
 
+static const char * const mt9t001_test_pattern_menu[] = {
+       "Disabled",
+       "Enabled",
+};
+
 static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
        {
                .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
+               .id             = V4L2_CID_TEST_PATTERN_COLOR,
                .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Test pattern",
+               .name           = "Test Pattern Color",
                .min            = 0,
                .max            = 1023,
                .step           = 1,
@@ -741,7 +745,7 @@ static int mt9t001_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
-                                               ARRAY_SIZE(mt9t001_gains) + 3);
+                                               ARRAY_SIZE(mt9t001_gains) + 4);
 
        v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
                          V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
@@ -752,6 +756,10 @@ static int mt9t001_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
                          V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
                          1, pdata->ext_clk);
+       v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+                       V4L2_CID_TEST_PATTERN,
+                       ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0,
+                       0, mt9t001_test_pattern_menu);
 
        for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
                v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
index e2177405dad2eb65de2bbc635727dca3f86099d1..3f356cb282567e882361b7958146090d9092cb43 100644 (file)
@@ -141,6 +141,10 @@ struct mt9v032 {
        u16 chip_control;
        u16 aec_agc;
        u16 hblank;
+       struct {
+               struct v4l2_ctrl *test_pattern;
+               struct v4l2_ctrl *test_pattern_color;
+       };
 };
 
 static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
@@ -500,7 +504,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_TEST_PATTERN_COLOR    (V4L2_CID_USER_BASE | 0x1001)
 
 static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -545,7 +549,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
                break;
 
        case V4L2_CID_TEST_PATTERN:
-               switch (ctrl->val) {
+               switch (mt9v032->test_pattern->val) {
                case 0:
                        data = 0;
                        break;
@@ -562,13 +566,13 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
                             | MT9V032_TEST_PATTERN_ENABLE;
                        break;
                default:
-                       data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT)
+                       data = (mt9v032->test_pattern_color->val <<
+                               MT9V032_TEST_PATTERN_DATA_SHIFT)
                             | MT9V032_TEST_PATTERN_USE_DATA
                             | MT9V032_TEST_PATTERN_ENABLE
                             | MT9V032_TEST_PATTERN_FLIP;
                        break;
                }
-
                return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
        }
 
@@ -579,18 +583,24 @@ static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
        .s_ctrl = mt9v032_s_ctrl,
 };
 
-static const struct v4l2_ctrl_config mt9v032_ctrls[] = {
-       {
-               .ops            = &mt9v032_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Test pattern",
-               .min            = 0,
-               .max            = 1023,
-               .step           = 1,
-               .def            = 0,
-               .flags          = 0,
-       }
+static const char * const mt9v032_test_pattern_menu[] = {
+       "Disabled",
+       "Gray Vertical Shade",
+       "Gray Horizontal Shade",
+       "Gray Diagonal Shade",
+       "Plain",
+};
+
+static const struct v4l2_ctrl_config mt9v032_test_pattern_color = {
+       .ops            = &mt9v032_ctrl_ops,
+       .id             = V4L2_CID_TEST_PATTERN_COLOR,
+       .type           = V4L2_CTRL_TYPE_INTEGER,
+       .name           = "Test Pattern Color",
+       .min            = 0,
+       .max            = 1023,
+       .step           = 1,
+       .def            = 0,
+       .flags          = 0,
 };
 
 /* -----------------------------------------------------------------------------
@@ -741,7 +751,7 @@ static int mt9v032_probe(struct i2c_client *client,
        mutex_init(&mt9v032->power_lock);
        mt9v032->pdata = pdata;
 
-       v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 8);
+       v4l2_ctrl_handler_init(&mt9v032->ctrls, 10);
 
        v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
                          V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@@ -763,6 +773,14 @@ static int mt9v032_probe(struct i2c_client *client,
                          V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN,
                          MT9V032_VERTICAL_BLANKING_MAX, 1,
                          MT9V032_VERTICAL_BLANKING_DEF);
+       mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls,
+                               &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN,
+                               ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0,
+                               mt9v032_test_pattern_menu);
+       mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls,
+                                     &mt9v032_test_pattern_color, NULL);
+
+       v4l2_ctrl_cluster(2, &mt9v032->test_pattern);
 
        mt9v032->pixel_rate =
                v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
@@ -784,8 +802,6 @@ static int mt9v032_probe(struct i2c_client *client,
                v4l2_ctrl_cluster(2, &mt9v032->link_freq);
        }
 
-       for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i)
-               v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL);
 
        mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
 
index 78ac5744cb5dd55ffda31edf6e7ead3e74fb1e0c..d2d298b6354e8038d95076fdc6a9bd8a68f256d4 100644 (file)
@@ -684,6 +684,11 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
                &container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
        struct i2c_client  *client = v4l2_get_subdevdata(sd);
        u8 val;
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
+       if (ret < 0)
+               return ret;
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
index e5c0eedebc58b5129bbaf0bedd3b97d81ada4a19..c31cc04fffd282a6194ff7cb1d90bfb3a4634a2a 100644 (file)
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
 
+#define THS7303_CHANNEL_1      1
+#define THS7303_CHANNEL_2      2
+#define THS7303_CHANNEL_3      3
+
+enum ths7303_filter_mode {
+       THS7303_FILTER_MODE_480I_576I,
+       THS7303_FILTER_MODE_480P_576P,
+       THS7303_FILTER_MODE_720P_1080I,
+       THS7303_FILTER_MODE_1080P,
+       THS7303_FILTER_MODE_DISABLE
+};
+
 MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
 MODULE_AUTHOR("Chaithrika U S");
 MODULE_LICENSE("GPL");
@@ -37,35 +49,96 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level 0-1");
 
 /* following function is used to set ths7303 */
-static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std)
+int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
 {
+       u8 input_bias_chroma = 3;
+       u8 input_bias_luma = 3;
+       int disable = 0;
        int err = 0;
-       u8 val;
-       struct i2c_client *client;
+       u8 val = 0;
+       u8 temp;
 
-       client = v4l2_get_subdevdata(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
-               val = 0x02;
-               v4l2_dbg(1, debug, sd, "setting value for SDTV format\n");
-       } else {
-               val = 0x00;
-               v4l2_dbg(1, debug, sd, "disabling all channels\n");
+       if (!client)
+               return -EINVAL;
+
+       switch (mode) {
+       case THS7303_FILTER_MODE_1080P:
+               val = (3 << 6);
+               val |= (3 << 3);
+               break;
+       case THS7303_FILTER_MODE_720P_1080I:
+               val = (2 << 6);
+               val |= (2 << 3);
+               break;
+       case THS7303_FILTER_MODE_480P_576P:
+               val = (1 << 6);
+               val |= (1 << 3);
+               break;
+       case THS7303_FILTER_MODE_480I_576I:
+               break;
+       case THS7303_FILTER_MODE_DISABLE:
+               pr_info("mode disabled\n");
+               /* disable all channels */
+               disable = 1;
+       default:
+               /* disable all channels */
+               disable = 1;
        }
+       /* Setup channel 2 - Luma - Green */
+       temp = val;
+       if (!disable)
+               val |= input_bias_luma;
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_2, val);
+       if (err)
+               goto out;
 
-       err |= i2c_smbus_write_byte_data(client, 0x01, val);
-       err |= i2c_smbus_write_byte_data(client, 0x02, val);
-       err |= i2c_smbus_write_byte_data(client, 0x03, val);
+       /* setup two chroma channels */
+       if (!disable)
+               temp |= input_bias_chroma;
 
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_1, temp);
        if (err)
-               v4l2_err(sd, "write failed\n");
+               goto out;
 
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_3, temp);
+       if (err)
+               goto out;
+       return err;
+out:
+       pr_info("write byte data failed\n");
        return err;
 }
 
 static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
-       return ths7303_setvalue(sd, norm);
+       if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM))
+               return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
+       else
+               return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
+}
+
+/* for setting filter for HD output */
+static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
+                              struct v4l2_dv_timings *dv_timings)
+{
+       u32 height = dv_timings->bt.height;
+       int interlaced = dv_timings->bt.interlaced;
+       int res = 0;
+
+       if (height == 1080 && !interlaced)
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
+       else if ((height == 720 && !interlaced) ||
+                       (height == 1080 && interlaced))
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
+       else if ((height == 480 || height == 576) && !interlaced)
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
+       else
+               /* disable all channels */
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
+
+       return res;
 }
 
 static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
@@ -78,6 +151,7 @@ static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
 
 static const struct v4l2_subdev_video_ops ths7303_video_ops = {
        .s_std_output   = ths7303_s_std_output,
+       .s_dv_timings    = ths7303_s_dv_timings,
 };
 
 static const struct v4l2_subdev_core_ops ths7303_core_ops = {
@@ -107,7 +181,7 @@ static int ths7303_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
 
-       return ths7303_setvalue(sd, std_id);
+       return ths7303_s_std_output(sd, std_id);
 }
 
 static int ths7303_remove(struct i2c_client *client)
index 1f3943bb87d531bdc16337feb7f6a36c2e232fbb..d5e10215a28f46197d480aa51156cab605d7ef21 100644 (file)
@@ -519,6 +519,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
 
        *std_id = V4L2_STD_UNKNOWN;
 
+       /* To query the standard the TVP514x must power on the ADCs. */
+       if (!decoder->streaming) {
+               tvp514x_s_stream(sd, 1);
+               msleep(LOCK_RETRY_DELAY);
+       }
+
        /* query the current standard */
        current_std = tvp514x_query_current_std(sd);
        if (current_std == STD_INVALID)
@@ -625,25 +631,12 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
        int err;
        enum tvp514x_input input_sel;
        enum tvp514x_output output_sel;
-       u8 sync_lock_status, lock_mask;
-       int try_count = LOCK_RETRY_COUNT;
 
        if ((input >= INPUT_INVALID) ||
                        (output >= OUTPUT_INVALID))
                /* Index out of bound */
                return -EINVAL;
 
-       /*
-        * For the sequence streamon -> streamoff and again s_input
-        * it fails to lock the signal, since streamoff puts TVP514x
-        * into power off state which leads to failure in sub-sequent s_input.
-        *
-        * So power up the TVP514x device here, since it is important to lock
-        * the signal at this stage.
-        */
-       if (!decoder->streaming)
-               tvp514x_s_stream(sd, 1);
-
        input_sel = input;
        output_sel = output;
 
@@ -660,64 +653,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
 
        decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel;
        decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel;
-
-       /* Clear status */
-       msleep(LOCK_RETRY_DELAY);
-       err =
-           tvp514x_write_reg(sd, REG_CLEAR_LOST_LOCK, 0x01);
-       if (err)
-               return err;
-
-       switch (input_sel) {
-       case INPUT_CVBS_VI1A:
-       case INPUT_CVBS_VI1B:
-       case INPUT_CVBS_VI1C:
-       case INPUT_CVBS_VI2A:
-       case INPUT_CVBS_VI2B:
-       case INPUT_CVBS_VI2C:
-       case INPUT_CVBS_VI3A:
-       case INPUT_CVBS_VI3B:
-       case INPUT_CVBS_VI3C:
-       case INPUT_CVBS_VI4A:
-               lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT |
-                       STATUS_HORZ_SYNC_LOCK_BIT |
-                       STATUS_VIRT_SYNC_LOCK_BIT;
-               break;
-
-       case INPUT_SVIDEO_VI2A_VI1A:
-       case INPUT_SVIDEO_VI2B_VI1B:
-       case INPUT_SVIDEO_VI2C_VI1C:
-       case INPUT_SVIDEO_VI2A_VI3A:
-       case INPUT_SVIDEO_VI2B_VI3B:
-       case INPUT_SVIDEO_VI2C_VI3C:
-       case INPUT_SVIDEO_VI4A_VI1A:
-       case INPUT_SVIDEO_VI4A_VI1B:
-       case INPUT_SVIDEO_VI4A_VI1C:
-       case INPUT_SVIDEO_VI4A_VI3A:
-       case INPUT_SVIDEO_VI4A_VI3B:
-       case INPUT_SVIDEO_VI4A_VI3C:
-               lock_mask = STATUS_HORZ_SYNC_LOCK_BIT |
-                       STATUS_VIRT_SYNC_LOCK_BIT;
-               break;
-       /* Need to add other interfaces*/
-       default:
-               return -EINVAL;
-       }
-
-       while (try_count-- > 0) {
-               /* Allow decoder to sync up with new input */
-               msleep(LOCK_RETRY_DELAY);
-
-               sync_lock_status = tvp514x_read_reg(sd,
-                               REG_STATUS1);
-               if (lock_mask == (sync_lock_status & lock_mask))
-                       /* Input detected */
-                       break;
-       }
-
-       if (try_count < 0)
-               return -EINVAL;
-
        decoder->input = input;
        decoder->output = output;
 
index b68918c97f66868baaa1ece4da01ad286f391747..56c6c77793d726f48c50eefbe6cb399a46b19ffe 100644 (file)
@@ -668,6 +668,12 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
                .default_value = 32768,
                .type          = V4L2_CTRL_TYPE_INTEGER,
        },{
+               .id            = V4L2_CID_COLOR_KILLER,
+               .name          = "Color killer",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }, {
                .id            = V4L2_CID_HUE,
                .name          = "Hue",
                .minimum       = 0,
@@ -1474,6 +1480,9 @@ static int bttv_g_ctrl(struct file *file, void *priv,
        case V4L2_CID_SATURATION:
                c->value = btv->saturation;
                break;
+       case V4L2_CID_COLOR_KILLER:
+               c->value = btv->opt_color_killer;
+               break;
 
        case V4L2_CID_AUDIO_MUTE:
        case V4L2_CID_AUDIO_VOLUME:
@@ -1526,7 +1535,6 @@ static int bttv_s_ctrl(struct file *file, void *f,
                                        struct v4l2_control *c)
 {
        int err;
-       int val;
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
@@ -1547,6 +1555,16 @@ static int bttv_s_ctrl(struct file *file, void *f,
        case V4L2_CID_SATURATION:
                bt848_sat(btv, c->value);
                break;
+       case V4L2_CID_COLOR_KILLER:
+               btv->opt_color_killer = c->value;
+               if (btv->opt_color_killer) {
+                       btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
+                       btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
+               } else {
+                       btand(~BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
+                       btand(~BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
+               }
+               break;
        case V4L2_CID_AUDIO_MUTE:
                audio_mute(btv, c->value);
                /* fall through */
@@ -1564,9 +1582,13 @@ static int bttv_s_ctrl(struct file *file, void *f,
 
        case V4L2_CID_PRIVATE_CHROMA_AGC:
                btv->opt_chroma_agc = c->value;
-               val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
-               btwrite(val, BT848_E_SCLOOP);
-               btwrite(val, BT848_O_SCLOOP);
+               if (btv->opt_chroma_agc) {
+                       btor(BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
+                       btor(BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
+               } else {
+                       btand(~BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
+                       btand(~BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
+               }
                break;
        case V4L2_CID_PRIVATE_COMBFILTER:
                btv->opt_combfilter = c->value;
index 70fd4f23f605aa8374799239ca71ca18219bf9d2..9ec0adba236c5bf559fecfeab02f8ab7bd394c0c 100644 (file)
@@ -429,6 +429,7 @@ struct bttv {
        int opt_lumafilter;
        int opt_automute;
        int opt_chroma_agc;
+       int opt_color_killer;
        int opt_adc_crush;
        int opt_vcr_hack;
        int opt_whitecrush_upper;
index ee3884fbc9ce3e95120e2e421724833629c6cb11..7d96fab7d2463bd8ba6254581547a258a61329bc 100644 (file)
@@ -646,7 +646,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
                dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
        default:
                result = -EOPNOTSUPP;
-       };
+       }
  free_mem_and_exit:
        kfree (p_ca_message);
        kfree (p_ca_slot_info);
index aee7f0dacff11a8a61764c274559bf5454909fad..495781ee47113e88e792199d2ce4181e8bf1b953 100644 (file)
@@ -416,7 +416,7 @@ static void netup_read_ci_status(struct work_struct *work)
                                DVB_CA_EN50221_POLL_CAM_READY : 0);
                ci_dbg_print("%s: setting CI[1] status = 0x%x\n",
                                __func__, inter->state[1]->status);
-       };
+       }
 
        if (inter->state[0] != NULL) {
                inter->state[0]->status =
@@ -425,7 +425,7 @@ static void netup_read_ci_status(struct work_struct *work)
                                DVB_CA_EN50221_POLL_CAM_READY : 0);
                ci_dbg_print("%s: setting CI[0] status = 0x%x\n",
                                __func__, inter->state[0]->status);
-       };
+       }
 }
 
 /* CI irq handler */
index c9f15d6dec40ffa0cc4844313b6a5f7ce56d6946..6617774a326a38f98bd611816003a4907e596aff 100644 (file)
@@ -193,7 +193,7 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
                                0, &store, 1);
                if (ret != 0)
                        return ret;
-       };
+       }
        state->current_ci_flag = flag;
 
        mutex_lock(&dev->gpio_lock);
index 39a4a4b9ed7e893d97fe3460dcef33dc663de5b8..5acdf954ff6bcdadec1c1dfe248012f5a3bf7f84 100644 (file)
@@ -542,11 +542,13 @@ struct cx23885_board cx23885_boards[] = {
                        {
                                .type   = CX23885_VMUX_COMPOSITE1,
                                .vmux   = CX25840_COMPOSITE8,
+                               .amux   = CX25840_AUDIO7,
                        },
                        {
                                .type   = CX23885_VMUX_SVIDEO,
                                .vmux   = CX25840_SVIDEO_LUMA3 |
                                                CX25840_SVIDEO_CHROMA4,
+                               .amux   = CX25840_AUDIO7,
                        },
                        {
                                .type   = CX23885_VMUX_COMPONENT,
@@ -554,6 +556,7 @@ struct cx23885_board cx23885_boards[] = {
                                        CX25840_VIN1_CH1 |
                                        CX25840_VIN6_CH2 |
                                        CX25840_VIN7_CH3,
+                               .amux   = CX25840_AUDIO7,
                        },
                },
        },
index 8c4a9a5f9a504ff2959df17d189ab148644f6a03..1a21926ca412cbdab3cdb00841e40e930818f470 100644 (file)
@@ -508,7 +508,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
                (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
                (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
                (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
-               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
+               (dev->board == CX23885_BOARD_MYGICA_X8507)) {
                /* Configure audio routing */
                v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
                        INPUT(input)->amux, 0, 0);
index c8c94fbf5d8d2c68382e2edd3901b93fb1be340d..d33fc1a2303087ccb416ed158708c31c9ddec4d3 100644 (file)
@@ -761,7 +761,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
        }
 
        /* Default if filename is empty string */
-       if (strcmp(dev->input_filename_ch2, "") == 0) {
+       if (strcmp(dev->_filename_ch2, "") == 0) {
                if (dev->_isNTSC_ch2) {
                        dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
                                PIXEL_FRMT_411) ? "/root/vid411.yuv" :
index 52c13e0b6492c601400d3e999cd747307beba271..6759fff8eb640b57b4b9048bb48f3ef0dfa777c8 100644 (file)
@@ -808,7 +808,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
        }
 
        /* Default if filename is empty string */
-       if (strcmp(dev->input_filename, "") == 0) {
+       if (strcmp(dev->_filename, "") == 0) {
                if (dev->_isNTSC) {
                        dev->_filename =
                                (dev->_pixel_format == PIXEL_FRMT_411) ?
index def363fb71c0664a72e6cf8fff5d54d398b7d3bc..62184eb919e5d7563ab0c8d4a9c286c45131c92b 100644 (file)
@@ -721,7 +721,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
        f->fmt.pix.width        = dev->width;
        f->fmt.pix.height       = dev->height;
@@ -739,7 +739,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
        dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
                dev->width, dev->height, fh->mpegq.field );
@@ -755,7 +755,7 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
        dev->width              = f->fmt.pix.width;
        dev->height             = f->fmt.pix.height;
index d803bba09525206e9710d401829251d829e04ede..666f83b2f3c01da335a825d7d7a567211a58b90d 100644 (file)
@@ -896,7 +896,7 @@ static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
 }
index c04fb618e10b78a22209575c2506e4aae270e575..d154bc19735688de10c35e47e65b719d71dbfecd 100644 (file)
@@ -450,7 +450,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
                        cx88_core_irq(core,status);
                if (status & PCI_INT_TSINT)
                        cx8802_mpeg_irq(dev);
-       };
+       }
        if (MAX_IRQ_LOOP == loop) {
                dprintk( 0, "clearing mask\n" );
                printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
index 770ec05b5e9b7da789db5f1ae3a2823066be1f23..424fd97495dcc8144852ee15417c991e30c10a89 100644 (file)
@@ -373,7 +373,7 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
                set_audio_registers(core, nicam_bgdki_common);
                set_audio_registers(core, nicam_default);
                break;
-       };
+       }
 
        mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
        set_audio_finish(core, mode);
@@ -639,7 +639,7 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
                dprintk("%s Warning: wrong value\n", __func__);
                return;
                break;
-       };
+       }
 
        mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
        set_audio_finish(core, mode);
index a146d50d77952fda04871e9a51c3136818d45f22..05171457bf282e42c47dfe00c4410c33cde74518 100644 (file)
@@ -1535,7 +1535,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
                        cx88_core_irq(core,status);
                if (status & PCI_INT_VIDINT)
                        cx8800_vid_irq(dev);
-       };
+       }
        if (10 == loop) {
                printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
                       core->name);
index 22f8758d047f247084814db5e70a75a3b6edd6a6..4a77124ee70e2cbda80a414413a85346b7a832c3 100644 (file)
@@ -1204,7 +1204,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, str
                break;
        default:
                /* nothing */;
-       };
+       }
        switch (c->id) {
        case V4L2_CID_BRIGHTNESS:
                dev->ctl_bright = c->value;
index f588d6296c769bbad1f2222a98bd3394cf1b6aa4..181c7686e412aa485e755867d8fad8e7f5f13bf8 100644 (file)
@@ -165,12 +165,12 @@ config VIDEO_SAMSUNG_S5P_JPEG
          This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
 
 config VIDEO_SAMSUNG_S5P_MFC
-       tristate "Samsung S5P MFC 5.1 Video Codec"
+       tristate "Samsung S5P MFC Video Codec"
        depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
        select VIDEOBUF2_DMA_CONTIG
        default n
        help
-           MFC 5.1 driver for V4L2.
+           MFC 5.1 and 6.x driver for V4L2
 
 config VIDEO_MX2_EMMAPRP
        tristate "MX2 eMMa-PrP support"
index c4a82a1a8a977f42431e47e5fba269173c48c272..69d7a58c92c3e81191adcd3d227f7352a9e5d4d0 100644 (file)
@@ -174,26 +174,6 @@ static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
        return 0;
 }
 
-static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev,
-                                  unsigned int dv_preset)
-{
-       struct vpbe_config *cfg = vpbe_dev->cfg;
-       struct vpbe_enc_mode_info var;
-       int curr_output = vpbe_dev->current_out_index;
-       int i;
-
-       for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
-               var = cfg->outputs[curr_output].modes[i];
-               if ((var.timings_type & VPBE_ENC_DV_PRESET) &&
-                 (var.timings.dv_preset == dv_preset)) {
-                       vpbe_dev->current_timings = var;
-                       return 0;
-               }
-       }
-
-       return -EINVAL;
-}
-
 /* Get std by std id */
 static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
                             v4l2_std_id std_id)
@@ -206,7 +186,7 @@ static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
        for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
                var = cfg->outputs[curr_output].modes[i];
                if ((var.timings_type & VPBE_ENC_STD) &&
-                 (var.timings.std_id & std_id)) {
+                 (var.std_id & std_id)) {
                        vpbe_dev->current_timings = var;
                        return 0;
                }
@@ -344,38 +324,42 @@ static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
 }
 
 /**
- * vpbe_s_dv_preset - Set the given preset timings in the encoder
+ * vpbe_s_dv_timings - Set the given preset timings in the encoder
  *
- * Sets the preset if supported by the current encoder. Return the status.
+ * Sets the timings if supported by the current encoder. Return the status.
  * 0 - success & -EINVAL on error
  */
-static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
-                    struct v4l2_dv_preset *dv_preset)
+static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev,
+                   struct v4l2_dv_timings *dv_timings)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
        int out_index = vpbe_dev->current_out_index;
+       struct vpbe_output *output = &cfg->outputs[out_index];
        int sd_index = vpbe_dev->current_sd_index;
-       int ret;
+       int ret, i;
 
 
        if (!(cfg->outputs[out_index].output.capabilities &
-           V4L2_OUT_CAP_PRESETS))
+           V4L2_OUT_CAP_DV_TIMINGS))
                return -EINVAL;
 
-       ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset);
-
-       if (ret)
-               return ret;
-
+       for (i = 0; i < output->num_modes; i++) {
+               if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS &&
+                   !memcmp(&output->modes[i].dv_timings,
+                               dv_timings, sizeof(*dv_timings)))
+                       break;
+       }
+       if (i >= output->num_modes)
+               return -EINVAL;
+       vpbe_dev->current_timings = output->modes[i];
        mutex_lock(&vpbe_dev->lock);
 
-
        ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
-                                       s_dv_preset, dv_preset);
+                                       s_dv_timings, dv_timings);
        if (!ret && (vpbe_dev->amp != NULL)) {
                /* Call amplifier subdevice */
                ret = v4l2_subdev_call(vpbe_dev->amp, video,
-                               s_dv_preset, dv_preset);
+                               s_dv_timings, dv_timings);
        }
        /* set the lcd controller output for the given mode */
        if (!ret) {
@@ -392,17 +376,17 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
 }
 
 /**
- * vpbe_g_dv_preset - Get the preset in the current encoder
+ * vpbe_g_dv_timings - Get the timings in the current encoder
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
-static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
-                    struct v4l2_dv_preset *dv_preset)
+static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
+                    struct v4l2_dv_timings *dv_timings)
 {
        if (vpbe_dev->current_timings.timings_type &
-         VPBE_ENC_DV_PRESET) {
-               dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset;
+         VPBE_ENC_CUSTOM_TIMINGS) {
+               *dv_timings = vpbe_dev->current_timings.dv_timings;
                return 0;
        }
 
@@ -410,13 +394,13 @@ static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
 }
 
 /**
- * vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder
+ * vpbe_enum_dv_timings - Enumerate the dv timings in the current encoder
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
-static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
-                        struct v4l2_dv_enum_preset *preset_info)
+static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
+                        struct v4l2_enum_dv_timings *timings)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
        int out_index = vpbe_dev->current_out_index;
@@ -424,12 +408,12 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
        int j = 0;
        int i;
 
-       if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS))
+       if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
                return -EINVAL;
 
        for (i = 0; i < output->num_modes; i++) {
-               if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) {
-                       if (j == preset_info->index)
+               if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) {
+                       if (j == timings->index)
                                break;
                        j++;
                }
@@ -437,9 +421,8 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
 
        if (i == output->num_modes)
                return -EINVAL;
-
-       return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset,
-                                       preset_info);
+       timings->timings = output->modes[i].dv_timings;
+       return 0;
 }
 
 /**
@@ -489,10 +472,10 @@ static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
  */
 static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
 {
-       struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings;
+       struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
 
-       if (cur_timings.timings_type & VPBE_ENC_STD) {
-               *std_id = cur_timings.timings.std_id;
+       if (cur_timings->timings_type & VPBE_ENC_STD) {
+               *std_id = cur_timings->std_id;
                return 0;
        }
 
@@ -511,7 +494,7 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
 {
        struct vpbe_enc_mode_info *preset_mode = NULL;
        struct vpbe_config *cfg = vpbe_dev->cfg;
-       struct v4l2_dv_preset dv_preset;
+       struct v4l2_dv_timings dv_timings;
        struct osd_state *osd_device;
        int out_index = vpbe_dev->current_out_index;
        int ret = 0;
@@ -530,11 +513,12 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
                         */
                        if (preset_mode->timings_type & VPBE_ENC_STD)
                                return vpbe_s_std(vpbe_dev,
-                                                &preset_mode->timings.std_id);
-                       if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) {
-                               dv_preset.preset =
-                                       preset_mode->timings.dv_preset;
-                               return vpbe_s_dv_preset(vpbe_dev, &dv_preset);
+                                                &preset_mode->std_id);
+                       if (preset_mode->timings_type &
+                                               VPBE_ENC_CUSTOM_TIMINGS) {
+                               dv_timings =
+                                       preset_mode->dv_timings;
+                               return vpbe_s_dv_timings(vpbe_dev, &dv_timings);
                        }
                }
        }
@@ -626,11 +610,11 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
                if (IS_ERR(vpbe_dev->dac_clk)) {
                        ret =  PTR_ERR(vpbe_dev->dac_clk);
-                       goto vpbe_unlock;
+                       goto fail_mutex_unlock;
                }
                if (clk_enable(vpbe_dev->dac_clk)) {
                        ret =  -ENODEV;
-                       goto vpbe_unlock;
+                       goto fail_mutex_unlock;
                }
        }
 
@@ -642,7 +626,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
        if (ret) {
                v4l2_err(dev->driver,
                        "Unable to register v4l2 device.\n");
-               goto vpbe_fail_clock;
+               goto fail_clk_put;
        }
        v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");
 
@@ -658,7 +642,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                v4l2_err(&vpbe_dev->v4l2_dev,
                        "vpbe unable to init venc sub device\n");
                ret = -ENODEV;
-               goto vpbe_fail_v4l2_device;
+               goto fail_dev_unregister;
        }
        /* initialize osd device */
        osd_device = vpbe_dev->osd_device;
@@ -669,7 +653,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                        v4l2_err(&vpbe_dev->v4l2_dev,
                                 "unable to initialize the OSD device");
                        err = -ENOMEM;
-                       goto vpbe_fail_v4l2_device;
+                       goto fail_dev_unregister;
                }
        }
 
@@ -685,7 +669,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                v4l2_err(&vpbe_dev->v4l2_dev,
                        "unable to allocate memory for encoders sub devices");
                ret = -ENOMEM;
-               goto vpbe_fail_v4l2_device;
+               goto fail_dev_unregister;
        }
 
        i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
@@ -711,7 +695,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                                         " failed to register",
                                         enc_info->module_name);
                                ret = -ENODEV;
-                               goto vpbe_fail_sd_register;
+                               goto fail_kfree_encoders;
                        }
                } else
                        v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
@@ -730,7 +714,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                                         "amplifier %s failed to register",
                                         amp_info->module_name);
                                ret = -ENODEV;
-                               goto vpbe_fail_amp_register;
+                               goto fail_kfree_encoders;
                        }
                        v4l2_info(&vpbe_dev->v4l2_dev,
                                          "v4l2 sub device %s registered\n",
@@ -770,16 +754,14 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
        /* TBD handling of bootargs for default output and mode */
        return 0;
 
-vpbe_fail_amp_register:
-       kfree(vpbe_dev->amp);
-vpbe_fail_sd_register:
+fail_kfree_encoders:
        kfree(vpbe_dev->encoders);
-vpbe_fail_v4l2_device:
+fail_dev_unregister:
        v4l2_device_unregister(&vpbe_dev->v4l2_dev);
-vpbe_fail_clock:
+fail_clk_put:
        if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
                clk_put(vpbe_dev->dac_clk);
-vpbe_unlock:
+fail_mutex_unlock:
        mutex_unlock(&vpbe_dev->lock);
        return ret;
 }
@@ -810,9 +792,9 @@ static struct vpbe_device_ops vpbe_dev_ops = {
        .enum_outputs = vpbe_enum_outputs,
        .set_output = vpbe_set_output,
        .get_output = vpbe_get_output,
-       .s_dv_preset = vpbe_s_dv_preset,
-       .g_dv_preset = vpbe_g_dv_preset,
-       .enum_dv_presets = vpbe_enum_dv_presets,
+       .s_dv_timings = vpbe_s_dv_timings,
+       .g_dv_timings = vpbe_g_dv_timings,
+       .enum_dv_timings = vpbe_enum_dv_timings,
        .s_std = vpbe_s_std,
        .g_std = vpbe_g_std,
        .initialize = vpbe_initialize,
index 239f37bfa313b40903d8ac4d54192747165cd87d..161c77650e2f88ea13fedd063c43ef306a734d67 100644 (file)
@@ -393,7 +393,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev,
        int h_scale;
        int v_scale;
 
-       v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id;
+       v4l2_std_id standard_id = vpbe_dev->current_timings.std_id;
 
        /*
         * Application initially set the image format. Current display
@@ -637,7 +637,7 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
        struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
        struct osd_layer_config *cfg = &layer->layer_info.config;
        struct osd_state *osd_device = disp_dev->osd_device;
-       struct v4l2_rect *rect = &crop->c;
+       struct v4l2_rect rect = crop->c;
        int ret;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -648,21 +648,21 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
                return -EINVAL;
        }
 
-       if (rect->top < 0)
-               rect->top = 0;
-       if (rect->left < 0)
-               rect->left = 0;
+       if (rect.top < 0)
+               rect.top = 0;
+       if (rect.left < 0)
+               rect.left = 0;
 
-       vpbe_disp_check_window_params(disp_dev, rect);
+       vpbe_disp_check_window_params(disp_dev, &rect);
 
        osd_device->ops.get_layer_config(osd_device,
                        layer->layer_info.id, cfg);
 
        vpbe_disp_calculate_scale_factor(disp_dev, layer,
-                                       rect->width,
-                                       rect->height);
-       vpbe_disp_adj_position(disp_dev, layer, rect->top,
-                                       rect->left);
+                                       rect.width,
+                                       rect.height);
+       vpbe_disp_adj_position(disp_dev, layer, rect.top,
+                                       rect.left);
        ret = osd_device->ops.set_layer_config(osd_device,
                                layer->layer_info.id, cfg);
        if (ret < 0) {
@@ -943,7 +943,7 @@ static int vpbe_display_g_std(struct file *file, void *priv,
 
        /* Get the standard from the current encoder */
        if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) {
-               *std_id = vpbe_dev->current_timings.timings.std_id;
+               *std_id = vpbe_dev->current_timings.std_id;
                return 0;
        }
 
@@ -1029,29 +1029,29 @@ static int vpbe_display_g_output(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_enum_dv_presets - Enumerate the dv presets
+ * vpbe_display_enum_dv_timings - Enumerate the dv timings
  *
- * enum the preset in the current encoder. Return the status. 0 - success
+ * enum the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_enum_dv_presets(struct file *file, void *priv,
-                       struct v4l2_dv_enum_preset *preset)
+vpbe_display_enum_dv_timings(struct file *file, void *priv,
+                       struct v4l2_enum_dv_timings *timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        int ret;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n");
 
        /* Enumerate outputs */
-       if (NULL == vpbe_dev->ops.enum_dv_presets)
+       if (NULL == vpbe_dev->ops.enum_dv_timings)
                return -EINVAL;
 
-       ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset);
+       ret = vpbe_dev->ops.enum_dv_timings(vpbe_dev, timings);
        if (ret) {
                v4l2_err(&vpbe_dev->v4l2_dev,
-                       "Failed to enumerate dv presets info\n");
+                       "Failed to enumerate dv timings info\n");
                return -EINVAL;
        }
 
@@ -1059,21 +1059,21 @@ vpbe_display_enum_dv_presets(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_s_dv_preset - Set the dv presets
+ * vpbe_display_s_dv_timings - Set the dv timings
  *
- * Set the preset in the current encoder. Return the status. 0 - success
+ * Set the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_s_dv_preset(struct file *file, void *priv,
-                               struct v4l2_dv_preset *preset)
+vpbe_display_s_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        int ret;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n");
 
 
        /* If streaming is started, return error */
@@ -1083,13 +1083,13 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
        }
 
        /* Set the given standard in the encoder */
-       if (!vpbe_dev->ops.s_dv_preset)
+       if (!vpbe_dev->ops.s_dv_timings)
                return -EINVAL;
 
-       ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset);
+       ret = vpbe_dev->ops.s_dv_timings(vpbe_dev, timings);
        if (ret) {
                v4l2_err(&vpbe_dev->v4l2_dev,
-                       "Failed to set the dv presets info\n");
+                       "Failed to set the dv timings info\n");
                return -EINVAL;
        }
        /* set the current norm to zero to be consistent. If STD is used
@@ -1101,26 +1101,25 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_g_dv_preset - Set the dv presets
+ * vpbe_display_g_dv_timings - Set the dv timings
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_g_dv_preset(struct file *file, void *priv,
-                               struct v4l2_dv_preset *dv_preset)
+vpbe_display_g_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *dv_timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n");
 
        /* Get the given standard in the encoder */
 
        if (vpbe_dev->current_timings.timings_type &
-                               VPBE_ENC_DV_PRESET) {
-               dv_preset->preset =
-                       vpbe_dev->current_timings.timings.dv_preset;
+                               VPBE_ENC_CUSTOM_TIMINGS) {
+               *dv_timings = vpbe_dev->current_timings.dv_timings;
        } else {
                return -EINVAL;
        }
@@ -1572,9 +1571,9 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = {
        .vidioc_enum_output      = vpbe_display_enum_output,
        .vidioc_s_output         = vpbe_display_s_output,
        .vidioc_g_output         = vpbe_display_g_output,
-       .vidioc_s_dv_preset      = vpbe_display_s_dv_preset,
-       .vidioc_g_dv_preset      = vpbe_display_g_dv_preset,
-       .vidioc_enum_dv_presets  = vpbe_display_enum_dv_presets,
+       .vidioc_s_dv_timings     = vpbe_display_s_dv_timings,
+       .vidioc_g_dv_timings     = vpbe_display_g_dv_timings,
+       .vidioc_enum_dv_timings  = vpbe_display_enum_dv_timings,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .vidioc_g_register       = vpbe_display_g_register,
        .vidioc_s_register       = vpbe_display_s_register,
@@ -1639,8 +1638,7 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
                        VPBE_ENC_STD) {
                vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50);
                vbd->current_norm =
-                       disp_dev->vpbe_dev->
-                       current_timings.timings.std_id;
+                       disp_dev->vpbe_dev->current_timings.std_id;
        } else
                vbd->current_norm = 0;
 
index 0302669622d6d6e2b409be2221d4d34f4d25a5e8..aed7369b962a7da5a5c7e6c826ce06944d12136c 100644 (file)
@@ -298,7 +298,7 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
                return -EINVAL;
 
        /* Setup clock at VPSS & VENC for SD */
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -345,7 +345,7 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
          (pdata->venc_type != VPBE_VERSION_2))
                return -EINVAL;
        /* Setup clock at VPSS & VENC for SD */
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -385,7 +385,7 @@ static int venc_set_720p60_internal(struct v4l2_subdev *sd)
        struct venc_state *venc = to_state(sd);
        struct venc_platform_data *pdata = venc->pdata;
 
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -413,7 +413,7 @@ static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
        struct venc_state *venc = to_state(sd);
        struct venc_platform_data *pdata = venc->pdata;
 
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -446,26 +446,27 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
        return -EINVAL;
 }
 
-static int venc_s_dv_preset(struct v4l2_subdev *sd,
-                           struct v4l2_dv_preset *dv_preset)
+static int venc_s_dv_timings(struct v4l2_subdev *sd,
+                           struct v4l2_dv_timings *dv_timings)
 {
        struct venc_state *venc = to_state(sd);
+       u32 height = dv_timings->bt.height;
        int ret;
 
-       v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
+       v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
 
-       if (dv_preset->preset == V4L2_DV_576P50)
+       if (height == 576)
                return venc_set_576p50(sd);
-       else if (dv_preset->preset == V4L2_DV_480P59_94)
+       else if (height == 480)
                return venc_set_480p59_94(sd);
-       else if ((dv_preset->preset == V4L2_DV_720P60) &&
+       else if ((height == 720) &&
                        (venc->pdata->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 ((dv_preset->preset == V4L2_DV_1080I30) &&
+       } else if ((height == 1080) &&
                (venc->pdata->venc_type == VPBE_VERSION_2)) {
                /* TBD setup internal 1080i mode here */
                ret = venc_set_1080i30_internal(sd);
@@ -518,7 +519,7 @@ static const struct v4l2_subdev_core_ops venc_core_ops = {
 static const struct v4l2_subdev_video_ops venc_video_ops = {
        .s_routing = venc_s_routing,
        .s_std_output = venc_s_std_output,
-       .s_dv_preset = venc_s_dv_preset,
+       .s_dv_timings = venc_s_dv_timings,
 };
 
 static const struct v4l2_subdev_ops venc_ops = {
index 48052cbffc2ba36d123faba417116a980706f894..8be492cd8ed46bf58a9cd79ce4d26ed8474404aa 100644 (file)
@@ -1669,6 +1669,7 @@ static int vpfe_s_crop(struct file *file, void *priv,
                             const struct v4l2_crop *crop)
 {
        struct vpfe_device *vpfe_dev = video_drvdata(file);
+       struct v4l2_rect rect = crop->c;
        int ret = 0;
 
        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
@@ -1684,7 +1685,7 @@ static int vpfe_s_crop(struct file *file, void *priv,
        if (ret)
                return ret;
 
-       if (crop->c.top < 0 || crop->c.left < 0) {
+       if (rect.top < 0 || rect.left < 0) {
                v4l2_err(&vpfe_dev->v4l2_dev,
                        "doesn't support negative values for top & left\n");
                ret = -EINVAL;
@@ -1692,26 +1693,26 @@ static int vpfe_s_crop(struct file *file, void *priv,
        }
 
        /* adjust the width to 16 pixel boundary */
-       crop->c.width = ((crop->c.width + 15) & ~0xf);
+       rect.width = ((rect.width + 15) & ~0xf);
 
        /* make sure parameters are valid */
-       if ((crop->c.left + crop->c.width >
+       if ((rect.left + rect.width >
                vpfe_dev->std_info.active_pixels) ||
-           (crop->c.top + crop->c.height >
+           (rect.top + rect.height >
                vpfe_dev->std_info.active_lines)) {
                v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
                ret = -EINVAL;
                goto unlock_out;
        }
-       ccdc_dev->hw_ops.set_image_window(&crop->c);
-       vpfe_dev->fmt.fmt.pix.width = crop->c.width;
-       vpfe_dev->fmt.fmt.pix.height = crop->c.height;
+       ccdc_dev->hw_ops.set_image_window(&rect);
+       vpfe_dev->fmt.fmt.pix.width = rect.width;
+       vpfe_dev->fmt.fmt.pix.height = rect.height;
        vpfe_dev->fmt.fmt.pix.bytesperline =
                ccdc_dev->hw_ops.get_line_length();
        vpfe_dev->fmt.fmt.pix.sizeimage =
                vpfe_dev->fmt.fmt.pix.bytesperline *
                vpfe_dev->fmt.fmt.pix.height;
-       vpfe_dev->crop = crop->c;
+       vpfe_dev->crop = rect;
 unlock_out:
        mutex_unlock(&vpfe_dev->lock);
        return ret;
index 0bafecac4923bce09cef1850ebb3660a62401609..fcabc023885d06c66b33db117d5c744f138a2e45 100644 (file)
@@ -311,12 +311,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        }
 
        /* configure 1 or 2 channel mode */
-       ret = vpif_config_data->setup_input_channel_mode
-                                       (vpif->std_info.ycmux_mode);
-
-       if (ret < 0) {
-               vpif_dbg(1, debug, "can't set vpif channel mode\n");
-               return ret;
+       if (vpif_config_data->setup_input_channel_mode) {
+               ret = vpif_config_data->
+                       setup_input_channel_mode(vpif->std_info.ycmux_mode);
+               if (ret < 0) {
+                       vpif_dbg(1, debug, "can't set vpif channel mode\n");
+                       return ret;
+               }
        }
 
        /* Call vpif_set_params function to set the parameters and addresses */
@@ -863,13 +864,11 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait)
  */
 static int vpif_open(struct file *filep)
 {
-       struct vpif_capture_config *config = vpif_dev->platform_data;
        struct video_device *vdev = video_devdata(filep);
        struct common_obj *common;
        struct video_obj *vid_ch;
        struct channel_obj *ch;
        struct vpif_fh *fh;
-       int i;
 
        vpif_dbg(2, debug, "vpif_open\n");
 
@@ -878,26 +877,6 @@ static int vpif_open(struct file *filep)
        vid_ch = &ch->video;
        common = &ch->common[VPIF_VIDEO_INDEX];
 
-       if (NULL == ch->curr_subdev_info) {
-               /**
-                * search through the sub device to see a registered
-                * sub device and make it as current sub device
-                */
-               for (i = 0; i < config->subdev_count; i++) {
-                       if (vpif_obj.sd[i]) {
-                               /* the sub device is registered */
-                               ch->curr_subdev_info = &config->subdev_info[i];
-                               /* make first input as the current input */
-                               vid_ch->input_idx = 0;
-                               break;
-                       }
-               }
-               if (i == config->subdev_count) {
-                       vpif_err("No sub device registered\n");
-                       return -ENOENT;
-               }
-       }
-
        /* Allocate memory for the file handle object */
        fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
        if (NULL == fh) {
@@ -997,6 +976,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
        struct common_obj *common;
        u8 index = 0;
        struct vb2_queue *q;
+       int ret;
 
        vpif_dbg(2, debug, "vpif_reqbufs\n");
 
@@ -1036,8 +1016,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct vpif_cap_buffer);
 
-       vb2_queue_init(q);
-
+       ret = vb2_queue_init(q);
+       if (ret) {
+               vpif_err("vpif_capture: vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
+               return ret;
+       }
        /* Set io allowed member of file handle to TRUE */
        fh->io_allowed[index] = 1;
        /* Increment io usrs member of channel object to 1 */
@@ -1175,10 +1159,9 @@ static int vpif_streamon(struct file *file, void *priv,
                return ret;
 
        /* Enable streamon on the sub device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               s_stream, 1);
+       ret = v4l2_subdev_call(ch->sd, video, s_stream, 1);
 
-       if (ret && (ret != -ENOIOCTLCMD)) {
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
                vpif_dbg(1, debug, "stream on failed in subdev\n");
                return ret;
        }
@@ -1238,73 +1221,105 @@ static int vpif_streamoff(struct file *file, void *priv,
 
        common->started = 0;
 
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               s_stream, 0);
+       ret = v4l2_subdev_call(ch->sd, video, s_stream, 0);
 
-       if (ret && (ret != -ENOIOCTLCMD))
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
                vpif_dbg(1, debug, "stream off failed in subdev\n");
 
        return vb2_streamoff(&common->buffer_queue, buftype);
 }
 
 /**
- * vpif_map_sub_device_to_input() - Maps sub device to input
- * @ch - ptr to channel
- * @config - ptr to capture configuration
+ * vpif_input_to_subdev() - Maps input to sub device
+ * @vpif_cfg - global config ptr
+ * @chan_cfg - channel config ptr
  * @input_index - Given input index from application
- * @sub_device_index - index into sd table
  *
  * lookup the sub device information for a given input index.
  * we report all the inputs to application. inputs table also
  * has sub device name for the each input
  */
-static struct vpif_subdev_info *vpif_map_sub_device_to_input(
-                               struct channel_obj *ch,
-                               struct vpif_capture_config *vpif_cfg,
-                               int input_index,
-                               int *sub_device_index)
+static int vpif_input_to_subdev(
+               struct vpif_capture_config *vpif_cfg,
+               struct vpif_capture_chan_config *chan_cfg,
+               int input_index)
 {
-       struct vpif_capture_chan_config *chan_cfg;
-       struct vpif_subdev_info *subdev_info = NULL;
-       const char *subdev_name = NULL;
+       struct vpif_subdev_info *subdev_info;
+       const char *subdev_name;
        int i;
 
-       vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n");
+       vpif_dbg(2, debug, "vpif_input_to_subdev\n");
 
-       chan_cfg = &vpif_cfg->chan_config[ch->channel_id];
-
-       /**
-        * search through the inputs to find the sub device supporting
-        * the input
-        */
-       for (i = 0; i < chan_cfg->input_count; i++) {
-               /* For each sub device, loop through input */
-               if (i == input_index) {
-                       subdev_name = chan_cfg->inputs[i].subdev_name;
-                       break;
-               }
-       }
-
-       /* if reached maximum. return null */
-       if (i == chan_cfg->input_count || (NULL == subdev_name))
-               return subdev_info;
+       subdev_name = chan_cfg->inputs[input_index].subdev_name;
+       if (subdev_name == NULL)
+               return -1;
 
        /* loop through the sub device list to get the sub device info */
        for (i = 0; i < vpif_cfg->subdev_count; i++) {
                subdev_info = &vpif_cfg->subdev_info[i];
                if (!strcmp(subdev_info->name, subdev_name))
-                       break;
+                       return i;
+       }
+       return -1;
+}
+
+/**
+ * vpif_set_input() - Select an input
+ * @vpif_cfg - global config ptr
+ * @ch - channel
+ * @_index - Given input index from application
+ *
+ * Select the given input.
+ */
+static int vpif_set_input(
+               struct vpif_capture_config *vpif_cfg,
+               struct channel_obj *ch,
+               int index)
+{
+       struct vpif_capture_chan_config *chan_cfg =
+                       &vpif_cfg->chan_config[ch->channel_id];
+       struct vpif_subdev_info *subdev_info = NULL;
+       struct v4l2_subdev *sd = NULL;
+       u32 input = 0, output = 0;
+       int sd_index;
+       int ret;
+
+       sd_index = vpif_input_to_subdev(vpif_cfg, chan_cfg, index);
+       if (sd_index >= 0) {
+               sd = vpif_obj.sd[sd_index];
+               subdev_info = &vpif_cfg->subdev_info[sd_index];
        }
 
-       if (i == vpif_cfg->subdev_count)
-               return subdev_info;
+       /* first setup input path from sub device to vpif */
+       if (sd && vpif_cfg->setup_input_path) {
+               ret = vpif_cfg->setup_input_path(ch->channel_id,
+                                      subdev_info->name);
+               if (ret < 0) {
+                       vpif_dbg(1, debug, "couldn't setup input path for the" \
+                       " sub device %s, for input index %d\n",
+                       subdev_info->name, index);
+                       return ret;
+               }
+       }
 
-       /* check if the sub device is registered */
-       if (NULL == vpif_obj.sd[i])
-               return NULL;
+       if (sd) {
+               input = chan_cfg->inputs[index].input_route;
+               output = chan_cfg->inputs[index].output_route;
+               ret = v4l2_subdev_call(sd, video, s_routing,
+                               input, output, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       vpif_dbg(1, debug, "Failed to set input\n");
+                       return ret;
+               }
+       }
+       ch->input_idx = index;
+       ch->sd = sd;
+       /* copy interface parameters to vpif */
+       ch->vpifparams.iface = chan_cfg->vpif_if;
 
-       *sub_device_index = i;
-       return subdev_info;
+       /* update tvnorms from the sub device input info */
+       ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
+       return 0;
 }
 
 /**
@@ -1324,12 +1339,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
        vpif_dbg(2, debug, "vpif_querystd\n");
 
        /* Call querystd function of decoder device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               querystd, std_id);
-       if (ret < 0)
-               vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
+       ret = v4l2_subdev_call(ch->sd, video, querystd, std_id);
 
-       return ret;
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               return -ENODATA;
+       if (ret) {
+               vpif_dbg(1, debug, "Failed to query standard for sub devices\n");
+               return ret;
+       }
+
+       return 0;
 }
 
 /**
@@ -1397,11 +1416,12 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
        vpif_config_format(ch);
 
        /* set standard in the sub device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                               s_std, *std_id);
-       if (ret < 0)
+       ret = v4l2_subdev_call(ch->sd, core, s_std, *std_id);
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
                vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
-       return ret;
+               return ret;
+       }
+       return 0;
 }
 
 /**
@@ -1441,10 +1461,8 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
-
-       *index = vid_ch->input_idx;
 
+       *index = ch->input_idx;
        return 0;
 }
 
@@ -1461,13 +1479,13 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       struct video_obj *vid_ch = &ch->video;
-       struct vpif_subdev_info *subdev_info;
-       int ret = 0, sd_index = 0;
-       u32 input = 0, output = 0;
+       int ret;
 
        chan_cfg = &config->chan_config[ch->channel_id];
 
+       if (index >= chan_cfg->input_count)
+               return -EINVAL;
+
        if (common->started) {
                vpif_err("Streaming in progress\n");
                return -EBUSY;
@@ -1486,45 +1504,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
                return ret;
 
        fh->initialized = 1;
-       subdev_info = vpif_map_sub_device_to_input(ch, config, index,
-                                                  &sd_index);
-       if (NULL == subdev_info) {
-               vpif_dbg(1, debug,
-                       "couldn't lookup sub device for the input index\n");
-               return -EINVAL;
-       }
-
-       /* first setup input path from sub device to vpif */
-       if (config->setup_input_path) {
-               ret = config->setup_input_path(ch->channel_id,
-                                              subdev_info->name);
-               if (ret < 0) {
-                       vpif_dbg(1, debug, "couldn't setup input path for the"
-                               " sub device %s, for input index %d\n",
-                               subdev_info->name, index);
-                       return ret;
-               }
-       }
-
-       if (subdev_info->can_route) {
-               input = subdev_info->input;
-               output = subdev_info->output;
-               ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing,
-                                       input, output, 0);
-               if (ret < 0) {
-                       vpif_dbg(1, debug, "Failed to set input\n");
-                       return ret;
-               }
-       }
-       vid_ch->input_idx = index;
-       ch->curr_subdev_info = subdev_info;
-       ch->curr_sd_index = sd_index;
-       /* copy interface parameters to vpif */
-       ch->vpifparams.iface = subdev_info->vpif_if;
-
-       /* update tvnorms from the sub device input info */
-       ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
-       return ret;
+       return vpif_set_input(config, ch, index);
 }
 
 /**
@@ -1655,9 +1635,11 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_capture_config *config = vpif_dev->platform_data;
 
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-       strlcpy(cap->driver, "vpif capture", sizeof(cap->driver));
-       strlcpy(cap->bus_info, "VPIF Platform", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(vpif_dev));
        strlcpy(cap->card, config->card_name, sizeof(cap->card));
 
        return 0;
@@ -1730,9 +1712,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                               video, enum_dv_timings, timings);
+       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -EINVAL;
+       return ret;
 }
 
 /**
@@ -1747,9 +1732,12 @@ vpif_query_dv_timings(struct file *file, void *priv,
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                               video, query_dv_timings, timings);
+       ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -ENODATA;
+       return ret;
 }
 
 /**
@@ -1775,13 +1763,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        }
 
        /* Configure subdevice timings, if any */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                       video, s_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD) {
-               vpif_dbg(2, debug, "Custom DV timings not supported by "
-                               "subdevice\n");
-               return -EINVAL;
-       }
+       ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               ret = 0;
        if (ret < 0) {
                vpif_dbg(2, debug, "Error setting custom DV timings\n");
                return ret;
@@ -1906,8 +1890,7 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                       g_register, reg);
+       return v4l2_subdev_call(ch->sd, core, g_register, reg);
 }
 
 /*
@@ -1924,8 +1907,7 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                       s_register, reg);
+       return v4l2_subdev_call(ch->sd, core, s_register, reg);
 }
 #endif
 
@@ -2063,7 +2045,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
        struct vpif_capture_config *config;
-       int i, j, k, m, q, err;
+       int i, j, k, err;
+       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
        struct channel_obj *ch;
        struct common_obj *common;
@@ -2086,18 +2069,19 @@ static __init int vpif_probe(struct platform_device *pdev)
                return err;
        }
 
-       k = 0;
-       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
+       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
                for (i = res->start; i <= res->end; i++) {
                        if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
-                                       "VPIF_Capture",
-                               (void *)(&vpif_obj.dev[k]->channel_id))) {
+                                       "VPIF_Capture", (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id))) {
                                err = -EBUSY;
-                               i--;
+                               for (j = 0; j < i; j++)
+                                       free_irq(j, (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id));
                                goto vpif_int_err;
                        }
                }
-               k++;
+               res_idx++;
        }
 
        for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
@@ -2111,7 +2095,7 @@ static __init int vpif_probe(struct platform_device *pdev)
                                video_device_release(ch->video_dev);
                        }
                        err = -ENOMEM;
-                       goto vpif_dev_alloc_err;
+                       goto vpif_int_err;
                }
 
                /* Initialize field of video device */
@@ -2142,24 +2126,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
        }
 
-       for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
-               ch = vpif_obj.dev[j];
-               ch->channel_id = j;
-               common = &(ch->common[VPIF_VIDEO_INDEX]);
-               spin_lock_init(&common->irqlock);
-               mutex_init(&common->lock);
-               ch->video_dev->lock = &common->lock;
-               /* Initialize prio member of channel object */
-               v4l2_prio_init(&ch->prio);
-               err = video_register_device(ch->video_dev,
-                                           VFL_TYPE_GRABBER, (j ? 1 : 0));
-               if (err)
-                       goto probe_out;
-
-               video_set_drvdata(ch->video_dev, ch);
-
-       }
-
        i2c_adap = i2c_get_adapter(1);
        config = pdev->dev.platform_data;
 
@@ -2169,7 +2135,7 @@ static __init int vpif_probe(struct platform_device *pdev)
        if (vpif_obj.sd == NULL) {
                vpif_err("unable to allocate memory for subdevice pointers\n");
                err = -ENOMEM;
-               goto probe_out;
+               goto vpif_sd_error;
        }
 
        for (i = 0; i < subdev_count; i++) {
@@ -2186,19 +2152,32 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
                v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
                          subdevdata->name);
-
-               if (vpif_obj.sd[i])
-                       vpif_obj.sd[i]->grp_id = 1 << i;
        }
 
+       for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
+               ch = vpif_obj.dev[j];
+               ch->channel_id = j;
+               common = &(ch->common[VPIF_VIDEO_INDEX]);
+               spin_lock_init(&common->irqlock);
+               mutex_init(&common->lock);
+               ch->video_dev->lock = &common->lock;
+               /* Initialize prio member of channel object */
+               v4l2_prio_init(&ch->prio);
+               video_set_drvdata(ch->video_dev, ch);
+
+               /* select input 0 */
+               err = vpif_set_input(config, ch, 0);
+               if (err)
+                       goto probe_out;
+
+               err = video_register_device(ch->video_dev,
+                                           VFL_TYPE_GRABBER, (j ? 1 : 0));
+               if (err)
+                       goto probe_out;
+       }
        v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
        return 0;
 
-probe_subdev_out:
-       /* free sub devices memory */
-       kfree(vpif_obj.sd);
-
-       j = VPIF_CAPTURE_MAX_DEVICES;
 probe_out:
        for (k = 0; k < j; k++) {
                /* Get the pointer to the channel object */
@@ -2206,22 +2185,23 @@ probe_out:
                /* Unregister video device */
                video_unregister_device(ch->video_dev);
        }
+probe_subdev_out:
+       /* free sub devices memory */
+       kfree(vpif_obj.sd);
 
-vpif_dev_alloc_err:
-       k = VPIF_CAPTURE_MAX_DEVICES-1;
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
-       i = res->end;
-
-vpif_int_err:
-       for (q = k; q >= 0; q--) {
-               for (m = i; m >= (int)res->start; m--)
-                       free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id));
-
-               res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1);
-               if (res)
-                       i = res->end;
+vpif_sd_error:
+       for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
+               ch = vpif_obj.dev[i];
+               /* Note: does nothing if ch->video_dev == NULL */
+               video_device_release(ch->video_dev);
        }
+vpif_int_err:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
+       for (i = 0; i < res_idx; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               for (j = res->start; j <= res->end; j++)
+                       free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
+       }
        return err;
 }
 
index d24efc17e4c876537933aeff8e7a95f6aded1e28..3d3c1e5cd5d4c63c1eb23b61be1574296ab27885 100644 (file)
@@ -54,8 +54,6 @@ struct video_obj {
        /* Currently selected or default standard */
        v4l2_std_id stdid;
        struct v4l2_dv_timings dv_timings;
-       /* This is to track the last input that is passed to application */
-       u32 input_idx;
 };
 
 struct vpif_cap_buffer {
@@ -119,10 +117,10 @@ struct channel_obj {
        u8 initialized;
        /* Identifies channel */
        enum vpif_channel_id channel_id;
-       /* index into sd table */
-       int curr_sd_index;
-       /* ptr to current sub device information */
-       struct vpif_subdev_info *curr_subdev_info;
+       /* Current input */
+       u32 input_idx;
+       /* subdev corresponding to the current input, may be NULL */
+       struct v4l2_subdev *sd;
        /* vpif configuration params */
        struct vpif_params vpifparams;
        /* common object array */
@@ -159,10 +157,6 @@ struct vpif_config_params {
        u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
        u8 max_device_type;
 };
-/* Struct which keeps track of the line numbers for the sliced vbi service */
-struct vpif_service_line {
-       u16 service_id;
-       u16 service_line[2];
-};
+
 #endif                         /* End of __KERNEL__ */
 #endif                         /* VPIF_CAPTURE_H */
index a5b88689abad1d9055c45f6624190d68734dbf30..b716fbd4241f8599f90c8dbf7caf4b99e0f338bb 100644 (file)
@@ -280,12 +280,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        }
 
        /* clock settings */
-       ret =
-           vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode,
-                                       ch->vpifparams.std_info.hd_sd);
-       if (ret < 0) {
-               vpif_err("can't set clock\n");
-               return ret;
+       if (vpif_config_data->set_clock) {
+               ret = vpif_config_data->set_clock(ch->vpifparams.std_info.
+               ycmux_mode, ch->vpifparams.std_info.hd_sd);
+               if (ret < 0) {
+                       vpif_err("can't set clock\n");
+                       return ret;
+               }
        }
 
        /* set the parameters and addresses */
@@ -307,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel2_intr_assert();
                channel2_intr_enable(1);
                enable_channel2(1);
-               if (vpif_config_data->ch2_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                        channel2_clipping_enable(1);
        }
 
@@ -316,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel3_intr_assert();
                channel3_intr_enable(1);
                enable_channel3(1);
-               if (vpif_config_data->ch3_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                        channel3_clipping_enable(1);
        }
 
@@ -826,9 +827,11 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_display_config *config = vpif_dev->platform_data;
 
-       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-       strlcpy(cap->driver, "vpif display", sizeof(cap->driver));
-       strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(vpif_dev));
        strlcpy(cap->card, config->card_name, sizeof(cap->card));
 
        return 0;
@@ -935,6 +938,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
        enum v4l2_field field;
        struct vb2_queue *q;
        u8 index = 0;
+       int ret;
 
        /* This file handle has not initialized the channel,
           It is not allowed to do settings */
@@ -980,8 +984,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct vpif_disp_buffer);
 
-       vb2_queue_init(q);
-
+       ret = vb2_queue_init(q);
+       if (ret) {
+               vpif_err("vpif_display: vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
+               return ret;
+       }
        /* Set io allowed member of file handle to TRUE */
        fh->io_allowed[index] = 1;
        /* Increment io usrs member of channel object to 1 */
@@ -1173,14 +1181,16 @@ static int vpif_streamoff(struct file *file, void *priv,
        if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                /* disable channel */
                if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
-                       if (vpif_config_data->ch2_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                                channel2_clipping_enable(0);
                        enable_channel2(0);
                        channel2_intr_enable(0);
                }
                if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
                                        (2 == common->started)) {
-                       if (vpif_config_data->ch3_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                                channel3_clipping_enable(0);
                        enable_channel3(0);
                        channel3_intr_enable(0);
@@ -1213,49 +1223,126 @@ static int vpif_enum_output(struct file *file, void *fh,
 {
 
        struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
+       struct vpif_fh *vpif_handler = fh;
+       struct channel_obj *ch = vpif_handler->channel;
 
-       if (output->index >= config->output_count) {
+       chan_cfg = &config->chan_config[ch->channel_id];
+       if (output->index >= chan_cfg->output_count) {
                vpif_dbg(1, debug, "Invalid output index\n");
                return -EINVAL;
        }
 
-       strcpy(output->name, config->output[output->index]);
-       output->type = V4L2_OUTPUT_TYPE_ANALOG;
-       output->std = VPIF_V4L2_STD;
+       *output = chan_cfg->outputs[output->index].output;
+       return 0;
+}
+
+/**
+ * vpif_output_to_subdev() - Maps output to sub device
+ * @vpif_cfg - global config ptr
+ * @chan_cfg - channel config ptr
+ * @index - Given output index from application
+ *
+ * lookup the sub device information for a given output index.
+ * we report all the output to application. output table also
+ * has sub device name for the each output
+ */
+static int
+vpif_output_to_subdev(struct vpif_display_config *vpif_cfg,
+                     struct vpif_display_chan_config *chan_cfg, int index)
+{
+       struct vpif_subdev_info *subdev_info;
+       const char *subdev_name;
+       int i;
+
+       vpif_dbg(2, debug, "vpif_output_to_subdev\n");
+
+       if (chan_cfg->outputs == NULL)
+               return -1;
+
+       subdev_name = chan_cfg->outputs[index].subdev_name;
+       if (subdev_name == NULL)
+               return -1;
+
+       /* loop through the sub device list to get the sub device info */
+       for (i = 0; i < vpif_cfg->subdev_count; i++) {
+               subdev_info = &vpif_cfg->subdevinfo[i];
+               if (!strcmp(subdev_info->name, subdev_name))
+                       return i;
+       }
+       return -1;
+}
+
+/**
+ * vpif_set_output() - Select an output
+ * @vpif_cfg - global config ptr
+ * @ch - channel
+ * @index - Given output index from application
+ *
+ * Select the given output.
+ */
+static int vpif_set_output(struct vpif_display_config *vpif_cfg,
+                     struct channel_obj *ch, int index)
+{
+       struct vpif_display_chan_config *chan_cfg =
+               &vpif_cfg->chan_config[ch->channel_id];
+       struct vpif_subdev_info *subdev_info = NULL;
+       struct v4l2_subdev *sd = NULL;
+       u32 input = 0, output = 0;
+       int sd_index;
+       int ret;
+
+       sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index);
+       if (sd_index >= 0) {
+               sd = vpif_obj.sd[sd_index];
+               subdev_info = &vpif_cfg->subdevinfo[sd_index];
+       }
+
+       if (sd) {
+               input = chan_cfg->outputs[index].input_route;
+               output = chan_cfg->outputs[index].output_route;
+               ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       vpif_err("Failed to set output\n");
+                       return ret;
+               }
 
+       }
+       ch->output_idx = index;
+       ch->sd = sd;
+       if (chan_cfg->outputs != NULL)
+               /* update tvnorms from the sub device output info */
+               ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std;
        return 0;
 }
 
 static int vpif_s_output(struct file *file, void *priv, unsigned int i)
 {
+       struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       int ret = 0;
+
+       chan_cfg = &config->chan_config[ch->channel_id];
+
+       if (i >= chan_cfg->output_count)
+               return -EINVAL;
 
        if (common->started) {
                vpif_err("Streaming in progress\n");
                return -EBUSY;
        }
 
-       ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
-                                                       s_routing, 0, i, 0);
-
-       if (ret < 0)
-               vpif_err("Failed to set output standard\n");
-
-       vid_ch->output_id = i;
-       return ret;
+       return vpif_set_output(config, ch, i);
 }
 
 static int vpif_g_output(struct file *file, void *priv, unsigned int *i)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       *i = vid_ch->output_id;
+       *i = ch->output_idx;
 
        return 0;
 }
@@ -1290,10 +1377,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
-                       video, enum_dv_timings, timings);
+       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -EINVAL;
+       return ret;
 }
 
 /**
@@ -1319,13 +1408,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        }
 
        /* Configure subdevice timings, if any */
-       ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
-                       video, s_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD) {
-               vpif_dbg(2, debug, "Custom DV timings not supported by "
-                               "subdevice\n");
-               return -EINVAL;
-       }
+       ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               ret = 0;
        if (ret < 0) {
                vpif_dbg(2, debug, "Error setting custom DV timings\n");
                return ret;
@@ -1450,10 +1535,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg){
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
-                       g_register, reg);
+       return v4l2_subdev_call(ch->sd, core, g_register, reg);
 }
 
 /*
@@ -1469,10 +1552,8 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg){
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
-                       s_register, reg);
+       return v4l2_subdev_call(ch->sd, core, s_register, reg);
 }
 #endif
 
@@ -1536,9 +1617,6 @@ static struct video_device vpif_video_template = {
        .name           = "vpif",
        .fops           = &vpif_fops,
        .ioctl_ops      = &vpif_ioctl_ops,
-       .tvnorms        = VPIF_V4L2_STD,
-       .current_norm   = V4L2_STD_625_50,
-
 };
 
 /*Configure the channels, buffer sizei, request irq */
@@ -1611,7 +1689,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
        struct vpif_display_config *config;
-       int i, j = 0, k, q, m, err = 0;
+       int i, j = 0, k, err = 0;
+       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
        struct common_obj *common;
        struct channel_obj *ch;
@@ -1634,21 +1713,22 @@ static __init int vpif_probe(struct platform_device *pdev)
                return err;
        }
 
-       k = 0;
-       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
+       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
                for (i = res->start; i <= res->end; i++) {
                        if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
-                                       "VPIF_Display",
-                               (void *)(&vpif_obj.dev[k]->channel_id))) {
+                                       "VPIF_Display", (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id))) {
                                err = -EBUSY;
+                               for (j = 0; j < i; j++)
+                                       free_irq(j, (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id));
                                goto vpif_int_err;
                        }
                }
-               k++;
+               res_idx++;
        }
 
        for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
-
                /* Get the pointer to the channel object */
                ch = vpif_obj.dev[i];
 
@@ -1694,6 +1774,32 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
        }
 
+       i2c_adap = i2c_get_adapter(1);
+       config = pdev->dev.platform_data;
+       subdev_count = config->subdev_count;
+       subdevdata = config->subdevinfo;
+       vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
+                                                               GFP_KERNEL);
+       if (vpif_obj.sd == NULL) {
+               vpif_err("unable to allocate memory for subdevice pointers\n");
+               err = -ENOMEM;
+               goto vpif_sd_error;
+       }
+
+       for (i = 0; i < subdev_count; i++) {
+               vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+                                               i2c_adap,
+                                               &subdevdata[i].board_info,
+                                               NULL);
+               if (!vpif_obj.sd[i]) {
+                       vpif_err("Error registering v4l2 subdevice\n");
+                       goto probe_subdev_out;
+               }
+
+               if (vpif_obj.sd[i])
+                       vpif_obj.sd[i]->grp_id = 1 << i;
+       }
+
        for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
                ch = vpif_obj.dev[j];
                /* Initialize field of the channel objects */
@@ -1715,6 +1821,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 
                }
                ch->initialized = 0;
+               if (subdev_count)
+                       ch->sd = vpif_obj.sd[0];
                ch->channel_id = j;
                if (j < 2)
                        ch->common[VPIF_VIDEO_INDEX].numbuffers =
@@ -1729,6 +1837,12 @@ static __init int vpif_probe(struct platform_device *pdev)
                ch->common[VPIF_VIDEO_INDEX].fmt.type =
                                                V4L2_BUF_TYPE_VIDEO_OUTPUT;
                ch->video_dev->lock = &common->lock;
+               video_set_drvdata(ch->video_dev, ch);
+
+               /* select output 0 */
+               err = vpif_set_output(config, ch, 0);
+               if (err)
+                       goto probe_out;
 
                /* register video device */
                vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
@@ -1738,42 +1852,12 @@ static __init int vpif_probe(struct platform_device *pdev)
                                          VFL_TYPE_GRABBER, (j ? 3 : 2));
                if (err < 0)
                        goto probe_out;
-
-               video_set_drvdata(ch->video_dev, ch);
-       }
-
-       i2c_adap = i2c_get_adapter(1);
-       config = pdev->dev.platform_data;
-       subdev_count = config->subdev_count;
-       subdevdata = config->subdevinfo;
-       vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
-                                                               GFP_KERNEL);
-       if (vpif_obj.sd == NULL) {
-               vpif_err("unable to allocate memory for subdevice pointers\n");
-               err = -ENOMEM;
-               goto probe_out;
-       }
-
-       for (i = 0; i < subdev_count; i++) {
-               vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
-                                               i2c_adap,
-                                               &subdevdata[i].board_info,
-                                               NULL);
-               if (!vpif_obj.sd[i]) {
-                       vpif_err("Error registering v4l2 subdevice\n");
-                       goto probe_subdev_out;
-               }
-
-               if (vpif_obj.sd[i])
-                       vpif_obj.sd[i]->grp_id = 1 << i;
        }
 
        v4l2_info(&vpif_obj.v4l2_dev,
                        " VPIF display driver initialized\n");
        return 0;
 
-probe_subdev_out:
-       kfree(vpif_obj.sd);
 probe_out:
        for (k = 0; k < j; k++) {
                ch = vpif_obj.dev[k];
@@ -1781,14 +1865,21 @@ probe_out:
                video_device_release(ch->video_dev);
                ch->video_dev = NULL;
        }
+probe_subdev_out:
+       kfree(vpif_obj.sd);
+vpif_sd_error:
+       for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
+               ch = vpif_obj.dev[i];
+               /* Note: does nothing if ch->video_dev == NULL */
+               video_device_release(ch->video_dev);
+       }
 vpif_int_err:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
        vpif_err("VPIF IRQ request failed\n");
-       for (q = k; k >= 0; k--) {
-               for (m = i; m >= res->start; m--)
-                       free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id));
-               res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1);
-               m = res->end;
+       for (i = 0; i < res_idx; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               for (j = res->start; j <= res->end; j++)
+                       free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
        }
 
        return err;
index f628ebcf36747110c78c86f4b904d76a5fca2ff8..a5a18f74395cdfa80a8f5e56d314f949afcb9f84 100644 (file)
@@ -62,13 +62,6 @@ struct video_obj {
        v4l2_std_id stdid;              /* Currently selected or default
                                         * standard */
        struct v4l2_dv_timings dv_timings;
-       u32 output_id;                  /* Current output id */
-};
-
-struct vbi_obj {
-       int num_services;
-       struct vpif_vbi_params vbiparams;       /* vpif parameters for the raw
-                                                * vbi data */
 };
 
 struct vpif_disp_buffer {
@@ -131,12 +124,13 @@ struct channel_obj {
                                         * which is being displayed */
        u8 initialized;                 /* flag to indicate whether
                                         * encoder is initialized */
+       u32 output_idx;                 /* Current output index */
+       struct v4l2_subdev *sd;         /* Current output subdev(may be NULL) */
 
        enum vpif_channel_id channel_id;/* Identifies channel */
        struct vpif_params vpifparams;
        struct common_obj common[VPIF_NUMOBJECTS];
        struct video_obj video;
-       struct vbi_obj vbi;
 };
 
 /* File handle structure */
@@ -168,12 +162,4 @@ struct vpif_config_params {
        u8 min_numbuffers;
 };
 
-/* Struct which keeps track of the line numbers for the sliced vbi service */
-struct vpif_service_line {
-       u16 service_id;
-       u16 service_line[2];
-       u16 enc_service_id;
-       u8 bytestowrite;
-};
-
 #endif                         /* DAVINCIHD_DISPLAY_H */
index 0d8625f03a32f9099920586a47e5f82ae0384332..0146b354dc22a785961dfe0e1dd5df6214311c53 100644 (file)
@@ -212,7 +212,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
                else
                        cfg |= GSC_IN_YUV422_3P;
                break;
-       };
+       }
 
        writel(cfg, dev->regs + GSC_IN_CON);
 }
@@ -332,7 +332,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
        case 3:
                cfg |= GSC_OUT_YUV420_3P;
                break;
-       };
+       }
 
 end_set:
        writel(cfg, dev->regs + GSC_OUT_CON);
index 897250b886474c0c950e23b0279e9f5e22343329..31ac4dc692475a5b5f1339941617569fd936f43e 100644 (file)
@@ -864,7 +864,7 @@ int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *
 {
        struct viu_fh  *fh = priv;
        struct viu_dev *dev = fh->dev;
-       struct v4l2_framebuffer *fb = arg;
+       const struct v4l2_framebuffer *fb = arg;
        struct viu_fmt *fmt;
 
        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
index d03637537118047a6ced26241cb55842de398d02..2e2121e98133d0ff56f7510c79a06cac8b9182d8 100644 (file)
@@ -397,8 +397,7 @@ static void device_isr(unsigned long priv)
        curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
 
        if (NULL == curr_ctx) {
-               printk(KERN_ERR
-                       "Instance released before the end of transaction\n");
+               pr_err("Instance released before the end of transaction\n");
                return;
        }
 
@@ -894,7 +893,7 @@ static int m2mtest_open(struct file *file)
 
        if (mutex_lock_interruptible(&dev->dev_mutex))
                return -ERESTARTSYS;
-       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                rc = -ENOMEM;
                goto open_unlock;
@@ -1020,7 +1019,7 @@ static int m2mtest_probe(struct platform_device *pdev)
        struct video_device *vfd;
        int ret;
 
-       dev = kzalloc(sizeof *dev, GFP_KERNEL);
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
 
@@ -1028,7 +1027,7 @@ static int m2mtest_probe(struct platform_device *pdev)
 
        ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
        if (ret)
-               goto free_dev;
+               return ret;
 
        atomic_set(&dev->num_inst, 0);
        mutex_init(&dev->dev_mutex);
@@ -1067,15 +1066,13 @@ static int m2mtest_probe(struct platform_device *pdev)
 
        return 0;
 
-       v4l2_m2m_release(dev->m2m_dev);
 err_m2m:
+       v4l2_m2m_release(dev->m2m_dev);
        video_unregister_device(dev->vfd);
 rel_vdev:
        video_device_release(vfd);
 unreg_dev:
        v4l2_device_unregister(&dev->v4l2_dev);
-free_dev:
-       kfree(dev);
 
        return ret;
 }
@@ -1090,7 +1087,6 @@ static int m2mtest_remove(struct platform_device *pdev)
        del_timer_sync(&dev->timer);
        video_unregister_device(dev->vfd);
        v4l2_device_unregister(&dev->v4l2_dev);
-       kfree(dev);
 
        return 0;
 }
index 084ea77d65a75a454eccd76c1746b04cb5d4668a..e2c57f334c5d4a4da780069bf5869eb383f4b4a0 100644 (file)
 #ifndef OMAP3_ISP_REG_H
 #define OMAP3_ISP_REG_H
 
-#include <plat/omap34xx.h>
-
-
 #define CM_CAM_MCLK_HZ                 172800000       /* Hz */
 
 /* ISP Submodules offset */
 
+#define L4_34XX_BASE                   0x48000000
+#define OMAP3430_ISP_BASE              (L4_34XX_BASE + 0xBC000)
+
 #define OMAP3ISP_REG_BASE              OMAP3430_ISP_BASE
 #define OMAP3ISP_REG(offset)           (OMAP3ISP_REG_BASE + (offset))
 
index dded988152206e779c3f49844d5ade4a09f14663..367efd164d0f1c9580111b12b51c8e2a9f225bfa 100644 (file)
@@ -177,7 +177,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
 
 void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
 {
+       struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
        struct fimc_vid_cap *cap = &fimc->vid_cap;
+       struct fimc_frame *f = &cap->ctx->d_frame;
        struct fimc_vid_buffer *v_buf;
        struct timeval *tv;
        struct timespec ts;
@@ -216,6 +218,25 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
                if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
                        cap->buf_index = 0;
        }
+       /*
+        * Set up a buffer at MIPI-CSIS if current image format
+        * requires the frame embedded data capture.
+        */
+       if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) {
+               unsigned int plane = ffs(f->fmt->mdataplanes) - 1;
+               unsigned int size = f->payload[plane];
+               s32 index = fimc_hw_get_frame_index(fimc);
+               void *vaddr;
+
+               list_for_each_entry(v_buf, &cap->active_buf_q, list) {
+                       if (v_buf->index != index)
+                               continue;
+                       vaddr = vb2_plane_vaddr(&v_buf->vb, plane);
+                       v4l2_subdev_call(csis, video, s_rx_buffer,
+                                        vaddr, &size);
+                       break;
+               }
+       }
 
        if (cap->active_buf_cnt == 0) {
                if (deq_buf)
@@ -351,6 +372,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
                unsigned int size = (wh * fmt->depth[i]) / 8;
                if (pixm)
                        sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
+               else if (fimc_fmt_is_user_defined(fmt->color))
+                       sizes[i] = frame->payload[i];
                else
                        sizes[i] = max_t(u32, size, frame->payload[i]);
 
@@ -611,10 +634,10 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
        u32 mask = FMT_FLAGS_CAM;
        struct fimc_fmt *ffmt;
 
-       /* Color conversion from/to JPEG is not supported */
+       /* Conversion from/to JPEG or User Defined format is not supported */
        if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
-           fimc_fmt_is_jpeg(ctx->s_frame.fmt->color))
-               *code = V4L2_MBUS_FMT_JPEG_1X8;
+           fimc_fmt_is_user_defined(ctx->s_frame.fmt->color))
+               *code = ctx->s_frame.fmt->mbus_code;
 
        if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK)
                mask |= FMT_FLAGS_M2M;
@@ -628,18 +651,19 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
                *fourcc = ffmt->fourcc;
 
        if (pad == FIMC_SD_PAD_SINK) {
-               max_w = fimc_fmt_is_jpeg(ffmt->color) ?
+               max_w = fimc_fmt_is_user_defined(ffmt->color) ?
                        pl->scaler_dis_w : pl->scaler_en_w;
                /* Apply the camera input interface pixel constraints */
                v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
                                      height, max_t(u32, *height, 32),
                                      FIMC_CAMIF_MAX_HEIGHT,
-                                     fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1,
+                                     fimc_fmt_is_user_defined(ffmt->color) ?
+                                     3 : 1,
                                      0);
                return ffmt;
        }
        /* Can't scale or crop in transparent (JPEG) transfer mode */
-       if (fimc_fmt_is_jpeg(ffmt->color)) {
+       if (fimc_fmt_is_user_defined(ffmt->color)) {
                *width  = ctx->s_frame.f_width;
                *height = ctx->s_frame.f_height;
                return ffmt;
@@ -684,7 +708,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx,
        u32 max_sc_h, max_sc_v;
 
        /* In JPEG transparent transfer mode cropping is not supported */
-       if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) {
+       if (fimc_fmt_is_user_defined(ctx->d_frame.fmt->color)) {
                r->width  = sink->f_width;
                r->height = sink->f_height;
                r->left   = r->top = 0;
@@ -847,6 +871,48 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
        return 0;
 }
 
+/**
+ * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters
+ * @sensor: pointer to the sensor subdev
+ * @plane_fmt: provides plane sizes corresponding to the frame layout entries
+ * @try: true to set the frame parameters, false to query only
+ *
+ * This function is used by this driver only for compressed/blob data formats.
+ */
+static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
+                                     struct v4l2_plane_pix_format *plane_fmt,
+                                     unsigned int num_planes, bool try)
+{
+       struct v4l2_mbus_frame_desc fd;
+       int i, ret;
+
+       for (i = 0; i < num_planes; i++)
+               fd.entry[i].length = plane_fmt[i].sizeimage;
+
+       if (try)
+               ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd);
+       else
+               ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd);
+
+       if (ret < 0)
+               return ret;
+
+       if (num_planes != fd.num_entries)
+               return -EINVAL;
+
+       for (i = 0; i < num_planes; i++)
+               plane_fmt[i].sizeimage = fd.entry[i].length;
+
+       if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) {
+               v4l2_err(sensor->v4l2_dev,  "Unsupported buffer size: %u\n",
+                        fd.entry[0].length);
+
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
                                 struct v4l2_format *f)
 {
@@ -865,7 +931,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
        struct v4l2_mbus_framefmt mf;
        struct fimc_fmt *ffmt = NULL;
 
-       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+       if (fimc_jpeg_fourcc(pix->pixelformat)) {
                fimc_capture_try_format(ctx, &pix->width, &pix->height,
                                        NULL, &pix->pixelformat,
                                        FIMC_SD_PAD_SINK);
@@ -879,25 +945,32 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
                return -EINVAL;
 
        if (!fimc->vid_cap.user_subdev_api) {
-               mf.width  = pix->width;
+               mf.width = pix->width;
                mf.height = pix->height;
-               mf.code   = ffmt->mbus_code;
+               mf.code = ffmt->mbus_code;
                fimc_md_graph_lock(fimc);
                fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
                fimc_md_graph_unlock(fimc);
-
-               pix->width       = mf.width;
-               pix->height      = mf.height;
+               pix->width = mf.width;
+               pix->height = mf.height;
                if (ffmt)
                        pix->pixelformat = ffmt->fourcc;
        }
 
        fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
+
+       if (ffmt->flags & FMT_FLAGS_COMPRESSED)
+               fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
+                                       pix->plane_fmt, ffmt->memplanes, true);
+
        return 0;
 }
 
-static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg)
+static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
+                                       enum fimc_color_fmt color)
 {
+       bool jpeg = fimc_fmt_is_user_defined(color);
+
        ctx->scaler.enabled = !jpeg;
        fimc_ctrls_activate(ctx, !jpeg);
 
@@ -920,7 +993,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
                return -EBUSY;
 
        /* Pre-configure format at camera interface input, for JPEG only */
-       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+       if (fimc_jpeg_fourcc(pix->pixelformat)) {
                fimc_capture_try_format(ctx, &pix->width, &pix->height,
                                        NULL, &pix->pixelformat,
                                        FIMC_SD_PAD_SINK);
@@ -953,7 +1026,16 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
        }
 
        fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
-       for (i = 0; i < ff->fmt->colplanes; i++)
+
+       if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
+               ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
+                                       pix->plane_fmt, ff->fmt->memplanes,
+                                       true);
+               if (ret < 0)
+                       return ret;
+       }
+
+       for (i = 0; i < ff->fmt->memplanes; i++)
                ff->payload[i] = pix->plane_fmt[i].sizeimage;
 
        set_frame_bounds(ff, pix->width, pix->height);
@@ -961,7 +1043,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
        if (!(ctx->state & FIMC_COMPOSE))
                set_frame_crop(ff, 0, 0, pix->width, pix->height);
 
-       fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color));
+       fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color);
 
        /* Reset cropping and set format at the camera interface input */
        if (!fimc->vid_cap.user_subdev_api) {
@@ -1063,6 +1145,23 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
                    src_fmt.format.height != sink_fmt.format.height ||
                    src_fmt.format.code != sink_fmt.format.code)
                        return -EPIPE;
+
+               if (sd == fimc->pipeline.subdevs[IDX_SENSOR] &&
+                   fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
+                       struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
+                       struct fimc_frame *frame = &vid_cap->ctx->d_frame;
+                       unsigned int i;
+
+                       ret = fimc_get_sensor_frame_desc(sd, plane_fmt,
+                                                        frame->fmt->memplanes,
+                                                        false);
+                       if (ret < 0)
+                               return -EPIPE;
+
+                       for (i = 0; i < frame->fmt->memplanes; i++)
+                               if (frame->payload[i] < plane_fmt[i].sizeimage)
+                                       return -EPIPE;
+               }
        }
        return 0;
 }
@@ -1424,7 +1523,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
        /* Update RGB Alpha control state and value range */
        fimc_alpha_ctrl_update(ctx);
 
-       fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
+       fimc_capture_mark_jpeg_xfer(ctx, ffmt->color);
 
        ff = fmt->pad == FIMC_SD_PAD_SINK ?
                &ctx->s_frame : &ctx->d_frame;
index 1a445404e73d2bea57a2e788e21717a7f21fb6ac..8d0d2b94a135f45b0d8fa2c1378fd287aff7ef27 100644 (file)
@@ -184,7 +184,17 @@ static struct fimc_fmt fimc_formats[] = {
                .memplanes      = 1,
                .colplanes      = 1,
                .mbus_code      = V4L2_MBUS_FMT_JPEG_1X8,
-               .flags          = FMT_FLAGS_CAM,
+               .flags          = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
+       }, {
+               .name           = "S5C73MX interleaved UYVY/JPEG",
+               .fourcc         = V4L2_PIX_FMT_S5C_UYVY_JPG,
+               .color          = FIMC_FMT_YUYV_JPEG,
+               .depth          = { 8 },
+               .memplanes      = 2,
+               .colplanes      = 1,
+               .mdataplanes    = 0x2, /* plane 1 holds frame meta data */
+               .mbus_code      = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
+               .flags          = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
        },
 };
 
@@ -371,7 +381,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
                default:
                        return -EINVAL;
                }
-       } else {
+       } else if (!frame->fmt->mdataplanes) {
                if (frame->fmt->memplanes >= 2)
                        paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
 
@@ -698,6 +708,11 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
                if (frame->fmt->colplanes == 1) /* packed formats */
                        bpl = (bpl * frame->fmt->depth[0]) / 8;
                pixm->plane_fmt[i].bytesperline = bpl;
+
+               if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) {
+                       pixm->plane_fmt[i].sizeimage = frame->payload[i];
+                       continue;
+               }
                pixm->plane_fmt[i].sizeimage = (frame->o_width *
                        frame->o_height * frame->fmt->depth[i]) / 8;
        }
index cd716ba6015f6e5c441c84a4fe34627f1121ee47..c0040d7924995051e71faaed70942cb2b74ec7c6 100644 (file)
@@ -40,6 +40,8 @@
 #define SCALER_MAX_VRATIO      64
 #define DMA_MIN_SIZE           8
 #define FIMC_CAMIF_MAX_HEIGHT  0x2000
+#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M)
+#define FIMC_MAX_PLANES                3
 
 /* indices to the clocks array */
 enum {
@@ -83,7 +85,7 @@ enum fimc_datapath {
 };
 
 enum fimc_color_fmt {
-       FIMC_FMT_RGB444 = 0x10,
+       FIMC_FMT_RGB444 = 0x10,
        FIMC_FMT_RGB555,
        FIMC_FMT_RGB565,
        FIMC_FMT_RGB666,
@@ -95,14 +97,15 @@ enum fimc_color_fmt {
        FIMC_FMT_CBYCRY422,
        FIMC_FMT_CRYCBY422,
        FIMC_FMT_YCBCR444_LOCAL,
-       FIMC_FMT_JPEG = 0x40,
-       FIMC_FMT_RAW8 = 0x80,
+       FIMC_FMT_RAW8 = 0x40,
        FIMC_FMT_RAW10,
        FIMC_FMT_RAW12,
+       FIMC_FMT_JPEG = 0x80,
+       FIMC_FMT_YUYV_JPEG = 0x100,
 };
 
+#define fimc_fmt_is_user_defined(x) (!!((x) & 0x180))
 #define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
-#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
 
 #define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
                        __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -139,6 +142,7 @@ enum fimc_color_fmt {
  * @memplanes: number of physically non-contiguous data planes
  * @colplanes: number of physically contiguous data planes
  * @depth: per plane driver's private 'number of bits per pixel'
+ * @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no)
  * @flags: flags indicating which operation mode format applies to
  */
 struct fimc_fmt {
@@ -149,12 +153,14 @@ struct fimc_fmt {
        u16     memplanes;
        u16     colplanes;
        u8      depth[VIDEO_MAX_PLANES];
+       u16     mdataplanes;
        u16     flags;
 #define FMT_FLAGS_CAM          (1 << 0)
 #define FMT_FLAGS_M2M_IN       (1 << 1)
 #define FMT_FLAGS_M2M_OUT      (1 << 2)
 #define FMT_FLAGS_M2M          (1 << 1 | 1 << 2)
 #define FMT_HAS_ALPHA          (1 << 3)
+#define FMT_FLAGS_COMPRESSED   (1 << 4)
 };
 
 /**
@@ -272,7 +278,7 @@ struct fimc_frame {
        u32     offs_v;
        u32     width;
        u32     height;
-       unsigned long           payload[VIDEO_MAX_PLANES];
+       unsigned int            payload[VIDEO_MAX_PLANES];
        struct fimc_addr        paddr;
        struct fimc_dma_offset  dma_offset;
        struct fimc_fmt         *fmt;
@@ -577,6 +583,18 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
        return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
 }
 
+static inline bool fimc_jpeg_fourcc(u32 pixelformat)
+{
+       return (pixelformat == V4L2_PIX_FMT_JPEG ||
+               pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG);
+}
+
+static inline bool fimc_user_defined_mbus_fmt(u32 code)
+{
+       return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
+               code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
+}
+
 /* Return the alpha component bit mask */
 static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
 {
index 6b71d953fd15b1a533f90a39d0eb0b9ed112b17c..4500e44f6857c909adcbd74cb13ad4dc2ac85cbc 100644 (file)
@@ -551,30 +551,31 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
        return 0;
 }
 
-static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr)
+static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        struct fimc_ctx *ctx = fh_to_ctx(fh);
        struct fimc_dev *fimc = ctx->fimc_dev;
+       struct v4l2_crop cr = *crop;
        struct fimc_frame *f;
        int ret;
 
-       ret = fimc_m2m_try_crop(ctx, cr);
+       ret = fimc_m2m_try_crop(ctx, &cr);
        if (ret)
                return ret;
 
-       f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
+       f = (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
                &ctx->s_frame : &ctx->d_frame;
 
        /* Check to see if scaling ratio is within supported range */
        if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
-               if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-                       ret = fimc_check_scaler_ratio(ctx, cr->c.width,
-                                       cr->c.height, ctx->d_frame.width,
+               if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+                       ret = fimc_check_scaler_ratio(ctx, cr.c.width,
+                                       cr.c.height, ctx->d_frame.width,
                                        ctx->d_frame.height, ctx->rotation);
                } else {
                        ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
-                                       ctx->s_frame.height, cr->c.width,
-                                       cr->c.height, ctx->rotation);
+                                       ctx->s_frame.height, cr.c.width,
+                                       cr.c.height, ctx->rotation);
                }
                if (ret) {
                        v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n");
@@ -582,10 +583,10 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *
                }
        }
 
-       f->offs_h = cr->c.left;
-       f->offs_v = cr->c.top;
-       f->width  = cr->c.width;
-       f->height = cr->c.height;
+       f->offs_h = cr.c.left;
+       f->offs_v = cr.c.top;
+       f->width  = cr.c.width;
+       f->height = cr.c.height;
 
        fimc_ctx_state_set(FIMC_PARAMS, ctx);
 
index 783408fd7d566b53b165e5bd896ee8aaef38c4ea..2c9d0c06c9e8faef0be5645508ad8495b9356844 100644 (file)
@@ -625,7 +625,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
                                cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
                } /* else defaults to ITU-R BT.656 8-bit */
        } else if (cam->bus_type == FIMC_MIPI_CSI2) {
-               if (fimc_fmt_is_jpeg(f->fmt->color))
+               if (fimc_fmt_is_user_defined(f->fmt->color))
                        cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
        }
 
@@ -680,6 +680,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
                        tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
                        break;
                case V4L2_MBUS_FMT_JPEG_1X8:
+               case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
                        tmp = FIMC_REG_CSIIMGFMT_USER(1);
                        cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
                        break;
@@ -744,13 +745,13 @@ void fimc_hw_dis_capture(struct fimc_dev *dev)
 }
 
 /* Return an index to the buffer actually being written. */
-u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
+s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
 {
-       u32 reg;
+       s32 reg;
 
        if (dev->variant->has_cistatus2) {
-               reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3F;
-               return reg > 0 ? --reg : reg;
+               reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
+               return reg - 1;
        }
 
        reg = readl(dev->regs + FIMC_REG_CISTATUS);
@@ -759,6 +760,18 @@ u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
                FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
 }
 
+/* Return an index to the buffer being written previously. */
+s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
+{
+       s32 reg;
+
+       if (!dev->variant->has_cistatus2)
+               return -1;
+
+       reg = readl(dev->regs + FIMC_REG_CISTATUS2);
+       return ((reg >> 7) & 0x3f) - 1;
+}
+
 /* Locking: the caller holds fimc->slock */
 void fimc_activate_capture(struct fimc_ctx *ctx)
 {
index 579ac8ac03deb76c2f78ef5f63ac63a35676f545..b6abfc7b72ace7472c7caea9d398500f3402be08 100644 (file)
@@ -307,7 +307,8 @@ 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);
-u32 fimc_hw_get_frame_index(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);
 void fimc_deactivate_capture(struct fimc_dev *fimc);
 
index e92236ac5cfe86e5787f0f95bc057a920d3d4255..4c961b1b68e6004ab1dd98d578b0e6cc407e97f9 100644 (file)
@@ -2,7 +2,7 @@
  * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
  *
  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
- * Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -98,6 +98,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
 #define CSIS_MAX_PIX_WIDTH             0xffff
 #define CSIS_MAX_PIX_HEIGHT            0xffff
 
+/* Non-image packet data buffers */
+#define S5PCSIS_PKTDATA_ODD            0x2000
+#define S5PCSIS_PKTDATA_EVEN           0x3000
+#define S5PCSIS_PKTDATA_SIZE           SZ_4K
+
 enum {
        CSIS_CLK_MUX,
        CSIS_CLK_GATE,
@@ -110,8 +115,8 @@ static char *csi_clock_name[] = {
 #define NUM_CSIS_CLOCKS        ARRAY_SIZE(csi_clock_name)
 
 static const char * const csis_supply_name[] = {
-       "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
-       "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
+       "vddcore",  /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
+       "vddio",    /* CSIS I/O and PLL (1.8V) supply */
 };
 #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
 
@@ -144,12 +149,18 @@ static const struct s5pcsis_event s5pcsis_events[] = {
 };
 #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
 
+struct csis_pktbuf {
+       u32 *data;
+       unsigned int len;
+};
+
 /**
  * struct csis_state - the driver's internal state data structure
  * @lock: mutex serializing the subdev and power management operations,
  *        protecting @format and @flags members
  * @pads: CSIS pads array
  * @sd: v4l2_subdev associated with CSIS device instance
+ * @index: the hardware instance index
  * @pdev: CSIS platform device
  * @regs: mmaped I/O registers memory
  * @supplies: CSIS regulator supplies
@@ -159,12 +170,14 @@ static const struct s5pcsis_event s5pcsis_events[] = {
  * @csis_fmt: current CSIS pixel format
  * @format: common media bus format for the source and sink pad
  * @slock: spinlock protecting structure members below
+ * @pkt_buf: the frame embedded (non-image) data buffer
  * @events: MIPI-CSIS event (error) counters
  */
 struct csis_state {
        struct mutex lock;
        struct media_pad pads[CSIS_PADS_NUM];
        struct v4l2_subdev sd;
+       u8 index;
        struct platform_device *pdev;
        void __iomem *regs;
        struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
@@ -175,6 +188,7 @@ struct csis_state {
        struct v4l2_mbus_framefmt format;
 
        struct spinlock slock;
+       struct csis_pktbuf pkt_buf;
        struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
 };
 
@@ -202,7 +216,11 @@ static const struct csis_pix_format s5pcsis_formats[] = {
                .code = V4L2_MBUS_FMT_JPEG_1X8,
                .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
                .data_alignment = 32,
-       },
+       }, {
+               .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
+               .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
+               .data_alignment = 32,
+       }
 };
 
 #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
@@ -266,7 +284,7 @@ static void __s5pcsis_set_format(struct csis_state *state)
        struct v4l2_mbus_framefmt *mf = &state->format;
        u32 val;
 
-       v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n",
+       v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
                 mf->code, mf->width, mf->height);
 
        /* Color format */
@@ -304,8 +322,10 @@ static void s5pcsis_set_params(struct csis_state *state)
                val |= S5PCSIS_CTRL_ALIGN_32BIT;
        else /* 24-bits */
                val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
-       /* Not using external clock. */
+
        val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
+       if (pdata->wclk_source)
+               val |= S5PCSIS_CTRL_WCLK_EXTCLK;
        s5pcsis_write(state, S5PCSIS_CTRL, val);
 
        /* Update the shadow register. */
@@ -529,6 +549,22 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
+static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
+                              unsigned int *size)
+{
+       struct csis_state *state = sd_to_csis_state(sd);
+       unsigned long flags;
+
+       *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
+
+       spin_lock_irqsave(&state->slock, flags);
+       state->pkt_buf.data = buf;
+       state->pkt_buf.len = *size;
+       spin_unlock_irqrestore(&state->slock, flags);
+
+       return 0;
+}
+
 static int s5pcsis_log_status(struct v4l2_subdev *sd)
 {
        struct csis_state *state = sd_to_csis_state(sd);
@@ -566,6 +602,7 @@ static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
 };
 
 static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
+       .s_rx_buffer = s5pcsis_s_rx_buffer,
        .s_stream = s5pcsis_s_stream,
 };
 
@@ -578,13 +615,26 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
 static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
 {
        struct csis_state *state = dev_id;
+       struct csis_pktbuf *pktbuf = &state->pkt_buf;
        unsigned long flags;
        u32 status;
 
        status = s5pcsis_read(state, S5PCSIS_INTSRC);
-
        spin_lock_irqsave(&state->slock, flags);
 
+       if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
+               u32 offset;
+
+               if (status & S5PCSIS_INTSRC_EVEN)
+                       offset = S5PCSIS_PKTDATA_EVEN;
+               else
+                       offset = S5PCSIS_PKTDATA_ODD;
+
+               memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
+               pktbuf->data = NULL;
+               rmb();
+       }
+
        /* Update the event/error counters */
        if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
                int i;
@@ -620,14 +670,15 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
        spin_lock_init(&state->slock);
 
        state->pdev = pdev;
+       state->index = max(0, pdev->id);
 
        pdata = pdev->dev.platform_data;
-       if (pdata == NULL || pdata->phy_enable == NULL) {
+       if (pdata == NULL) {
                dev_err(&pdev->dev, "Platform data not fully specified\n");
                return -EINVAL;
        }
 
-       if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
+       if ((state->index == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
            pdata->lanes > CSIS0_MAX_LANES) {
                dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
                        pdata->lanes);
@@ -710,7 +761,6 @@ e_clkput:
 
 static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
 {
-       struct s5p_platform_mipi_csis *pdata = dev->platform_data;
        struct platform_device *pdev = to_platform_device(dev);
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csis_state *state = sd_to_csis_state(sd);
@@ -722,7 +772,7 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
        mutex_lock(&state->lock);
        if (state->flags & ST_POWERED) {
                s5pcsis_stop_stream(state);
-               ret = pdata->phy_enable(state->pdev, false);
+               ret = s5p_csis_phy_enable(state->index, false);
                if (ret)
                        goto unlock;
                ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
@@ -741,7 +791,6 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
 
 static int s5pcsis_pm_resume(struct device *dev, bool runtime)
 {
-       struct s5p_platform_mipi_csis *pdata = dev->platform_data;
        struct platform_device *pdev = to_platform_device(dev);
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csis_state *state = sd_to_csis_state(sd);
@@ -759,7 +808,7 @@ static int s5pcsis_pm_resume(struct device *dev, bool runtime)
                                            state->supplies);
                if (ret)
                        goto unlock;
-               ret = pdata->phy_enable(state->pdev, true);
+               ret = s5p_csis_phy_enable(state->index, true);
                if (!ret) {
                        state->flags |= ST_POWERED;
                } else {
index 1e3b9dd014c094655d7e5b6719c60d06c48d49a8..1bfbc325836b7077b9609da1af8f9958b92d4608 100644 (file)
@@ -507,7 +507,7 @@ static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
        return 0;
 }
 
-static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
 {
        struct g2d_ctx *ctx = prv;
        struct g2d_dev *dev = ctx->dev;
index 394775ae5774f4d21d98719c3afae2343b658466..17983c4c9a9aca9a12e63e60853bde15a0f5f6ca 100644 (file)
@@ -1353,7 +1353,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
                return ret;
        }
        dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
-       clk_enable(jpeg->clk);
+       clk_prepare_enable(jpeg->clk);
 
        /* v4l2 device */
        ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
@@ -1460,7 +1460,7 @@ device_register_rollback:
        v4l2_device_unregister(&jpeg->v4l2_dev);
 
 clk_get_rollback:
-       clk_disable(jpeg->clk);
+       clk_disable_unprepare(jpeg->clk);
        clk_put(jpeg->clk);
 
        return ret;
@@ -1480,7 +1480,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
        v4l2_m2m_release(jpeg->m2m_dev);
        v4l2_device_unregister(&jpeg->v4l2_dev);
 
-       clk_disable(jpeg->clk);
+       clk_disable_unprepare(jpeg->clk);
        clk_put(jpeg->clk);
 
        return 0;
index d0663409af0066d960b37da99a8e902359ffdfac..379008c6d09adfca74f45afda0109b2bb3640768 100644 (file)
@@ -1,5 +1,6 @@
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
-s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
+s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
 s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
-s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
-s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
+s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
+s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o
+s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
new file mode 100644 (file)
index 0000000..363a97c
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _REGS_FIMV_V6_H
+#define _REGS_FIMV_V6_H
+
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
+#define S5P_FIMV_REG_SIZE_V6   (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
+#define S5P_FIMV_REG_COUNT_V6  ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
+
+/* Number of bits that the buffer address should be shifted for particular
+ * MFC buffers.  */
+#define S5P_FIMV_MEM_OFFSET_V6         0
+
+#define S5P_FIMV_START_ADDR_V6         0x0000
+#define S5P_FIMV_END_ADDR_V6           0xfd80
+
+#define S5P_FIMV_REG_CLEAR_BEGIN_V6    0xf000
+#define S5P_FIMV_REG_CLEAR_COUNT_V6    1024
+
+/* Codec Common Registers */
+#define S5P_FIMV_RISC_ON_V6                    0x0000
+#define S5P_FIMV_RISC2HOST_INT_V6              0x003C
+#define S5P_FIMV_HOST2RISC_INT_V6              0x0044
+#define S5P_FIMV_RISC_BASE_ADDRESS_V6          0x0054
+
+#define S5P_FIMV_MFC_RESET_V6                  0x1070
+
+#define S5P_FIMV_HOST2RISC_CMD_V6              0x1100
+#define S5P_FIMV_H2R_CMD_EMPTY_V6              0
+#define S5P_FIMV_H2R_CMD_SYS_INIT_V6           1
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6      2
+#define S5P_FIMV_CH_SEQ_HEADER_V6              3
+#define S5P_FIMV_CH_INIT_BUFS_V6               4
+#define S5P_FIMV_CH_FRAME_START_V6             5
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6     6
+#define S5P_FIMV_H2R_CMD_SLEEP_V6              7
+#define S5P_FIMV_H2R_CMD_WAKEUP_V6             8
+#define S5P_FIMV_CH_LAST_FRAME_V6              9
+#define S5P_FIMV_H2R_CMD_FLUSH_V6              10
+/* RMVME: REALLOC used? */
+#define S5P_FIMV_CH_FRAME_START_REALLOC_V6     5
+
+#define S5P_FIMV_RISC2HOST_CMD_V6              0x1104
+#define S5P_FIMV_R2H_CMD_EMPTY_V6              0
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6       1
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6  2
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6       3
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6   4
+
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6
+#define S5P_FIMV_R2H_CMD_SLEEP_RET_V6          7
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6         8
+#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6   9
+#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6      10
+#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6      11
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6      12
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6     13
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6     14
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6     15
+#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
+#define S5P_FIMV_R2H_CMD_ERR_RET_V6            32
+
+#define S5P_FIMV_FW_VERSION_V6                 0xf000
+
+#define S5P_FIMV_INSTANCE_ID_V6                        0xf008
+#define S5P_FIMV_CODEC_TYPE_V6                 0xf00c
+#define S5P_FIMV_CONTEXT_MEM_ADDR_V6           0xf014
+#define S5P_FIMV_CONTEXT_MEM_SIZE_V6           0xf018
+#define S5P_FIMV_PIXEL_FORMAT_V6               0xf020
+
+#define S5P_FIMV_METADATA_ENABLE_V6            0xf024
+#define S5P_FIMV_DBG_BUFFER_ADDR_V6            0xf030
+#define S5P_FIMV_DBG_BUFFER_SIZE_V6            0xf034
+#define S5P_FIMV_RET_INSTANCE_ID_V6            0xf070
+
+#define S5P_FIMV_ERROR_CODE_V6                 0xf074
+#define S5P_FIMV_ERR_WARNINGS_START_V6         160
+#define S5P_FIMV_ERR_DEC_MASK_V6               0xffff
+#define S5P_FIMV_ERR_DEC_SHIFT_V6              0
+#define S5P_FIMV_ERR_DSPL_MASK_V6              0xffff0000
+#define S5P_FIMV_ERR_DSPL_SHIFT_V6             16
+
+#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6     0xf078
+#define S5P_FIMV_METADATA_STATUS_V6            0xf07C
+#define S5P_FIMV_METADATA_ADDR_MB_INFO_V6      0xf080
+#define S5P_FIMV_METADATA_SIZE_MB_INFO_V6      0xf084
+
+/* Decoder Registers */
+#define S5P_FIMV_D_CRC_CTRL_V6                 0xf0b0
+#define S5P_FIMV_D_DEC_OPTIONS_V6              0xf0b4
+#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6    4
+#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6      3
+#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6                1
+#define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6         0x3
+#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6      0
+
+#define S5P_FIMV_D_DISPLAY_DELAY_V6            0xf0b8
+
+#define S5P_FIMV_D_SET_FRAME_WIDTH_V6          0xf0bc
+#define S5P_FIMV_D_SET_FRAME_HEIGHT_V6         0xf0c0
+
+#define S5P_FIMV_D_SEI_ENABLE_V6               0xf0c4
+
+/* Buffer setting registers */
+#define S5P_FIMV_D_MIN_NUM_DPB_V6              0xf0f0
+#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6                0xf0f4
+#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6      0xf0f8
+#define S5P_FIMV_D_MVC_NUM_VIEWS_V6            0xf0fc
+#define S5P_FIMV_D_MIN_NUM_MV_V6               0xf100
+#define S5P_FIMV_D_NUM_DPB_V6                  0xf130
+#define S5P_FIMV_D_LUMA_DPB_SIZE_V6            0xf134
+#define S5P_FIMV_D_CHROMA_DPB_SIZE_V6          0xf138
+#define S5P_FIMV_D_MV_BUFFER_SIZE_V6           0xf13c
+
+#define S5P_FIMV_D_LUMA_DPB_V6                 0xf140
+#define S5P_FIMV_D_CHROMA_DPB_V6               0xf240
+#define S5P_FIMV_D_MV_BUFFER_V6                        0xf340
+
+#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6      0xf440
+#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6      0xf444
+#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6     0xf448
+#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6     0xf44c
+#define S5P_FIMV_D_NUM_MV_V6                   0xf478
+#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6          0xf4b0
+#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6          0xf4b4
+
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc
+#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6                0xf4c0
+#define S5P_FIMV_D_SLICE_IF_ENABLE_V6          0xf4c4
+#define S5P_FIMV_D_PICTURE_TAG_V6              0xf4c8
+#define S5P_FIMV_D_STREAM_DATA_SIZE_V6         0xf4d0
+
+/* Display information register */
+#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6      0xf500
+#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6     0xf504
+
+/* Display status */
+#define S5P_FIMV_D_DISPLAY_STATUS_V6           0xf508
+
+#define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6                0xf50c
+#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6      0xf510
+
+#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6       0xf514
+
+#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6       0xf518
+#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6       0xf51c
+#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6  0xf520
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6     0xf524
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6   0xf528
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6     0xf52c
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6   0xf530
+#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6     0xf534
+#define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6      0xf538
+
+/* Decoded picture information register */
+#define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6      0xf53c
+#define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6     0xf540
+#define S5P_FIMV_D_DECODED_STATUS_V6           0xf544
+#define S5P_FIMV_DEC_CRC_GEN_MASK_V6           0x1
+#define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6          6
+
+#define S5P_FIMV_D_DECODED_LUMA_ADDR_V6                0xf548
+#define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6      0xf54c
+
+#define S5P_FIMV_D_DECODED_FRAME_TYPE_V6       0xf550
+#define S5P_FIMV_DECODE_FRAME_MASK_V6          7
+
+#define S5P_FIMV_D_DECODED_CROP_INFO1_V6       0xf554
+#define S5P_FIMV_D_DECODED_CROP_INFO2_V6       0xf558
+#define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6  0xf55c
+#define S5P_FIMV_D_DECODED_NAL_SIZE_V6         0xf560
+#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6     0xf564
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6   0xf568
+#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6     0xf56c
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6   0xf570
+
+/* Returned value register for specific setting */
+#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6              0xf574
+#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6              0xf578
+#define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6             0xf57c
+#define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6             0xf580
+#define S5P_FIMV_D_CHROMA_FORMAT_V6                    0xf588
+#define S5P_FIMV_D_MPEG4_INFO_V6                       0xf58c
+#define S5P_FIMV_D_H264_INFO_V6                                0xf590
+
+#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6       0xf594
+#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6       0xf598
+#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6          0xf59c
+#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6          0xf5a0
+#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6            0xf5a4
+#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6            0xf5a8
+#define S5P_FIMV_D_METADATA_ADDR_VUI_V6                        0xf5ac
+#define S5P_FIMV_D_METADATA_SIZE_VUI_V6                        0xf5b0
+
+#define S5P_FIMV_D_MVC_VIEW_ID_V6              0xf5b4
+
+/* SEI related information */
+#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6     0xf5f0
+#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6   0xf5f4
+#define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6      0xf5f8
+#define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6      0xf5fc
+
+/* Encoder Registers */
+#define S5P_FIMV_E_FRAME_WIDTH_V6              0xf770
+#define S5P_FIMV_E_FRAME_HEIGHT_V6             0xf774
+#define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6      0xf778
+#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6     0xf77c
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_V6                0xf780
+#define S5P_FIMV_E_ENC_OPTIONS_V6              0xf784
+#define S5P_FIMV_E_PICTURE_PROFILE_V6          0xf788
+#define S5P_FIMV_E_FIXED_PICTURE_QP_V6         0xf790
+
+#define S5P_FIMV_E_RC_CONFIG_V6                        0xf794
+#define S5P_FIMV_E_RC_QP_BOUND_V6              0xf798
+#define S5P_FIMV_E_RC_RPARAM_V6                        0xf79c
+#define S5P_FIMV_E_MB_RC_CONFIG_V6             0xf7a0
+#define S5P_FIMV_E_PADDING_CTRL_V6             0xf7a4
+#define S5P_FIMV_E_MV_HOR_RANGE_V6             0xf7ac
+#define S5P_FIMV_E_MV_VER_RANGE_V6             0xf7b0
+
+#define S5P_FIMV_E_VBV_BUFFER_SIZE_V6          0xf84c
+#define S5P_FIMV_E_VBV_INIT_DELAY_V6           0xf850
+#define S5P_FIMV_E_NUM_DPB_V6                  0xf890
+#define S5P_FIMV_E_LUMA_DPB_V6                 0xf8c0
+#define S5P_FIMV_E_CHROMA_DPB_V6               0xf904
+#define S5P_FIMV_E_ME_BUFFER_V6                        0xf948
+
+#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6      0xf98c
+#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6      0xf990
+#define S5P_FIMV_E_TMV_BUFFER0_V6              0xf994
+#define S5P_FIMV_E_TMV_BUFFER1_V6              0xf998
+#define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6         0xf9f0
+#define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6       0xf9f4
+#define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6       0xf9f8
+#define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6       0xf9fc
+#define S5P_FIMV_E_ROI_BUFFER_ADDR_V6          0xfA00
+
+#define S5P_FIMV_E_PARAM_CHANGE_V6             0xfa04
+#define S5P_FIMV_E_IR_SIZE_V6                  0xfa08
+#define S5P_FIMV_E_GOP_CONFIG_V6               0xfa0c
+#define S5P_FIMV_E_MSLICE_MODE_V6              0xfa10
+#define S5P_FIMV_E_MSLICE_SIZE_MB_V6           0xfa14
+#define S5P_FIMV_E_MSLICE_SIZE_BITS_V6         0xfa18
+#define S5P_FIMV_E_FRAME_INSERTION_V6          0xfa1c
+
+#define S5P_FIMV_E_RC_FRAME_RATE_V6            0xfa20
+#define S5P_FIMV_E_RC_BIT_RATE_V6              0xfa24
+#define S5P_FIMV_E_RC_QP_OFFSET_V6             0xfa28
+#define S5P_FIMV_E_RC_ROI_CTRL_V6              0xfa2c
+#define S5P_FIMV_E_PICTURE_TAG_V6              0xfa30
+#define S5P_FIMV_E_BIT_COUNT_ENABLE_V6         0xfa34
+#define S5P_FIMV_E_MAX_BIT_COUNT_V6            0xfa38
+#define S5P_FIMV_E_MIN_BIT_COUNT_V6            0xfa3c
+
+#define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6             0xfa40
+#define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6             0xfa44
+#define S5P_FIMV_E_STREAM_SIZE_V6                      0xfa80
+#define S5P_FIMV_E_SLICE_TYPE_V6                       0xfa84
+#define S5P_FIMV_E_PICTURE_COUNT_V6                    0xfa88
+#define S5P_FIMV_E_RET_PICTURE_TAG_V6                  0xfa8c
+#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6      0xfa90
+
+#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6         0xfa94
+#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6       0xfa98
+#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6              0xfa9c
+#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6            0xfaa0
+#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6          0xfaa4
+#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6          0xfaa8
+
+#define S5P_FIMV_E_MPEG4_OPTIONS_V6            0xfb10
+#define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6         0xfb14
+#define S5P_FIMV_E_ASPECT_RATIO_V6             0xfb50
+#define S5P_FIMV_E_EXTENDED_SAR_V6             0xfb54
+
+#define S5P_FIMV_E_H264_OPTIONS_V6             0xfb58
+#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6     0xfb5c
+#define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6      0xfb60
+#define S5P_FIMV_E_H264_I_PERIOD_V6            0xfb64
+
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6              0xfb68
+#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6            0xfb6c
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6            0xfb70
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6    0xfb74
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6             0xfb78
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6             0xfb7c
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6             0xfb80
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6             0xfb84
+
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6   0xfb88
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6   0xfb8c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6   0xfb90
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6   0xfb94
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6   0xfb98
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6   0xfb9c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6   0xfba0
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6   0xfba4
+
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6    0xfba8
+#define S5P_FIMV_E_H264_NUM_T_LAYER_V6         0xfbac
+
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6      0xfbb0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6      0xfbb4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6      0xfbb8
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6      0xfbbc
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6      0xfbc0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6      0xfbc4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6      0xfbc8
+
+#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6              0xfc4c
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6       0
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6         1
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6           2
+
+#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6               0xfd40
+#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6          0xfd44
+#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6            0xfd48
+#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6              0xfd4c
+#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6               0xfd50
+#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6     0xfd80
+
+/* Codec numbers  */
+#define S5P_FIMV_CODEC_NONE_V6         -1
+
+
+#define S5P_FIMV_CODEC_H264_DEC_V6     0
+#define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1
+
+#define S5P_FIMV_CODEC_MPEG4_DEC_V6    3
+#define S5P_FIMV_CODEC_FIMV1_DEC_V6    4
+#define S5P_FIMV_CODEC_FIMV2_DEC_V6    5
+#define S5P_FIMV_CODEC_FIMV3_DEC_V6    6
+#define S5P_FIMV_CODEC_FIMV4_DEC_V6    7
+#define S5P_FIMV_CODEC_H263_DEC_V6     8
+#define S5P_FIMV_CODEC_VC1RCV_DEC_V6   9
+#define S5P_FIMV_CODEC_VC1_DEC_V6      10
+/* FIXME: Add 11~12 */
+#define S5P_FIMV_CODEC_MPEG2_DEC_V6    13
+#define S5P_FIMV_CODEC_VP8_DEC_V6      14
+/* FIXME: Add 15~16 */
+#define S5P_FIMV_CODEC_H264_ENC_V6     20
+#define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21
+
+#define S5P_FIMV_CODEC_MPEG4_ENC_V6    23
+#define S5P_FIMV_CODEC_H263_ENC_V6     24
+
+#define S5P_FIMV_NV12M_HALIGN_V6               16
+#define S5P_FIMV_NV12MT_HALIGN_V6              16
+#define S5P_FIMV_NV12MT_VALIGN_V6              16
+
+#define S5P_FIMV_TMV_BUFFER_ALIGN_V6           16
+#define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6      256
+#define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6    256
+#define S5P_FIMV_ME_BUFFER_ALIGN_V6            256
+#define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6       256
+
+#define S5P_FIMV_LUMA_MB_TO_PIXEL_V6           256
+#define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6         128
+#define S5P_FIMV_NUM_TMV_BUFFERS_V6            2
+
+#define S5P_FIMV_MAX_FRAME_SIZE_V6             (2 * SZ_1M)
+#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6       16
+#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6       16
+
+/* Buffer size requirements defined by hardware */
+#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h)      (((w) + 1) * ((h) + 1) * 8)
+#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
+       ((DIV_ROUND_UP(imw, 64) *  DIV_ROUND_UP(imh, 64) * 256) + \
+        (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h)    (((w) * 192) + 64)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
+                       ((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \
+                        (2048/16 * 256 + 8320))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
+                                               (2096 * ((w) + (h) + 1))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h)    ((w) * 400)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
+                       ((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
+                       (((w) * 64) + (((w) + 1) * 16) + (4096 * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \
+                       (((w) * 16) + (((w) + 1) * 16))
+
+/* MFC Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V6            (28 * SZ_1K)    /*  28KB */
+#define MFC_H264_DEC_CTX_BUF_SIZE_V6   (2 * SZ_1M)     /*  2MB */
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V6  (20 * SZ_1K)    /*  20KB */
+#define MFC_H264_ENC_CTX_BUF_SIZE_V6   (100 * SZ_1K)   /* 100KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V6  (12 * SZ_1K)    /*  12KB */
+
+/* MFCv6 variant defines */
+#define MAX_FW_SIZE_V6                 (SZ_1M)         /* 1MB */
+#define MAX_CPB_SIZE_V6                        (3 * SZ_1M)     /* 3MB */
+#define MFC_VERSION_V6                 0x61
+#define MFC_NUM_PORTS_V6               1
+
+#endif /* _REGS_FIMV_V6_H */
index a19bece41ba9d0c4a53845943c8219e27659382b..9319e93599ae5731241b58535583bc1a04b77e73 100644 (file)
@@ -12,6 +12,9 @@
 #ifndef _REGS_FIMV_H
 #define _REGS_FIMV_H
 
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
 #define S5P_FIMV_REG_SIZE      (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
 #define S5P_FIMV_REG_COUNT     ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
 
 #define S5P_FIMV_ENC_PROFILE_H264_MAIN                 0
 #define S5P_FIMV_ENC_PROFILE_H264_HIGH                 1
 #define S5P_FIMV_ENC_PROFILE_H264_BASELINE             2
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
 #define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE              0
 #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE     1
 #define S5P_FIMV_ENC_PIC_STRUCT                0x083c /* picture field/frame flag */
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK            (3<<4)
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC             (1<<4)
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC             (2<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT           4
 
 /* Decode frame address */
 #define S5P_FIMV_DECODE_Y_ADR                  0x2024
 #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
 #define S5P_FIMV_R2H_CMD_ERR_RET               32
 
+/* Dummy definition for MFCv6 compatibilty */
+#define S5P_FIMV_CODEC_H264_MVC_DEC            -1
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
+#define S5P_FIMV_MFC_RESET                     -1
+#define S5P_FIMV_RISC_ON                       -1
+#define S5P_FIMV_RISC_BASE_ADDRESS             -1
+#define S5P_FIMV_CODEC_VP8_DEC                 -1
+#define S5P_FIMV_REG_CLEAR_BEGIN               0
+#define S5P_FIMV_REG_CLEAR_COUNT               0
+
 /* Error handling defines */
 #define S5P_FIMV_ERR_WARNINGS_START            145
 #define S5P_FIMV_ERR_DEC_MASK                  0xFFFF
 #define S5P_FIMV_SHARED_EXTENDED_SAR           0x0078
 #define S5P_FIMV_SHARED_H264_I_PERIOD          0x009C
 #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG      0x00A0
+#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT  2
+
+/* Offset used by the hardware to store addresses */
+#define MFC_OFFSET_SHIFT       11
+
+#define FIRMWARE_ALIGN         (128 * SZ_1K)   /* 128KB */
+#define MFC_H264_CTX_BUF_SIZE  (600 * SZ_1K)   /* 600KB per H264 instance */
+#define MFC_CTX_BUF_SIZE       (10 * SZ_1K)    /* 10KB per instance */
+#define DESC_BUF_SIZE          (128 * SZ_1K)   /* 128KB for DESC buffer */
+#define SHARED_BUF_SIZE                (8 * SZ_1K)     /* 8KB for shared buffer */
+
+#define DEF_CPB_SIZE           (256 * SZ_1K)   /* 256KB */
+#define MAX_CPB_SIZE           (4 * SZ_1M)     /* 4MB */
+#define MAX_FW_SIZE            (384 * SZ_1K)
+
+#define MFC_VERSION            0x51
+#define MFC_NUM_PORTS          2
+
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL    0x16C
+#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID  0x170
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO     0x174
+#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS     0x178
+
+/* Values for resolution change in display status */
+#define S5P_FIMV_RES_INCREASE  1
+#define S5P_FIMV_RES_DECREASE  2
 
 #endif /* _REGS_FIMV_H */
index 5587ef15ca4fa3d34a3db0e7fe70039ccbc62fc7..130f4ac8649ec644faf589e734145761f5d7cc91 100644 (file)
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
+#include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_dec.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
+#include "s5p_mfc_cmd.h"
 #include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
 
 #define S5P_MFC_NAME           "s5p-mfc"
 #define S5P_MFC_DEC_NAME       "s5p-mfc-dec"
@@ -149,10 +149,12 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work)
                if (!ctx)
                        continue;
                ctx->state = MFCINST_ERROR;
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                clear_work_bit(ctx);
-               wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
+               wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0);
        }
        clear_bit(0, &dev->hw_lock);
        spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -199,6 +201,7 @@ static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
 static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_buf *dst_buf;
+       struct s5p_mfc_dev *dev = ctx->dev;
 
        ctx->state = MFCINST_FINISHED;
        ctx->sequence++;
@@ -213,8 +216,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
                ctx->dst_queue_cnt--;
                dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
 
-               if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
-                       s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+               if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
+                       s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
                        dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
                else
                        dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
@@ -228,8 +231,11 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
        struct s5p_mfc_buf  *dst_buf, *src_buf;
-       size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
-       unsigned int frame_type = s5p_mfc_get_frame_type();
+       size_t dec_y_addr;
+       unsigned int frame_type;
+
+       dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
+       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
 
        /* Copy timestamp / timecode from decoded src to dst and set
           appropraite flags */
@@ -265,10 +271,13 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
        struct s5p_mfc_buf  *dst_buf;
-       size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
-       unsigned int frame_type = s5p_mfc_get_frame_type();
+       size_t dspl_y_addr;
+       unsigned int frame_type;
        unsigned int index;
 
+       dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
+       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
+
        /* If frame is same as previous then skip and do not dequeue */
        if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
                if (!ctx->after_packed_pb)
@@ -285,8 +294,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
                        list_del(&dst_buf->list);
                        ctx->dst_queue_cnt--;
                        dst_buf->b->v4l2_buf.sequence = ctx->sequence;
-                       if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
-                               s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+                       if (s5p_mfc_hw_call(dev->mfc_ops,
+                                       get_pic_type_top, ctx) ==
+                               s5p_mfc_hw_call(dev->mfc_ops,
+                                       get_pic_type_bot, ctx))
                                dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
                        else
                                dst_buf->b->v4l2_buf.field =
@@ -317,21 +328,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
 
        unsigned int index;
 
-       dst_frame_status = s5p_mfc_get_dspl_status()
+       dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
                                & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
-       res_change = s5p_mfc_get_dspl_status()
-                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
+       res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
+                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
+                               >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
        mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
        if (ctx->state == MFCINST_RES_CHANGE_INIT)
                ctx->state = MFCINST_RES_CHANGE_FLUSH;
-       if (res_change) {
+       if (res_change == S5P_FIMV_RES_INCREASE ||
+               res_change == S5P_FIMV_RES_DECREASE) {
                ctx->state = MFCINST_RES_CHANGE_INIT;
-               s5p_mfc_clear_int_flags(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
                wake_up_ctx(ctx, reason, err);
                if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                        BUG();
                s5p_mfc_clock_off();
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                return;
        }
        if (ctx->dpb_flush_flag)
@@ -365,9 +378,12 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
                && !list_empty(&ctx->src_queue)) {
                src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
                                                                list);
-               ctx->consumed_stream += s5p_mfc_get_consumed_stream();
-               if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
-                       s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
+               ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
+                                               get_consumed_stream, dev);
+               if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
+                       s5p_mfc_hw_call(dev->mfc_ops,
+                               get_dec_frame_type, dev) ==
+                                       S5P_FIMV_DECODE_FRAME_P_FRAME
                                        && ctx->consumed_stream + STUFF_BYTE <
                                        src_buf->b->v4l2_planes[0].bytesused) {
                        /* Run MFC again on the same buffer */
@@ -379,7 +395,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
                        ctx->consumed_stream = 0;
                        list_del(&src_buf->list);
                        ctx->src_queue_cnt--;
-                       if (s5p_mfc_err_dec(err) > 0)
+                       if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
                                vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR);
                        else
                                vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE);
@@ -390,12 +406,12 @@ leave_handle_frame:
        if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
                                    || ctx->dst_queue_cnt < ctx->dpb_count)
                clear_work_bit(ctx);
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        wake_up_ctx(ctx, reason, err);
        if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                BUG();
        s5p_mfc_clock_off();
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 /* Error handling for interrupt */
@@ -412,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
 
        dev = ctx->dev;
        mfc_err("Interrupt Error: %08x\n", err);
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        wake_up_dev(dev, reason, err);
 
        /* Error recovery is dependent on the state of context */
@@ -441,9 +457,11 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
                ctx->state = MFCINST_ERROR;
                /* Mark all dst buffers as having an error */
                spin_lock_irqsave(&dev->irqlock, flags);
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
                /* Mark all src buffers as having an error */
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                spin_unlock_irqrestore(&dev->irqlock, flags);
                if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                        BUG();
@@ -461,7 +479,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
                                 unsigned int reason, unsigned int err)
 {
        struct s5p_mfc_dev *dev;
-       unsigned int guard_width, guard_height;
 
        if (ctx == NULL)
                return;
@@ -470,55 +487,44 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
                if (ctx->c_ops->post_seq_start(ctx))
                        mfc_err("post_seq_start() failed\n");
        } else {
-               ctx->img_width = s5p_mfc_get_img_width();
-               ctx->img_height = s5p_mfc_get_img_height();
-
-               ctx->buf_width = ALIGN(ctx->img_width,
-                                               S5P_FIMV_NV12MT_HALIGN);
-               ctx->buf_height = ALIGN(ctx->img_height,
-                                               S5P_FIMV_NV12MT_VALIGN);
-               mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
-                       "buffer dimensions: %dx%d\n", ctx->img_width,
-                               ctx->img_height, ctx->buf_width,
-                                               ctx->buf_height);
-               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
-                       ctx->luma_size = ALIGN(ctx->buf_width *
-                               ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
-                       ctx->chroma_size = ALIGN(ctx->buf_width *
-                                        ALIGN((ctx->img_height >> 1),
-                                              S5P_FIMV_NV12MT_VALIGN),
-                                              S5P_FIMV_DEC_BUF_ALIGN);
-                       ctx->mv_size = ALIGN(ctx->buf_width *
-                                       ALIGN((ctx->buf_height >> 2),
-                                       S5P_FIMV_NV12MT_VALIGN),
-                                       S5P_FIMV_DEC_BUF_ALIGN);
-               } else {
-                       guard_width = ALIGN(ctx->img_width + 24,
-                                       S5P_FIMV_NV12MT_HALIGN);
-                       guard_height = ALIGN(ctx->img_height + 16,
-                                               S5P_FIMV_NV12MT_VALIGN);
-                       ctx->luma_size = ALIGN(guard_width *
-                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
-                       guard_width = ALIGN(ctx->img_width + 16,
-                                               S5P_FIMV_NV12MT_HALIGN);
-                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                               S5P_FIMV_NV12MT_VALIGN);
-                       ctx->chroma_size = ALIGN(guard_width *
-                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
-                       ctx->mv_size = 0;
-               }
-               ctx->dpb_count = s5p_mfc_get_dpb_count();
+               ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width,
+                               dev);
+               ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
+                               dev);
+
+               s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
+
+               ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
+                               dev);
+               ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
+                               dev);
                if (ctx->img_width == 0 || ctx->img_height == 0)
                        ctx->state = MFCINST_ERROR;
                else
                        ctx->state = MFCINST_HEAD_PARSED;
+
+               if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) &&
+                               !list_empty(&ctx->src_queue)) {
+                       struct s5p_mfc_buf *src_buf;
+                       src_buf = list_entry(ctx->src_queue.next,
+                                       struct s5p_mfc_buf, list);
+                       if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
+                                               dev) <
+                                       src_buf->b->v4l2_planes[0].bytesused)
+                               ctx->head_processed = 0;
+                       else
+                               ctx->head_processed = 1;
+               } else {
+                       ctx->head_processed = 1;
+               }
        }
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        clear_work_bit(ctx);
        if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                BUG();
        s5p_mfc_clock_off();
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        wake_up_ctx(ctx, reason, err);
 }
 
@@ -533,14 +539,14 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
        if (ctx == NULL)
                return;
        dev = ctx->dev;
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        ctx->int_type = reason;
        ctx->int_err = err;
        ctx->int_cond = 1;
        clear_work_bit(ctx);
        if (err == 0) {
                ctx->state = MFCINST_RUNNING;
-               if (!ctx->dpb_flush_flag) {
+               if (!ctx->dpb_flush_flag && ctx->head_processed) {
                        spin_lock_irqsave(&dev->irqlock, flags);
                        if (!list_empty(&ctx->src_queue)) {
                                src_buf = list_entry(ctx->src_queue.next,
@@ -560,7 +566,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
                s5p_mfc_clock_off();
 
                wake_up(&ctx->queue);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        } else {
                if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                        BUG();
@@ -602,7 +608,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
 
        s5p_mfc_clock_off();
        wake_up(&ctx->queue);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 /* Interrupt processing */
@@ -618,81 +624,83 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
        atomic_set(&dev->watchdog_cnt, 0);
        ctx = dev->ctx[dev->curr_ctx];
        /* Get the reason of interrupt and the error code */
-       reason = s5p_mfc_get_int_reason();
-       err = s5p_mfc_get_int_err();
+       reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
+       err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
        mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
        switch (reason) {
-       case S5P_FIMV_R2H_CMD_ERR_RET:
+       case S5P_MFC_R2H_CMD_ERR_RET:
                /* An error has occured */
                if (ctx->state == MFCINST_RUNNING &&
-                       s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START)
+                       s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
+                               dev->warn_start)
                        s5p_mfc_handle_frame(ctx, reason, err);
                else
                        s5p_mfc_handle_error(ctx, reason, err);
                clear_bit(0, &dev->enter_suspend);
                break;
 
-       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
-       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+       case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
+       case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
+       case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
                if (ctx->c_ops->post_frame_start) {
                        if (ctx->c_ops->post_frame_start(ctx))
                                mfc_err("post_frame_start() failed\n");
-                       s5p_mfc_clear_int_flags(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
                        wake_up_ctx(ctx, reason, err);
                        if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                                BUG();
                        s5p_mfc_clock_off();
-                       s5p_mfc_try_run(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                } else {
                        s5p_mfc_handle_frame(ctx, reason, err);
                }
                break;
 
-       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+       case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
                s5p_mfc_handle_seq_done(ctx, reason, err);
                break;
 
-       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
-               ctx->inst_no = s5p_mfc_get_inst_no();
+       case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
+               ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
                ctx->state = MFCINST_GOT_INST;
                clear_work_bit(ctx);
                wake_up(&ctx->queue);
                goto irq_cleanup_hw;
 
-       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+       case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
                clear_work_bit(ctx);
                ctx->state = MFCINST_FREE;
                wake_up(&ctx->queue);
                goto irq_cleanup_hw;
 
-       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
-       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
-       case S5P_FIMV_R2H_CMD_SLEEP_RET:
-       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+       case S5P_MFC_R2H_CMD_SYS_INIT_RET:
+       case S5P_MFC_R2H_CMD_FW_STATUS_RET:
+       case S5P_MFC_R2H_CMD_SLEEP_RET:
+       case S5P_MFC_R2H_CMD_WAKEUP_RET:
                if (ctx)
                        clear_work_bit(ctx);
-               s5p_mfc_clear_int_flags(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
                wake_up_dev(dev, reason, err);
                clear_bit(0, &dev->hw_lock);
                clear_bit(0, &dev->enter_suspend);
                break;
 
-       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+       case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
                s5p_mfc_handle_init_buffers(ctx, reason, err);
                break;
 
-       case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
+       case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
                s5p_mfc_handle_stream_complete(ctx, reason, err);
                break;
 
        default:
                mfc_debug(2, "Unknown int reason\n");
-               s5p_mfc_clear_int_flags(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        }
        mfc_debug_leave();
        return IRQ_HANDLED;
 irq_cleanup_hw:
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        ctx->int_type = reason;
        ctx->int_err = err;
        ctx->int_cond = 1;
@@ -701,7 +709,7 @@ irq_cleanup_hw:
 
        s5p_mfc_clock_off();
 
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        mfc_debug(2, "Exit via irq_cleanup_hw\n");
        return IRQ_HANDLED;
 }
@@ -749,6 +757,7 @@ static int s5p_mfc_open(struct file *file)
        if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
                ctx->type = MFCINST_DECODER;
                ctx->c_ops = get_dec_codec_ops();
+               s5p_mfc_dec_init(ctx);
                /* Setup ctrl handler */
                ret = s5p_mfc_dec_ctrls_setup(ctx);
                if (ret) {
@@ -761,6 +770,7 @@ static int s5p_mfc_open(struct file *file)
                /* only for encoder */
                INIT_LIST_HEAD(&ctx->ref_queue);
                ctx->ref_queue_cnt = 0;
+               s5p_mfc_enc_init(ctx);
                /* Setup ctrl handler */
                ret = s5p_mfc_enc_ctrls_setup(ctx);
                if (ret) {
@@ -886,19 +896,20 @@ static int s5p_mfc_release(struct file *file)
                ctx->state = MFCINST_RETURN_INST;
                set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                /* Wait until instance is returned or timeout occured */
                if (s5p_mfc_wait_for_done_ctx
-                   (ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
+                   (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
                        s5p_mfc_clock_off();
                        mfc_err("Err returning instance\n");
                }
                mfc_debug(2, "After free instance\n");
                /* Free resources */
-               s5p_mfc_release_codec_buffers(ctx);
-               s5p_mfc_release_instance_buffer(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
                if (ctx->type == MFCINST_DECODER)
-                       s5p_mfc_release_dec_desc_buffer(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer,
+                                       ctx);
 
                ctx->inst_no = MFC_NO_INSTANCE_SET;
        }
@@ -910,6 +921,7 @@ static int s5p_mfc_release(struct file *file)
                mfc_debug(2, "Last instance - release firmware\n");
                /* reset <-> F/W release */
                s5p_mfc_reset(dev);
+               s5p_mfc_deinit_hw(dev);
                s5p_mfc_release_firmware(dev);
                del_timer_sync(&dev->watchdog_timer);
                if (s5p_mfc_power_off() < 0)
@@ -1041,6 +1053,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       dev->variant = (struct s5p_mfc_variant *)
+               platform_get_device_id(pdev)->driver_data;
+
        ret = s5p_mfc_init_pm(dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to get mfc clock source\n");
@@ -1076,6 +1091,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto err_res;
        }
+
        dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
                                           match_child);
        if (!dev->mem_dev_r) {
@@ -1139,6 +1155,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        vfd->release    = video_device_release,
        vfd->lock       = &dev->mfc_mutex;
        vfd->v4l2_dev   = &dev->v4l2_dev;
+       vfd->vfl_dir    = VFL_DIR_M2M;
        snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
        dev->vfd_enc    = vfd;
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
@@ -1160,6 +1177,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        dev->watchdog_timer.data = (unsigned long)dev;
        dev->watchdog_timer.function = s5p_mfc_watchdog;
 
+       /* Initialize HW ops and commands based on MFC version */
+       s5p_mfc_init_hw_ops(dev);
+       s5p_mfc_init_hw_cmds(dev);
+
        pr_debug("%s--\n", __func__);
        return 0;
 
@@ -1280,9 +1301,78 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
                           NULL)
 };
 
+struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
+       .h264_ctx       = MFC_H264_CTX_BUF_SIZE,
+       .non_h264_ctx   = MFC_CTX_BUF_SIZE,
+       .dsc            = DESC_BUF_SIZE,
+       .shm            = SHARED_BUF_SIZE,
+};
+
+struct s5p_mfc_buf_size buf_size_v5 = {
+       .fw     = MAX_FW_SIZE,
+       .cpb    = MAX_CPB_SIZE,
+       .priv   = &mfc_buf_size_v5,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v5 = {
+       .base = MFC_BASE_ALIGN_ORDER,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v5 = {
+       .version        = MFC_VERSION,
+       .port_num       = MFC_NUM_PORTS,
+       .buf_size       = &buf_size_v5,
+       .buf_align      = &mfc_buf_align_v5,
+       .mclk_name      = "sclk_mfc",
+       .fw_name        = "s5p-mfc.fw",
+};
+
+struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
+       .dev_ctx        = MFC_CTX_BUF_SIZE_V6,
+       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V6,
+       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V6,
+       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V6,
+       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V6,
+};
+
+struct s5p_mfc_buf_size buf_size_v6 = {
+       .fw     = MAX_FW_SIZE_V6,
+       .cpb    = MAX_CPB_SIZE_V6,
+       .priv   = &mfc_buf_size_v6,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v6 = {
+       .base = 0,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v6 = {
+       .version        = MFC_VERSION_V6,
+       .port_num       = MFC_NUM_PORTS_V6,
+       .buf_size       = &buf_size_v6,
+       .buf_align      = &mfc_buf_align_v6,
+       .mclk_name      = "aclk_333",
+       .fw_name        = "s5p-mfc-v6.fw",
+};
+
+static struct platform_device_id mfc_driver_ids[] = {
+       {
+               .name = "s5p-mfc",
+               .driver_data = (unsigned long)&mfc_drvdata_v5,
+       }, {
+               .name = "s5p-mfc-v5",
+               .driver_data = (unsigned long)&mfc_drvdata_v5,
+       }, {
+               .name = "s5p-mfc-v6",
+               .driver_data = (unsigned long)&mfc_drvdata_v6,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
+
 static struct platform_driver s5p_mfc_driver = {
-       .probe  = s5p_mfc_probe,
-       .remove = __devexit_p(s5p_mfc_remove),
+       .probe          = s5p_mfc_probe,
+       .remove         = __devexit_p(s5p_mfc_remove),
+       .id_table       = mfc_driver_ids,
        .driver = {
                .name   = S5P_MFC_NAME,
                .owner  = THIS_MODULE,
index 91a415573bd2a1a19233ef05429c7d632b7f2942..f0a41c95df84722b89b485e371668e5ba9a40743 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
  *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
  * (at your option) any later version.
  */
 
-#include "regs-mfc.h"
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
+#include "s5p_mfc_cmd_v5.h"
+#include "s5p_mfc_cmd_v6.h"
 
-/* This function is used to send a command to the MFC */
-static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
-                                               struct s5p_mfc_cmd_args *args)
-{
-       int cur_cmd;
-       unsigned long timeout;
-
-       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-       /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
-       do {
-               if (time_after(jiffies, timeout)) {
-                       mfc_err("Timeout while waiting for hardware\n");
-                       return -EIO;
-               }
-               cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
-       } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
-       mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
-       mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
-       mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
-       mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
-       /* Issue the command */
-       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
-       return 0;
-}
-
-/* Initialize the MFC */
-int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = dev->fw_size;
-       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
-}
-
-/* Suspend the MFC hardware */
-int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
-}
+static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
 
-/* Wake up the MFC hardware */
-int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
 {
-       struct s5p_mfc_cmd_args h2r_args;
+       if (IS_MFCV6(dev))
+               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
+       else
+               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
 
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
+       dev->mfc_cmds = s5p_mfc_cmds;
 }
-
-
-int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int ret;
-
-       /* Preparing decoding - getting instance number */
-       mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
-       dev->curr_ctx = ctx->num;
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = ctx->codec_mode;
-       h2r_args.arg[1] = 0; /* no crc & no pixelcache */
-       h2r_args.arg[2] = ctx->ctx_ofs;
-       h2r_args.arg[3] = ctx->ctx_size;
-       ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
-                                                               &h2r_args);
-       if (ret) {
-               mfc_err("Failed to create a new instance\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int ret;
-
-       if (ctx->state == MFCINST_FREE) {
-               mfc_err("Instance already returned\n");
-               ctx->state = MFCINST_ERROR;
-               return -EINVAL;
-       }
-       /* Closing decoding instance  */
-       mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
-       dev->curr_ctx = ctx->num;
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = ctx->inst_no;
-       ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
-                                                               &h2r_args);
-       if (ret) {
-               mfc_err("Failed to return an instance\n");
-               ctx->state = MFCINST_ERROR;
-               return -EINVAL;
-       }
-       return 0;
-}
-
index 8b090d3723e7d5f8fd2f84a1373c91e4b59379ea..282e6c780702730f1aabb057b779872334dd7efa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
  *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,10 +21,15 @@ struct s5p_mfc_cmd_args {
        unsigned int    arg[MAX_H2R_ARG];
 };
 
-int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx);
+struct s5p_mfc_hw_cmds {
+       int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args);
+       int (*sys_init_cmd)(struct s5p_mfc_dev *dev);
+       int (*sleep_cmd)(struct s5p_mfc_dev *dev);
+       int (*wakeup_cmd)(struct s5p_mfc_dev *dev);
+       int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx);
+       int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx);
+};
 
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev);
 #endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
new file mode 100644 (file)
index 0000000..1387780
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "regs-mfc.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+
+/* This function is used to send a command to the MFC */
+int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args)
+{
+       int cur_cmd;
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err("Timeout while waiting for hardware\n");
+                       return -EIO;
+               }
+               cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
+       } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
+       mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
+       mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
+       mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
+       mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
+       /* Issue the command */
+       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
+       return 0;
+}
+
+/* Initialize the MFC */
+int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = dev->fw_size;
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
+                       &h2r_args);
+}
+
+/* Suspend the MFC hardware */
+int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
+}
+
+/* Wake up the MFC hardware */
+int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
+                       &h2r_args);
+}
+
+
+int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       /* Preparing decoding - getting instance number */
+       mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
+               break;
+       default:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
+       };
+       h2r_args.arg[1] = 0; /* no crc & no pixelcache */
+       h2r_args.arg[2] = ctx->ctx.ofs;
+       h2r_args.arg[3] = ctx->ctx.size;
+       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to create a new instance\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       if (ctx->state == MFCINST_FREE) {
+               mfc_err("Instance already returned\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       /* Closing decoding instance  */
+       mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = ctx->inst_no;
+       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to return an instance\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* Initialize cmd function pointers for MFC v5 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
+       .cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
+       .sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
+       .sleep_cmd = s5p_mfc_sleep_cmd_v5,
+       .wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
+       .open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
+       .close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
+{
+       return &s5p_mfc_cmds_v5;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
new file mode 100644 (file)
index 0000000..6928a55
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef S5P_MFC_CMD_V5_H_
+#define S5P_MFC_CMD_V5_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void);
+
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
new file mode 100644 (file)
index 0000000..754bfbc
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5p_mfc_common.h"
+
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+
+int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args)
+{
+       mfc_debug(2, "Issue the command: %d\n", cmd);
+
+       /* Reset RISC2HOST command */
+       mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6);
+
+       /* Issue the command */
+       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6);
+       mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6);
+
+       return 0;
+}
+
+int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+       s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev);
+       mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+       mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6,
+                                       &h2r_args);
+}
+
+int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6,
+                       &h2r_args);
+}
+
+int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6,
+                                       &h2r_args);
+}
+
+/* Open a new instance and get its number */
+int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int codec_type;
+
+       mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
+       dev->curr_ctx = ctx->num;
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               codec_type = S5P_FIMV_CODEC_H264_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+               codec_type = S5P_FIMV_CODEC_VC1_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               codec_type = S5P_FIMV_CODEC_H263_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VP8_DEC:
+               codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_MVC_ENC:
+               codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
+               break;
+       default:
+               codec_type = S5P_FIMV_CODEC_NONE_V6;
+       };
+       mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
+       mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+       mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+       mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */
+
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6,
+                                       &h2r_args);
+}
+
+/* Close instance */
+int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret = 0;
+
+       dev->curr_ctx = ctx->num;
+       if (ctx->state != MFCINST_FREE) {
+               mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+               ret = s5p_mfc_cmd_host2risc_v6(dev,
+                                       S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6,
+                                       &h2r_args);
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/* Initialize cmd function pointers for MFC v6 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = {
+       .cmd_host2risc = s5p_mfc_cmd_host2risc_v6,
+       .sys_init_cmd = s5p_mfc_sys_init_cmd_v6,
+       .sleep_cmd = s5p_mfc_sleep_cmd_v6,
+       .wakeup_cmd = s5p_mfc_wakeup_cmd_v6,
+       .open_inst_cmd = s5p_mfc_open_inst_cmd_v6,
+       .close_inst_cmd = s5p_mfc_close_inst_cmd_v6,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void)
+{
+       return &s5p_mfc_cmds_v6;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
new file mode 100644 (file)
index 0000000..b7a8e57
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef S5P_MFC_CMD_V6_H_
+#define S5P_MFC_CMD_V6_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void);
+
+#endif /* S5P_MFC_CMD_H_ */
index 519b0d66d8d1263e52e170e387647ba3962b3fbe..f02e0497ca9837aad0269e4851702b72caeab431 100644 (file)
 #ifndef S5P_MFC_COMMON_H_
 #define S5P_MFC_COMMON_H_
 
-#include "regs-mfc.h"
 #include <linux/platform_device.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/videobuf2-core.h>
+#include "regs-mfc.h"
+#include "regs-mfc-v6.h"
 
 /* Definitions related to MFC memory */
 
 *  while mmaping */
 #define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
 
-/* Offset used by the hardware to store addresses */
-#define MFC_OFFSET_SHIFT       11
-
-#define FIRMWARE_ALIGN         0x20000         /* 128KB */
-#define MFC_H264_CTX_BUF_SIZE  0x96000         /* 600KB per H264 instance */
-#define MFC_CTX_BUF_SIZE       0x2800          /* 10KB per instance */
-#define DESC_BUF_SIZE          0x20000         /* 128KB for DESC buffer */
-#define SHARED_BUF_SIZE                0x2000          /* 8KB for shared buffer */
-
-#define DEF_CPB_SIZE           0x40000         /* 512KB */
-
 #define MFC_BANK1_ALLOC_CTX    0
 #define MFC_BANK2_ALLOC_CTX    1
 
@@ -74,7 +64,40 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
 #define MFC_ENC_CAP_PLANE_COUNT        1
 #define MFC_ENC_OUT_PLANE_COUNT        2
 #define STUFF_BYTE             4
-#define MFC_MAX_CTRLS          64
+#define MFC_MAX_CTRLS          70
+
+#define S5P_MFC_CODEC_NONE             -1
+#define S5P_MFC_CODEC_H264_DEC         0
+#define S5P_MFC_CODEC_H264_MVC_DEC     1
+#define S5P_MFC_CODEC_VC1_DEC          2
+#define S5P_MFC_CODEC_MPEG4_DEC                3
+#define S5P_MFC_CODEC_MPEG2_DEC                4
+#define S5P_MFC_CODEC_H263_DEC         5
+#define S5P_MFC_CODEC_VC1RCV_DEC       6
+#define S5P_MFC_CODEC_VP8_DEC          7
+
+#define S5P_MFC_CODEC_H264_ENC         20
+#define S5P_MFC_CODEC_H264_MVC_ENC     21
+#define S5P_MFC_CODEC_MPEG4_ENC                22
+#define S5P_MFC_CODEC_H263_ENC         23
+
+#define S5P_MFC_R2H_CMD_EMPTY                  0
+#define S5P_MFC_R2H_CMD_SYS_INIT_RET           1
+#define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET      2
+#define S5P_MFC_R2H_CMD_SEQ_DONE_RET           3
+#define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET       4
+#define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET     6
+#define S5P_MFC_R2H_CMD_SLEEP_RET              7
+#define S5P_MFC_R2H_CMD_WAKEUP_RET             8
+#define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET       9
+#define S5P_MFC_R2H_CMD_DPB_FLUSH_RET          10
+#define S5P_MFC_R2H_CMD_NAL_ABORT_RET          11
+#define S5P_MFC_R2H_CMD_FW_STATUS_RET          12
+#define S5P_MFC_R2H_CMD_FRAME_DONE_RET         13
+#define S5P_MFC_R2H_CMD_FIELD_DONE_RET         14
+#define S5P_MFC_R2H_CMD_SLICE_DONE_RET         15
+#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET     16
+#define S5P_MFC_R2H_CMD_ERR_RET                        32
 
 #define mfc_read(dev, offset)          readl(dev->regs_base + (offset))
 #define mfc_write(dev, data, offset)   writel((data), dev->regs_base + \
@@ -177,6 +200,58 @@ struct s5p_mfc_pm {
        struct device   *device;
 };
 
+struct s5p_mfc_buf_size_v5 {
+       unsigned int h264_ctx;
+       unsigned int non_h264_ctx;
+       unsigned int dsc;
+       unsigned int shm;
+};
+
+struct s5p_mfc_buf_size_v6 {
+       unsigned int dev_ctx;
+       unsigned int h264_dec_ctx;
+       unsigned int other_dec_ctx;
+       unsigned int h264_enc_ctx;
+       unsigned int other_enc_ctx;
+};
+
+struct s5p_mfc_buf_size {
+       unsigned int fw;
+       unsigned int cpb;
+       void *priv;
+};
+
+struct s5p_mfc_buf_align {
+       unsigned int base;
+};
+
+struct s5p_mfc_variant {
+       unsigned int version;
+       unsigned int port_num;
+       struct s5p_mfc_buf_size *buf_size;
+       struct s5p_mfc_buf_align *buf_align;
+       char    *mclk_name;
+       char    *fw_name;
+};
+
+/**
+ * struct s5p_mfc_priv_buf - represents internal used buffer
+ * @alloc:             allocation-specific context for each buffer
+ *                     (videobuf2 allocator)
+ * @ofs:               offset of each buffer, will be used for MFC
+ * @virt:              kernel virtual address, only valid when the
+ *                     buffer accessed by driver
+ * @dma:               DMA address, only valid when kernel DMA API used
+ * @size:              size of the buffer
+ */
+struct s5p_mfc_priv_buf {
+       void            *alloc;
+       unsigned long   ofs;
+       void            *virt;
+       dma_addr_t      dma;
+       size_t          size;
+};
+
 /**
  * struct s5p_mfc_dev - The struct containing driver internal parameters.
  *
@@ -191,6 +266,7 @@ struct s5p_mfc_pm {
  * @dec_ctrl_handler:  control framework handler for decoding
  * @enc_ctrl_handler:  control framework handler for encoding
  * @pm:                        power management control
+ * @variant:           MFC hardware variant information
  * @num_inst:          couter of active MFC instances
  * @irqlock:           lock for operations on videobuf2 queues
  * @condlock:          lock for changing/checking if a context is ready to be
@@ -212,6 +288,10 @@ struct s5p_mfc_pm {
  * @watchdog_work:     worker for the watchdog
  * @alloc_ctx:         videobuf2 allocator contexts for two memory banks
  * @enter_suspend:     flag set when entering suspend
+ * @ctx_buf:           common context memory (MFCv6)
+ * @warn_start:                hardware error code from which warnings start
+ * @mfc_ops:           ops structure holding HW operation function pointers
+ * @mfc_cmds:          cmd structure holding HW commands function pointers
  *
  */
 struct s5p_mfc_dev {
@@ -226,6 +306,7 @@ struct s5p_mfc_dev {
        struct v4l2_ctrl_handler dec_ctrl_handler;
        struct v4l2_ctrl_handler enc_ctrl_handler;
        struct s5p_mfc_pm       pm;
+       struct s5p_mfc_variant  *variant;
        int num_inst;
        spinlock_t irqlock;     /* lock when operating on videobuf2 queues */
        spinlock_t condlock;    /* lock when changing/checking if a context is
@@ -248,6 +329,11 @@ struct s5p_mfc_dev {
        struct work_struct watchdog_work;
        void *alloc_ctx[2];
        unsigned long enter_suspend;
+
+       struct s5p_mfc_priv_buf ctx_buf;
+       int warn_start;
+       struct s5p_mfc_hw_ops *mfc_ops;
+       struct s5p_mfc_hw_cmds *mfc_cmds;
 };
 
 /**
@@ -262,7 +348,6 @@ struct s5p_mfc_h264_enc_params {
        u8 max_ref_pic;
        u8 num_ref_pic_4p;
        int _8x8_transform;
-       int rc_mb;
        int rc_mb_dark;
        int rc_mb_smooth;
        int rc_mb_static;
@@ -281,6 +366,23 @@ struct s5p_mfc_h264_enc_params {
        enum v4l2_mpeg_video_h264_level level_v4l2;
        int level;
        u16 cpb_size;
+       int interlace;
+       u8 hier_qp;
+       u8 hier_qp_type;
+       u8 hier_qp_layer;
+       u8 hier_qp_layer_qp[7];
+       u8 sei_frame_packing;
+       u8 sei_fp_curr_frame_0;
+       u8 sei_fp_arrangement_type;
+
+       u8 fmo;
+       u8 fmo_map_type;
+       u8 fmo_slice_grp;
+       u8 fmo_chg_dir;
+       u32 fmo_chg_rate;
+       u32 fmo_run_len[4];
+       u8 aso;
+       u32 aso_slice_order[8];
 };
 
 /**
@@ -319,9 +421,11 @@ struct s5p_mfc_enc_params {
        u8 pad_cb;
        u8 pad_cr;
        int rc_frame;
+       int rc_mb;
        u32 rc_bitrate;
        u16 rc_reaction_coeff;
        u16 vbv_size;
+       u32 vbv_delay;
 
        enum v4l2_mpeg_video_header_mode seq_hdr_mode;
        enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
@@ -330,7 +434,6 @@ struct s5p_mfc_enc_params {
        u8 num_b_frame;
        u32 rc_framerate_num;
        u32 rc_framerate_denom;
-       int interlace;
 
        union {
                struct s5p_mfc_h264_enc_params h264;
@@ -388,6 +491,8 @@ struct s5p_mfc_codec_ops {
  *                     decoding buffer
  * @dpb_flush_flag:    flag used to indicate that a DPB buffers are being
  *                     flushed
+ * @head_processed:    flag mentioning whether the header data is processed
+ *                     completely or not
  * @bank1_buf:         handle to memory allocated for temporary buffers from
  *                     memory bank 1
  * @bank1_phys:                address of the temporary buffers from memory bank 1
@@ -412,19 +517,20 @@ struct s5p_mfc_codec_ops {
  * @display_delay_enable:      display delay for H264 enable flag
  * @after_packed_pb:   flag used to track buffer when stream is in
  *                     Packed PB format
+ * @sei_fp_parse:      enable/disable parsing of frame packing SEI information
  * @dpb_count:         count of the DPB buffers required by MFC hw
  * @total_dpb_count:   count of DPB buffers with additional buffers
  *                     requested by the application
- * @ctx_buf:           handle to the memory associated with this context
- * @ctx_phys:          address of the memory associated with this context
- * @ctx_size:          size of the memory associated with this context
- * @desc_buf:          description buffer for decoding handle
- * @desc_phys:         description buffer for decoding address
- * @shm_alloc:         handle for the shared memory buffer
- * @shm:               virtual address for the shared memory buffer
- * @shm_ofs:           address offset for shared memory
+ * @ctx:               context buffer information
+ * @dsc:               descriptor buffer information
+ * @shm:               shared memory buffer information
+ * @mv_count:          number of MV buffers allocated for decoding
  * @enc_params:                encoding parameters for MFC
  * @enc_dst_buf_size:  size of the buffers for encoder output
+ * @luma_dpb_size:     dpb buffer size for luma
+ * @chroma_dpb_size:   dpb buffer size for chroma
+ * @me_buffer_size:    size of the motion estimation buffer
+ * @tmv_buffer_size:   size of temporal predictor motion vector buffer
  * @frame_type:                used to force the type of the next encoded frame
  * @ref_queue:         list of the reference buffers for encoding
  * @ref_queue_cnt:     number of the buffers in the reference list
@@ -473,6 +579,7 @@ struct s5p_mfc_ctx {
        unsigned long consumed_stream;
 
        unsigned int dpb_flush_flag;
+       unsigned int head_processed;
 
        /* Buffers */
        void *bank1_buf;
@@ -502,37 +609,41 @@ struct s5p_mfc_ctx {
        int display_delay;
        int display_delay_enable;
        int after_packed_pb;
+       int sei_fp_parse;
 
        int dpb_count;
        int total_dpb_count;
-
+       int mv_count;
        /* Buffers */
-       void *ctx_buf;
-       size_t ctx_phys;
-       size_t ctx_ofs;
-       size_t ctx_size;
-
-       void *desc_buf;
-       size_t desc_phys;
-
-
-       void *shm_alloc;
-       void *shm;
-       size_t shm_ofs;
+       struct s5p_mfc_priv_buf ctx;
+       struct s5p_mfc_priv_buf dsc;
+       struct s5p_mfc_priv_buf shm;
 
        struct s5p_mfc_enc_params enc_params;
 
        size_t enc_dst_buf_size;
+       size_t luma_dpb_size;
+       size_t chroma_dpb_size;
+       size_t me_buffer_size;
+       size_t tmv_buffer_size;
 
        enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
 
        struct list_head ref_queue;
        unsigned int ref_queue_cnt;
 
+       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+       union {
+               unsigned int mb;
+               unsigned int bits;
+       } slice_size;
+
        struct s5p_mfc_codec_ops *c_ops;
 
        struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
        struct v4l2_ctrl_handler ctrl_handler;
+       unsigned int frame_tag;
+       size_t scratch_buf_size;
 };
 
 /*
@@ -565,6 +676,9 @@ struct mfc_control {
        __u8                    is_volatile;
 };
 
+/* Macro for making hardware specific calls */
+#define s5p_mfc_hw_call(f, op, args...) \
+       ((f && f->op) ? f->op(args) : -ENODEV)
 
 #define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
 #define ctrl_to_ctx(__ctrl) \
@@ -575,4 +689,9 @@ void set_work_bit(struct s5p_mfc_ctx *ctx);
 void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
 void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
 
+#define HAS_PORTNUM(dev)       (dev ? (dev->variant ? \
+                               (dev->variant->port_num ? 1 : 0) : 0) : 0)
+#define IS_TWOPORT(dev)                (dev->variant->port_num == 2 ? 1 : 0)
+#define IS_MFCV6(dev)          (dev->variant->version >= 0x60 ? 1 : 0)
+
 #endif /* S5P_MFC_COMMON_H_ */
index 0deba6bc687c7a357ba37ff40de904afb1bebb94..585b7b0ed8ec6a4cd4422246e22c0170f29ac10d 100644 (file)
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
 #include "s5p_mfc_pm.h"
 
 static void *s5p_mfc_bitproc_buf;
@@ -37,13 +37,19 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
        /* Firmare has to be present as a separate file or compiled
         * into kernel. */
        mfc_debug_enter();
+
        err = request_firmware((const struct firmware **)&fw_blob,
-                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
+                                    dev->variant->fw_name, dev->v4l2_dev.dev);
        if (err != 0) {
                mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
                return -EINVAL;
        }
-       dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
+       dev->fw_size = dev->variant->buf_size->fw;
+       if (fw_blob->size > dev->fw_size) {
+               mfc_err("MFC firmware is too big to be loaded\n");
+               release_firmware(fw_blob);
+               return -ENOMEM;
+       }
        if (s5p_mfc_bitproc_buf) {
                mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
                release_firmware(fw_blob);
@@ -77,32 +83,37 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
                return -EIO;
        }
        dev->bank1 = s5p_mfc_bitproc_phys;
-       b_base = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER);
-       if (IS_ERR(b_base)) {
-               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
-               s5p_mfc_bitproc_phys = 0;
-               s5p_mfc_bitproc_buf = NULL;
-               mfc_err("Allocating bank2 base failed\n");
-       release_firmware(fw_blob);
-               return -ENOMEM;
-       }
-       bank2_base_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
-       vb2_dma_contig_memops.put(b_base);
-       if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
-               mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
-               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
-               s5p_mfc_bitproc_phys = 0;
-               s5p_mfc_bitproc_buf = NULL;
-               release_firmware(fw_blob);
-               return -EIO;
+       if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
+               b_base = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
+                       1 << MFC_BASE_ALIGN_ORDER);
+               if (IS_ERR(b_base)) {
+                       vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+                       s5p_mfc_bitproc_phys = 0;
+                       s5p_mfc_bitproc_buf = NULL;
+                       mfc_err("Allocating bank2 base failed\n");
+                       release_firmware(fw_blob);
+                       return -ENOMEM;
+               }
+               bank2_base_phys = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
+               vb2_dma_contig_memops.put(b_base);
+               if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
+                       mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
+                       vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+                       s5p_mfc_bitproc_phys = 0;
+                       s5p_mfc_bitproc_buf = NULL;
+                       release_firmware(fw_blob);
+                       return -EIO;
+               }
+               /* Valid buffers passed to MFC encoder with LAST_FRAME command
+                * should not have address of bank2 - MFC will treat it as a null frame.
+                * To avoid such situation we set bank2 address below the pool address.
+                */
+               dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
+       } else {
+               dev->bank2 = dev->bank1;
        }
-       /* Valid buffers passed to MFC encoder with LAST_FRAME command
-        * should not have address of bank2 - MFC will treat it as a null frame.
-        * To avoid such situation we set bank2 address below the pool address.
-        */
-       dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
        memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
        wmb();
        release_firmware(fw_blob);
@@ -119,8 +130,9 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
        /* Firmare has to be present as a separate file or compiled
         * into kernel. */
        mfc_debug_enter();
+
        err = request_firmware((const struct firmware **)&fw_blob,
-                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
+                                    dev->variant->fw_name, dev->v4l2_dev.dev);
        if (err != 0) {
                mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
                return -EINVAL;
@@ -161,46 +173,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
 {
        unsigned int mc_status;
        unsigned long timeout;
+       int i;
 
        mfc_debug_enter();
-       /* Stop procedure */
-       /*  reset RISC */
-       mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
-       /*  All reset except for MC */
-       mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
-       mdelay(10);
-
-       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-       /* Check MC status */
-       do {
-               if (time_after(jiffies, timeout)) {
-                       mfc_err("Timeout while resetting MFC\n");
-                       return -EIO;
-               }
 
-               mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+       if (IS_MFCV6(dev)) {
+               /* Reset IP */
+               /*  except RISC, reset */
+               mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6);
+               /*  reset release */
+               mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6);
+
+               /* Zero Initialization of MFC registers */
+               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
+               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
+               mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
+
+               for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
+                       mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
 
-       } while (mc_status & 0x3);
+               /* Reset */
+               mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
+               mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
+               mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
+       } else {
+               /* Stop procedure */
+               /*  reset RISC */
+               mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
+               /*  All reset except for MC */
+               mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
+               mdelay(10);
+
+               timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+               /* Check MC status */
+               do {
+                       if (time_after(jiffies, timeout)) {
+                               mfc_err("Timeout while resetting MFC\n");
+                               return -EIO;
+                       }
+
+                       mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+
+               } while (mc_status & 0x3);
+
+               mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
+               mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
+       }
 
-       mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
-       mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
        mfc_debug_leave();
        return 0;
 }
 
 static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
 {
-       mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
-       mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
-       mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
+       if (IS_MFCV6(dev)) {
+               mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6);
+               mfc_debug(2, "Base Address : %08x\n", dev->bank1);
+       } else {
+               mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
+               mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
+               mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
+                               dev->bank1, dev->bank2);
+       }
 }
 
 static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
 {
-       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
-       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
-       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
-       mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+       if (IS_MFCV6(dev)) {
+               /* Zero initialization should be done before RESET.
+                * Nothing to do here. */
+       } else {
+               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
+               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
+               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+       }
 }
 
 /* Initialize hardware */
@@ -228,9 +275,12 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
        s5p_mfc_clear_cmds(dev);
        /* 3. Release reset signal to the RISC */
        s5p_mfc_clean_dev_int_flags(dev);
-       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+       if (IS_MFCV6(dev))
+               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+       else
+               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
        mfc_debug(2, "Will now wait for completion of firmware transfer\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
                mfc_err("Failed to load firmware\n");
                s5p_mfc_reset(dev);
                s5p_mfc_clock_off();
@@ -238,7 +288,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
        }
        s5p_mfc_clean_dev_int_flags(dev);
        /* 4. Initialize firmware */
-       ret = s5p_mfc_sys_init_cmd(dev);
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
        if (ret) {
                mfc_err("Failed to send command to MFC - timeout\n");
                s5p_mfc_reset(dev);
@@ -246,7 +296,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
                return ret;
        }
        mfc_debug(2, "Ok, now will write a command to init the system\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
                mfc_err("Failed to load firmware\n");
                s5p_mfc_reset(dev);
                s5p_mfc_clock_off();
@@ -254,7 +304,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
        }
        dev->int_cond = 0;
        if (dev->int_err != 0 || dev->int_type !=
-                                       S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
+                                       S5P_MFC_R2H_CMD_SYS_INIT_RET) {
                /* Failure. */
                mfc_err("Failed to init firmware - error: %d int: %d\n",
                                                dev->int_err, dev->int_type);
@@ -262,7 +312,11 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
                s5p_mfc_clock_off();
                return -EIO;
        }
-       ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+       if (IS_MFCV6(dev))
+               ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
+       else
+               ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+
        mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
                (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
        s5p_mfc_clock_off();
@@ -271,6 +325,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
 }
 
 
+/* Deinitialize hardware */
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
+{
+       s5p_mfc_clock_on();
+
+       s5p_mfc_reset(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
+
+       s5p_mfc_clock_off();
+}
+
 int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
 {
        int ret;
@@ -278,19 +343,19 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
        mfc_debug_enter();
        s5p_mfc_clock_on();
        s5p_mfc_clean_dev_int_flags(dev);
-       ret = s5p_mfc_sleep_cmd(dev);
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
        if (ret) {
                mfc_err("Failed to send command to MFC - timeout\n");
                return ret;
        }
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
                mfc_err("Failed to sleep\n");
                return -EIO;
        }
        s5p_mfc_clock_off();
        dev->int_cond = 0;
        if (dev->int_err != 0 || dev->int_type !=
-                                               S5P_FIMV_R2H_CMD_SLEEP_RET) {
+                                               S5P_MFC_R2H_CMD_SLEEP_RET) {
                /* Failure. */
                mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
                                                                dev->int_type);
@@ -320,22 +385,25 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
        s5p_mfc_clear_cmds(dev);
        s5p_mfc_clean_dev_int_flags(dev);
        /* 3. Initialize firmware */
-       ret = s5p_mfc_wakeup_cmd(dev);
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
        if (ret) {
                mfc_err("Failed to send command to MFC - timeout\n");
                return ret;
        }
        /* 4. Release reset signal to the RISC */
-       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+       if (IS_MFCV6(dev))
+               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+       else
+               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
        mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
                mfc_err("Failed to load firmware\n");
                return -EIO;
        }
        s5p_mfc_clock_off();
        dev->int_cond = 0;
        if (dev->int_err != 0 || dev->int_type !=
-                                               S5P_FIMV_R2H_CMD_WAKEUP_RET) {
+                                               S5P_MFC_R2H_CMD_WAKEUP_RET) {
                /* Failure. */
                mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
                                                                dev->int_type);
index e1e0c544b6a2ccb675c6f445ba6ff758dbd54898..90aa9b9886d56f1e3c30e204ad2ee61793d1b8d1 100644 (file)
@@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
 int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
 
 int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
 
 int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
 int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
index 6ee21bb713980ac840b1c87d175f898b380d46db..eb6a70b0f8213285a888ee867e3346d8ca9c5770 100644 (file)
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_dec.h"
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
 #include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
+
+#define DEF_SRC_FMT_DEC        V4L2_PIX_FMT_H264
+#define DEF_DST_FMT_DEC        V4L2_PIX_FMT_NV12MT_16X16
 
 static struct s5p_mfc_fmt formats[] = {
+       {
+               .name           = "4:2:0 2 Planes 16x16 Tiles",
+               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
        {
                .name           = "4:2:0 2 Planes 64x32 Tiles",
                .fourcc         = V4L2_PIX_FMT_NV12MT,
-               .codec_mode     = S5P_FIMV_CODEC_NONE,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
                .type           = MFC_FMT_RAW,
                .num_planes     = 2,
-        },
+       },
        {
-               .name = "4:2:0 2 Planes",
-               .fourcc = V4L2_PIX_FMT_NV12M,
-               .codec_mode = S5P_FIMV_CODEC_NONE,
-               .type = MFC_FMT_RAW,
-               .num_planes = 2,
+               .name           = "4:2:0 2 Planes Y/CbCr",
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
+       {
+               .name           = "4:2:0 2 Planes Y/CrCb",
+               .fourcc         = V4L2_PIX_FMT_NV21M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
        },
        {
-               .name = "H264 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264,
-               .codec_mode = S5P_FIMV_CODEC_H264_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "H264 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H264,
+               .codec_mode     = S5P_MFC_CODEC_H264_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "H263 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H263,
-               .codec_mode = S5P_FIMV_CODEC_H263_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "H264/MVC Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H264_MVC,
+               .codec_mode     = S5P_MFC_CODEC_H264_MVC_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG1 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG1,
-               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "H263 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H263,
+               .codec_mode     = S5P_MFC_CODEC_H263_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG2 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG2,
-               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "MPEG1 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG1,
+               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG4 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG4,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "MPEG2 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG2,
+               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "XviD Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_XVID,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "MPEG4 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG4,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "VC1 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
-               .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "XviD Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_XVID,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "VC1 RCV Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
-               .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "VC1 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_G,
+               .codec_mode     = S5P_MFC_CODEC_VC1_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+       },
+       {
+               .name           = "VC1 RCV Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_L,
+               .codec_mode     = S5P_MFC_CODEC_VC1RCV_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+       },
+       {
+               .name           = "VP8 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_VP8,
+               .codec_mode     = S5P_MFC_CODEC_VP8_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
 };
 
@@ -297,7 +326,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
                /* If the MFC is parsing the header,
                 * so wait until it is finished */
                s5p_mfc_clean_ctx_int_flags(ctx);
-               s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET,
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
                                                                        0);
        }
        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
@@ -342,21 +371,36 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 /* Try format */
 static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
+       struct s5p_mfc_dev *dev = video_drvdata(file);
        struct s5p_mfc_fmt *fmt;
 
-       if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_err("This node supports decoding only\n");
-               return -EINVAL;
-       }
-       fmt = find_format(f, MFC_FMT_DEC);
-       if (!fmt) {
-               mfc_err("Unsupported format\n");
-               return -EINVAL;
-       }
-       if (fmt->type != MFC_FMT_DEC) {
-               mfc_err("\n");
-               return -EINVAL;
+       mfc_debug(2, "Type is %d\n", f->type);
+       if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fmt = find_format(f, MFC_FMT_DEC);
+               if (!fmt) {
+                       mfc_err("Unsupported format for source.\n");
+                       return -EINVAL;
+               }
+               if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("Unsupported format for destination.\n");
+                       return -EINVAL;
+               }
+               if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               } else if (!IS_MFCV6(dev) &&
+                               (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
        }
+
        return 0;
 }
 
@@ -379,8 +423,29 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                ret = -EBUSY;
                goto out;
        }
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("Unsupported format for source.\n");
+                       return -EINVAL;
+               }
+               if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               } else if (IS_MFCV6(dev) &&
+                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
+               ctx->dst_fmt = fmt;
+               mfc_debug_leave();
+               return ret;
+       } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_err("Wrong type error for S_FMT : %d", f->type);
+               return -EINVAL;
+       }
        fmt = find_format(f, MFC_FMT_DEC);
-       if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
+       if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
                mfc_err("Unknown codec\n");
                ret = -EINVAL;
                goto out;
@@ -391,6 +456,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                ret = -EINVAL;
                goto out;
        }
+       if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+               mfc_err("Not supported format.\n");
+               return -EINVAL;
+       }
        ctx->src_fmt = fmt;
        ctx->codec_mode = fmt->codec_mode;
        mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
@@ -476,7 +545,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                        return -ENOMEM;
                }
                ctx->total_dpb_count = reqbufs->count;
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
                if (ret) {
                        mfc_err("Failed to allocate decoding buffers\n");
                        reqbufs->count = 0;
@@ -492,15 +561,16 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                        reqbufs->count = 0;
                        s5p_mfc_clock_on();
                        ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       s5p_mfc_release_codec_buffers(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
+                                       ctx);
                        s5p_mfc_clock_off();
                        return -ENOMEM;
                }
                if (s5p_mfc_ctx_ready(ctx))
                        set_work_bit_irqsave(ctx);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                s5p_mfc_wait_for_done_ctx(ctx,
-                                        S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
+                                       S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
        }
        return ret;
 }
@@ -582,18 +652,22 @@ static int vidioc_streamon(struct file *file, void *priv,
                        ctx->src_bufs_cnt = 0;
                        ctx->capture_state = QUEUE_FREE;
                        ctx->output_state = QUEUE_FREE;
-                       s5p_mfc_alloc_instance_buffer(ctx);
-                       s5p_mfc_alloc_dec_temp_buffers(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer,
+                                       ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers,
+                                       ctx);
                        set_work_bit_irqsave(ctx);
                        s5p_mfc_clean_ctx_int_flags(ctx);
-                       s5p_mfc_try_run(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 
                        if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
+                               S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
                                /* Error or timeout */
                                mfc_err("Error getting instance from hardware\n");
-                               s5p_mfc_release_instance_buffer(ctx);
-                               s5p_mfc_release_dec_desc_buffer(ctx);
+                               s5p_mfc_hw_call(dev->mfc_ops,
+                                               release_instance_buffer, ctx);
+                               s5p_mfc_hw_call(dev->mfc_ops,
+                                               release_dec_desc_buffer, ctx);
                                return -EIO;
                        }
                        mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
@@ -662,7 +736,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
                /* Should wait for the header to be parsed */
                s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0);
+                               S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
                if (ctx->state >= MFCINST_HEAD_PARSED &&
                    ctx->state < MFCINST_ABORT) {
                        ctrl->val = ctx->dpb_count;
@@ -686,6 +760,7 @@ static int vidioc_g_crop(struct file *file, void *priv,
                struct v4l2_crop *cr)
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
        u32 left, right, top, bottom;
 
        if (ctx->state != MFCINST_HEAD_PARSED &&
@@ -695,10 +770,10 @@ static int vidioc_g_crop(struct file *file, void *priv,
                        return -EINVAL;
                }
        if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
-               left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
+               left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);
                right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
                left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
-               top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
+               top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);
                bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
                top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
                cr->c.left = left;
@@ -749,6 +824,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
                        void *allocators[])
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
 
        /* Video output for decoding (source)
         * this can be set after getting an instance */
@@ -784,7 +860,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
            vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
                psize[0] = ctx->luma_size;
                psize[1] = ctx->chroma_size;
-               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+
+               if (IS_MFCV6(dev))
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+               else
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
                allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
        } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
                   ctx->state == MFCINST_INIT) {
@@ -876,7 +958,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
        /* If context is ready then dev = work->data;schedule it to run */
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        return 0;
 }
 
@@ -892,19 +974,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
                dev->curr_ctx == ctx->num && dev->hw_lock) {
                ctx->state = MFCINST_ABORT;
                s5p_mfc_wait_for_done_ctx(ctx,
-                                       S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0);
+                                       S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
                aborted = 1;
        }
        spin_lock_irqsave(&dev->irqlock, flags);
        if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
                INIT_LIST_HEAD(&ctx->dst_queue);
                ctx->dst_queue_cnt = 0;
                ctx->dpb_flush_flag = 1;
                ctx->dec_dst_flag = 0;
        }
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                INIT_LIST_HEAD(&ctx->src_queue);
                ctx->src_queue_cnt = 0;
        }
@@ -944,7 +1028,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
        }
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 static struct vb2_ops s5p_mfc_dec_qops = {
@@ -1028,3 +1112,13 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
                ctx->ctrls[i] = NULL;
 }
 
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_format f;
+       f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC;
+       ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
+       f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC;
+       ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);
+       mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
+                       (unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt);
+}
index fdf1d99a9d15df53decc6bb427ede6dfd0903ece..d06a7cab5eb1bc32f86cb7edfbac1062fd141b14 100644 (file)
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
 struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
 int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
 
 #endif /* S5P_MFC_DEC_H_ */
index 179e4db60b15614a4cac63e04be9bc98667232b4..2af6d522f4acf3b94b142281c22edd2ce7c53c44 100644 (file)
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
 
+#define DEF_SRC_FMT_ENC        V4L2_PIX_FMT_NV12MT
+#define DEF_DST_FMT_ENC        V4L2_PIX_FMT_H264
+
 static struct s5p_mfc_fmt formats[] = {
        {
-               .name = "4:2:0 2 Planes 64x32 Tiles",
-               .fourcc = V4L2_PIX_FMT_NV12MT,
-               .codec_mode = S5P_FIMV_CODEC_NONE,
-               .type = MFC_FMT_RAW,
-               .num_planes = 2,
+               .name           = "4:2:0 2 Planes 16x16 Tiles",
+               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
+       {
+               .name           = "4:2:0 2 Planes 64x32 Tiles",
+               .fourcc         = V4L2_PIX_FMT_NV12MT,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
+       {
+               .name           = "4:2:0 2 Planes Y/CbCr",
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
        },
        {
-               .name = "4:2:0 2 Planes",
-               .fourcc = V4L2_PIX_FMT_NV12M,
-               .codec_mode = S5P_FIMV_CODEC_NONE,
-               .type = MFC_FMT_RAW,
-               .num_planes = 2,
+               .name           = "4:2:0 2 Planes Y/CrCb",
+               .fourcc         = V4L2_PIX_FMT_NV21M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
        },
        {
-               .name = "H264 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264,
-               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
-               .type = MFC_FMT_ENC,
-               .num_planes = 1,
+               .name           = "H264 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H264,
+               .codec_mode     = S5P_MFC_CODEC_H264_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG4 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG4,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
-               .type = MFC_FMT_ENC,
-               .num_planes = 1,
+               .name           = "MPEG4 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG4,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
        },
        {
-               .name = "H263 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H263,
-               .codec_mode = S5P_FIMV_CODEC_H263_ENC,
-               .type = MFC_FMT_ENC,
-               .num_planes = 1,
+               .name           = "H263 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H263,
+               .codec_mode     = S5P_MFC_CODEC_H263_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
        },
 };
 
@@ -574,7 +590,8 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
        if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
                return 1;
        /* context is ready to encode a frame */
-       if (ctx->state == MFCINST_RUNNING &&
+       if ((ctx->state == MFCINST_RUNNING ||
+               ctx->state == MFCINST_HEAD_PARSED) &&
                ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
                return 1;
        /* context is ready to encode remaining frames */
@@ -619,7 +636,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
        dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
        dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
        dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+                       dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        return 0;
 }
@@ -638,14 +656,23 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
                list_del(&dst_mb->list);
                ctx->dst_queue_cnt--;
                vb2_set_plane_payload(dst_mb->b, 0,
-                                               s5p_mfc_get_enc_strm_size());
+                       s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev));
                vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
                spin_unlock_irqrestore(&dev->irqlock, flags);
        }
-       ctx->state = MFCINST_RUNNING;
-       if (s5p_mfc_ctx_ready(ctx))
-               set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       if (IS_MFCV6(dev)) {
+               ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
+       } else {
+               ctx->state = MFCINST_RUNNING;
+               if (s5p_mfc_ctx_ready(ctx))
+                       set_work_bit_irqsave(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       }
+
+       if (IS_MFCV6(dev))
+               ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops,
+                               get_enc_dpb_count, dev);
+
        return 0;
 }
 
@@ -662,14 +689,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
        src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
        src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
        src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
-       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx, src_y_addr,
+                       src_c_addr);
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
        spin_lock_irqsave(&dev->irqlock, flags);
        dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
        dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
        dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+                       dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
        return 0;
@@ -685,15 +714,16 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
        unsigned int strm_size;
        unsigned long flags;
 
-       slice_type = s5p_mfc_get_enc_slice_type();
-       strm_size = s5p_mfc_get_enc_strm_size();
+       slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
+       strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
        mfc_debug(2, "Encoded slice type: %d", slice_type);
        mfc_debug(2, "Encoded stream size: %d", strm_size);
        mfc_debug(2, "Display order: %d",
                  mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
        spin_lock_irqsave(&dev->irqlock, flags);
        if (slice_type >= 0) {
-               s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
+               s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx,
+                               &enc_y_addr, &enc_c_addr);
                list_for_each_entry(mb_entry, &ctx->src_queue, list) {
                        mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
                        mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
@@ -939,15 +969,16 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                pix_fmt_mp->plane_fmt[0].bytesperline = 0;
                ctx->dst_bufs_cnt = 0;
                ctx->capture_state = QUEUE_FREE;
-               s5p_mfc_alloc_instance_buffer(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
                set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                if (s5p_mfc_wait_for_done_ctx(ctx, \
-                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
+                               S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
                                /* Error or timeout */
                        mfc_err("Error getting instance from hardware\n");
-                       s5p_mfc_release_instance_buffer(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer,
+                                       ctx);
                        ret = -EIO;
                        goto out;
                }
@@ -958,6 +989,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                        mfc_err("failed to set output format\n");
                        return -EINVAL;
                }
+
+               if (!IS_MFCV6(dev) &&
+                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               } else if (IS_MFCV6(dev) &&
+                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
+
                if (fmt->num_planes != pix_fmt_mp->num_planes) {
                        mfc_err("failed to set output format\n");
                        ret = -EINVAL;
@@ -970,45 +1012,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
                        pix_fmt_mp->width, pix_fmt_mp->height,
                        ctx->img_width, ctx->img_height);
-               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
-                       ctx->buf_width = ALIGN(ctx->img_width,
-                                                       S5P_FIMV_NV12M_HALIGN);
-                       ctx->luma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
-                               S5P_FIMV_NV12M_LVALIGN);
-                       ctx->chroma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
-                               >> 1), S5P_FIMV_NV12M_CVALIGN);
-
-                       ctx->luma_size = ALIGN(ctx->luma_size,
-                                                       S5P_FIMV_NV12M_SALIGN);
-                       ctx->chroma_size = ALIGN(ctx->chroma_size,
-                                                       S5P_FIMV_NV12M_SALIGN);
-
-                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-
-               } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
-                       ctx->buf_width = ALIGN(ctx->img_width,
-                                                       S5P_FIMV_NV12MT_HALIGN);
-                       ctx->luma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
-                               S5P_FIMV_NV12MT_VALIGN);
-                       ctx->chroma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
-                               >> 1), S5P_FIMV_NV12MT_VALIGN);
-                       ctx->luma_size = ALIGN(ctx->luma_size,
-                                                       S5P_FIMV_NV12MT_SALIGN);
-                       ctx->chroma_size = ALIGN(ctx->chroma_size,
-                                                       S5P_FIMV_NV12MT_SALIGN);
-
-                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-               }
+
+               s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx);
+               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+
                ctx->src_bufs_cnt = 0;
                ctx->output_state = QUEUE_FREE;
        } else {
@@ -1023,6 +1033,7 @@ out:
 static int vidioc_reqbufs(struct file *file, void *priv,
                                          struct v4l2_requestbuffers *reqbufs)
 {
+       struct s5p_mfc_dev *dev = video_drvdata(file);
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
        int ret = 0;
 
@@ -1042,12 +1053,16 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                        return ret;
                }
                ctx->capture_state = QUEUE_BUFS_REQUESTED;
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err("Failed to allocate encoding buffers\n");
-                       reqbufs->count = 0;
-                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       return -ENOMEM;
+
+               if (!IS_MFCV6(dev)) {
+                       ret = s5p_mfc_hw_call(ctx->dev->mfc_ops,
+                                       alloc_codec_buffers, ctx);
+                       if (ret) {
+                               mfc_err("Failed to allocate encoding buffers\n");
+                               reqbufs->count = 0;
+                               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                               return -ENOMEM;
+                       }
                }
        } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
                if (ctx->output_state != QUEUE_FREE) {
@@ -1310,6 +1325,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
                        p->codec.h264.profile =
                                S5P_FIMV_ENC_PROFILE_H264_BASELINE;
                        break;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+                       if (IS_MFCV6(dev))
+                               p->codec.h264.profile =
+                               S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
+                       else
+                               ret = -EINVAL;
+                       break;
                default:
                        ret = -EINVAL;
                }
@@ -1349,7 +1371,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
                p->codec.h264._8x8_transform = ctrl->val;
                break;
        case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
-               p->codec.h264.rc_mb = ctrl->val;
+               p->rc_mb = ctrl->val;
                break;
        case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
                p->codec.h264.rc_frame_qp = ctrl->val;
@@ -1500,7 +1522,7 @@ int vidioc_encoder_cmd(struct file *file, void *priv,
                        mfc_debug(2, "EOS: empty src queue, entering finishing state");
                        ctx->state = MFCINST_FINISHING;
                        spin_unlock_irqrestore(&dev->irqlock, flags);
-                       s5p_mfc_try_run(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                } else {
                        mfc_debug(2, "EOS: marking last buffer of stream");
                        buf = list_entry(ctx->src_queue.prev,
@@ -1583,6 +1605,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
                        unsigned int psize[], void *allocators[])
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
 
        if (ctx->state != MFCINST_GOT_INST) {
                mfc_err("inavlid state: %d\n", ctx->state);
@@ -1611,8 +1634,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
                        *buf_count = MFC_MAX_BUFFERS;
                psize[0] = ctx->luma_size;
                psize[1] = ctx->chroma_size;
-               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
-               allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+               if (IS_MFCV6(dev)) {
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+                       allocators[1] =
+                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+               } else {
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+                       allocators[1] =
+                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+               }
        } else {
                mfc_err("inavlid queue type: %d\n", vq->type);
                return -EINVAL;
@@ -1715,7 +1747,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
        /* If context is ready then dev = work->data;schedule it to run */
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        return 0;
 }
 
@@ -1729,19 +1761,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
                ctx->state == MFCINST_RUNNING) &&
                dev->curr_ctx == ctx->num && dev->hw_lock) {
                ctx->state = MFCINST_ABORT;
-               s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET,
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET,
                                          0);
        }
        ctx->state = MFCINST_FINISHED;
        spin_lock_irqsave(&dev->irqlock, flags);
        if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
                INIT_LIST_HEAD(&ctx->dst_queue);
                ctx->dst_queue_cnt = 0;
        }
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
                cleanup_ref_queue(ctx);
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                INIT_LIST_HEAD(&ctx->src_queue);
                ctx->src_queue_cnt = 0;
        }
@@ -1782,7 +1816,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
        }
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 static struct vb2_ops s5p_mfc_enc_qops = {
@@ -1880,3 +1914,13 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
        for (i = 0; i < NUM_CTRLS; i++)
                ctx->ctrls[i] = NULL;
 }
+
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_format f;
+       f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC;
+       ctx->src_fmt = find_format(&f, MFC_FMT_RAW);
+       f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
+       ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
+}
+
index ca9fd66bd310a287ff015ee3e041e3b3ccae5518..5118d46b3a9ea767acd6290a6b5a3d550aabc905 100644 (file)
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
 struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
 int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
 
 #endif /* S5P_MFC_ENC_H_  */
index 37860e299021dddfd16f28f967e7412fb88d6ba5..5b8f0e085e6d0fe9e8460569bf095ec79f903d1d 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_intr.h"
@@ -28,7 +27,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
 
        ret = wait_event_interruptible_timeout(dev->queue,
                (dev->int_cond && (dev->int_type == command
-               || dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+               || dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
                msecs_to_jiffies(MFC_INT_TIMEOUT));
        if (ret == 0) {
                mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
@@ -40,7 +39,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
        }
        mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
                                                        dev->int_type, command);
-       if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+       if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)
                return 1;
        return 0;
 }
@@ -60,12 +59,12 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
        if (interrupt) {
                ret = wait_event_interruptible_timeout(ctx->queue,
                                (ctx->int_cond && (ctx->int_type == command
-                       || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
                                        msecs_to_jiffies(MFC_INT_TIMEOUT));
        } else {
                ret = wait_event_timeout(ctx->queue,
                                (ctx->int_cond && (ctx->int_type == command
-                       || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
                                        msecs_to_jiffies(MFC_INT_TIMEOUT));
        }
        if (ret == 0) {
@@ -78,7 +77,7 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
        }
        mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
                                                        ctx->int_type, command);
-       if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+       if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)
                return 1;
        return 0;
 }
index 767a51271dc248f8f7663545ae4e101acee9ea39..6932e90d4065470c00cccb8b5f31987152a32df1 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.c
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
  *
  * Samsung MFC (Multi Function Codec - FIMV) driver
  * This file contains hw related functions.
  *
- * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * Kamil Debski, Copyright (c) 2012 Samsung Electronics Co., Ltd.
  * http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
  * published by the Free Software Foundation.
  */
 
-#include "regs-mfc.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
-#include <asm/cacheflush.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/firmware.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
+#include "s5p_mfc_opr_v5.h"
+#include "s5p_mfc_opr_v6.h"
 
-#define OFFSETA(x)             (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
-#define OFFSETB(x)             (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
+static struct s5p_mfc_hw_ops *s5p_mfc_ops;
 
-/* Allocate temporary buffers for decoding */
-int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
 {
-       void *desc_virt;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       ctx->desc_buf = vb2_dma_contig_memops.alloc(
-                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
-       if (IS_ERR_VALUE((int)ctx->desc_buf)) {
-               ctx->desc_buf = NULL;
-               mfc_err("Allocating DESC buffer failed\n");
-               return -ENOMEM;
-       }
-       ctx->desc_phys = s5p_mfc_mem_cookie(
-                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
-       BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
-       if (desc_virt == NULL) {
-               vb2_dma_contig_memops.put(ctx->desc_buf);
-               ctx->desc_phys = 0;
-               ctx->desc_buf = NULL;
-               mfc_err("Remapping DESC buffer failed\n");
-               return -ENOMEM;
-       }
-       memset(desc_virt, 0, DESC_BUF_SIZE);
-       wmb();
-       return 0;
-}
-
-/* Release temporary buffers for decoding */
-void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->desc_phys) {
-               vb2_dma_contig_memops.put(ctx->desc_buf);
-               ctx->desc_phys = 0;
-               ctx->desc_buf = NULL;
-       }
-}
-
-/* Allocate codec buffers */
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int enc_ref_y_size = 0;
-       unsigned int enc_ref_c_size = 0;
-       unsigned int guard_width, guard_height;
-
-       if (ctx->type == MFCINST_DECODER) {
-               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
-                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
-               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
-       } else if (ctx->type == MFCINST_ENCODER) {
-               enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
-
-               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
-                       enc_ref_c_size = ALIGN(ctx->img_width,
-                                               S5P_FIMV_NV12MT_HALIGN)
-                                               * ALIGN(ctx->img_height >> 1,
-                                               S5P_FIMV_NV12MT_VALIGN);
-                       enc_ref_c_size = ALIGN(enc_ref_c_size,
-                                                       S5P_FIMV_NV12MT_SALIGN);
-               } else {
-                       guard_width = ALIGN(ctx->img_width + 16,
-                                                       S5P_FIMV_NV12MT_HALIGN);
-                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                                       S5P_FIMV_NV12MT_VALIGN);
-                       enc_ref_c_size = ALIGN(guard_width * guard_height,
-                                              S5P_FIMV_NV12MT_SALIGN);
-               }
-               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
-                         enc_ref_y_size, enc_ref_c_size);
+       if (IS_MFCV6(dev)) {
+               s5p_mfc_ops = s5p_mfc_init_hw_ops_v6();
+               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6;
        } else {
-               return -EINVAL;
-       }
-       /* Codecs have different memory requirements */
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
-                                       S5P_FIMV_DEC_VERT_NB_MV_SIZE,
-                                       S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
-                                    S5P_FIMV_DEC_UPNB_MV_SIZE +
-                                    S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                                    S5P_FIMV_DEC_STX_PARSER_SIZE +
-                                    S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
-                                    S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_VC1RCV_DEC:
-       case S5P_FIMV_CODEC_VC1_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
-                            S5P_FIMV_DEC_UPNB_MV_SIZE +
-                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                            S5P_FIMV_DEC_NB_DCAC_SIZE +
-                            3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
-                            S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-               ctx->bank1_size = 0;
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_H263_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
-                            S5P_FIMV_DEC_UPNB_MV_SIZE +
-                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                            S5P_FIMV_DEC_NB_DCAC_SIZE,
-                            S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_H264_ENC:
-               ctx->bank1_size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_COLFLG_SIZE +
-                                  S5P_FIMV_ENC_INTRAMD_SIZE +
-                                  S5P_FIMV_ENC_NBORINFO_SIZE;
-               ctx->bank2_size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4) +
-                                  S5P_FIMV_ENC_INTRAPRED_SIZE;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-               ctx->bank1_size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_COLFLG_SIZE +
-                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               ctx->bank2_size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4);
-               break;
-       case S5P_FIMV_CODEC_H263_ENC:
-               ctx->bank1_size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               ctx->bank2_size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4);
-               break;
-       default:
-               break;
-       }
-       /* Allocate only if memory from bank 1 is necessary */
-       if (ctx->bank1_size > 0) {
-               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
-               if (IS_ERR(ctx->bank1_buf)) {
-                       ctx->bank1_buf = NULL;
-                       printk(KERN_ERR
-                              "Buf alloc for decoding failed (port A)\n");
-                       return -ENOMEM;
-               }
-               ctx->bank1_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
-               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       }
-       /* Allocate only if memory from bank 2 is necessary */
-       if (ctx->bank2_size > 0) {
-               ctx->bank2_buf = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
-               if (IS_ERR(ctx->bank2_buf)) {
-                       ctx->bank2_buf = NULL;
-                       mfc_err("Buf alloc for decoding failed (port B)\n");
-                       return -ENOMEM;
-               }
-               ctx->bank2_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
-               BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
-       }
-       return 0;
-}
-
-/* Release buffers allocated for codec */
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->bank1_buf) {
-               vb2_dma_contig_memops.put(ctx->bank1_buf);
-               ctx->bank1_buf = NULL;
-               ctx->bank1_phys = 0;
-               ctx->bank1_size = 0;
-       }
-       if (ctx->bank2_buf) {
-               vb2_dma_contig_memops.put(ctx->bank2_buf);
-               ctx->bank2_buf = NULL;
-               ctx->bank2_phys = 0;
-               ctx->bank2_size = 0;
+               s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
+               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
        }
+       dev->mfc_ops = s5p_mfc_ops;
 }
-
-/* Allocate memory for instance data buffer */
-int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
-{
-       void *context_virt;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
-               ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
-               ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
-       else
-               ctx->ctx_size = MFC_CTX_BUF_SIZE;
-       ctx->ctx_buf = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
-       if (IS_ERR(ctx->ctx_buf)) {
-               mfc_err("Allocating context buffer failed\n");
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-               return -ENOMEM;
-       }
-       ctx->ctx_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
-       BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
-       context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
-       if (context_virt == NULL) {
-               mfc_err("Remapping instance buffer failed\n");
-               vb2_dma_contig_memops.put(ctx->ctx_buf);
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-               return -ENOMEM;
-       }
-       /* Zero content of the allocated memory */
-       memset(context_virt, 0, ctx->ctx_size);
-       wmb();
-       if (s5p_mfc_init_shm(ctx) < 0) {
-               vb2_dma_contig_memops.put(ctx->ctx_buf);
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-/* Release instance buffer */
-void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->ctx_buf) {
-               vb2_dma_contig_memops.put(ctx->ctx_buf);
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-       }
-       if (ctx->shm_alloc) {
-               vb2_dma_contig_memops.put(ctx->shm_alloc);
-               ctx->shm_alloc = NULL;
-               ctx->shm = NULL;
-       }
-}
-
-/* Set registers for decoding temporary buffers */
-void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
-       mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
-}
-
-/* Set registers for shared buffer */
-static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
-}
-
-/* Set registers for decoding stream buffer */
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
-                 unsigned int start_num_byte, unsigned int buf_size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
-       mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
-       mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
-       s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
-       return 0;
-}
-
-/* Set decoding frame buffer */
-int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
-{
-       unsigned int frame_size, i;
-       unsigned int frame_size_ch, frame_size_mv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dpb;
-       size_t buf_addr1, buf_addr2;
-       int buf_size1, buf_size2;
-
-       buf_addr1 = ctx->bank1_phys;
-       buf_size1 = ctx->bank1_size;
-       buf_addr2 = ctx->bank2_phys;
-       buf_size2 = ctx->bank2_size;
-       dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
-                                               ~S5P_FIMV_DPB_COUNT_MASK;
-       mfc_write(dev, ctx->total_dpb_count | dpb,
-                                               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-       s5p_mfc_set_shared_buffer(ctx);
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_H264_VERT_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
-               buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               break;
-       case S5P_FIMV_CODEC_H263_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               break;
-       case S5P_FIMV_CODEC_VC1_DEC:
-       case S5P_FIMV_CODEC_VC1RCV_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               break;
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-               break;
-       default:
-               mfc_err("Unknown codec for decoding (%x)\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-               break;
-       }
-       frame_size = ctx->luma_size;
-       frame_size_ch = ctx->chroma_size;
-       frame_size_mv = ctx->mv_size;
-       mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
-                                                               frame_size_mv);
-       for (i = 0; i < ctx->total_dpb_count; i++) {
-               /* Bank2 */
-               mfc_debug(2, "Luma %d: %x\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.luma);
-               mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
-                                               S5P_FIMV_DEC_LUMA_ADR + i * 4);
-               mfc_debug(2, "\tChroma %d: %x\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.chroma);
-               mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
-                                              S5P_FIMV_DEC_CHROMA_ADR + i * 4);
-               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
-                       mfc_debug(2, "\tBuf2: %x, size: %d\n",
-                                                       buf_addr2, buf_size2);
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                                               S5P_FIMV_H264_MV_ADR + i * 4);
-                       buf_addr2 += frame_size_mv;
-                       buf_size2 -= frame_size_mv;
-               }
-       }
-       mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
-       mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
-                       buf_size1,  buf_size2, ctx->total_dpb_count);
-       if (buf_size1 < 0 || buf_size2 < 0) {
-               mfc_debug(2, "Not enough memory has been allocated\n");
-               return -ENOMEM;
-       }
-       s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
-       s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
-               s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
-       mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
-                                       << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
-                                               S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-/* Set registers for encoding stream buffer */
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long addr, unsigned int size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
-       mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
-       return 0;
-}
-
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long y_addr, unsigned long c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
-       mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
-}
-
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long *y_addr, unsigned long *c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
-                                                       << MFC_OFFSET_SHIFT);
-       *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
-                                                       << MFC_OFFSET_SHIFT);
-}
-
-/* Set encoding ref & codec buffer */
-int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       size_t buf_addr1, buf_addr2;
-       size_t buf_size1, buf_size2;
-       unsigned int enc_ref_y_size, enc_ref_c_size;
-       unsigned int guard_width, guard_height;
-       int i;
-
-       buf_addr1 = ctx->bank1_phys;
-       buf_size1 = ctx->bank1_size;
-       buf_addr2 = ctx->bank2_phys;
-       buf_size2 = ctx->bank2_size;
-       enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-               * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-       enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
-               enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
-       } else {
-               guard_width = ALIGN(ctx->img_width + 16,
-                                               S5P_FIMV_NV12MT_HALIGN);
-               guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                               S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_c_size = ALIGN(guard_width * guard_height,
-                                      S5P_FIMV_NV12MT_SALIGN);
-       }
-       mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_COZERO_FLAG_ADR);
-               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_UP_INTRA_MD_ADR);
-               buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
-               mfc_write(dev, OFFSETB(buf_addr2),
-                                       S5P_FIMV_H264_UP_INTRA_PRED_ADR);
-               buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
-               buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_NBOR_INFO_ADR);
-               buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
-               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
-                       buf_size1, buf_size2);
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
-               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_MPEG4_ACDC_COEF_ADR);
-               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
-                       buf_size1, buf_size2);
-               break;
-       case S5P_FIMV_CODEC_H263_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
-               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
-                       buf_size1, buf_size2);
-               break;
-       default:
-               mfc_err("Unknown codec set for encoding: %d\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       unsigned int reg;
-       unsigned int shm;
-
-       /* width */
-       mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
-       /* height */
-       mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
-       /* pictype : enable, IDR period */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       reg |= (1 << 18);
-       reg &= ~(0xFFFF);
-       reg |= p->gop_size;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
-       /* multi-slice control */
-       /* multi-slice MB number or bit size */
-       mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
-       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
-               mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
-       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
-               mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
-       } else {
-               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
-               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
-       }
-       /* cyclic intra refresh */
-       mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
-       /* memory structure cur. frame */
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
-               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
-       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
-               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
-       /* padding control & value */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
-       if (p->pad) {
-               /** enable */
-               reg |= (1 << 31);
-               /** cr value */
-               reg &= ~(0xFF << 16);
-               reg |= (p->pad_cr << 16);
-               /** cb value */
-               reg &= ~(0xFF << 8);
-               reg |= (p->pad_cb << 8);
-               /** y value */
-               reg &= ~(0xFF);
-               reg |= (p->pad_luma);
-       } else {
-               /** disable & all value clear */
-               reg = 0;
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /** frame-level rate control */
-       reg &= ~(0x1 << 9);
-       reg |= (p->rc_frame << 9);
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* bit rate */
-       if (p->rc_frame)
-               mfc_write(dev, p->rc_bitrate,
-                       S5P_FIMV_ENC_RC_BIT_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
-       /* reaction coefficient */
-       if (p->rc_frame)
-               mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* seq header ctrl */
-       shm &= ~(0x1 << 3);
-       shm |= (p->seq_hdr_mode << 3);
-       /* frame skip mode */
-       shm &= ~(0x3 << 1);
-       shm |= (p->frame_skip_mode << 1);
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       /* fixed target bit */
-       s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
-       unsigned int reg;
-       unsigned int shm;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* pictype : number of B */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* num_b_frame - 0 ~ 2 */
-       reg &= ~(0x3 << 16);
-       reg |= (p->num_b_frame << 16);
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* profile & level */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_264->level << 8);
-       /* profile - 0 ~ 2 */
-       reg &= ~(0x3F);
-       reg |= p_264->profile;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
-       /* interlace  */
-       mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
-       /* height */
-       if (p->interlace)
-               mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
-       /* loopfilter ctrl */
-       mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
-       /* loopfilter alpha offset */
-       if (p_264->loop_filter_alpha < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_264->loop_filter_alpha) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_264->loop_filter_alpha & 0xF);
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
-       /* loopfilter beta offset */
-       if (p_264->loop_filter_beta < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_264->loop_filter_beta) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_264->loop_filter_beta & 0xF);
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
-       /* entropy coding mode */
-       if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
-               mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
-       /* number of ref. picture */
-       reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
-       /* num of ref. pictures of P */
-       reg &= ~(0x3 << 5);
-       reg |= (p_264->num_ref_pic_4p << 5);
-       /* max number of ref. pictures */
-       reg &= ~(0x1F);
-       reg |= p_264->max_ref_pic;
-       mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
-       /* 8x8 transform enable */
-       mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= (p_264->rc_mb << 8);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_264->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_denom)
-               mfc_write(dev, p->rc_framerate_num * 1000
-                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_264->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_264->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* macroblock adaptive scaling features */
-       if (p_264->rc_mb) {
-               reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
-               /* dark region */
-               reg &= ~(0x1 << 3);
-               reg |= (p_264->rc_mb_dark << 3);
-               /* smooth region */
-               reg &= ~(0x1 << 2);
-               reg |= (p_264->rc_mb_smooth << 2);
-               /* static region */
-               reg &= ~(0x1 << 1);
-               reg |= (p_264->rc_mb_static << 1);
-               /* high activity region */
-               reg &= ~(0x1);
-               reg |= p_264->rc_mb_activity;
-               mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
-       }
-       if (!p->rc_frame &&
-           !p_264->rc_mb) {
-               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
-               shm |= (p_264->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
-       }
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* AR VUI control */
-       shm &= ~(0x1 << 15);
-       shm |= (p_264->vui_sar << 1);
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       if (p_264->vui_sar) {
-               /* aspect ration IDC */
-               shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
-               shm &= ~(0xFF);
-               shm |= p_264->vui_sar_idc;
-               s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
-               if (p_264->vui_sar_idc == 0xFF) {
-                       /* sample  AR info */
-                       shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
-                       shm &= ~(0xFFFFFFFF);
-                       shm |= p_264->vui_ext_sar_width << 16;
-                       shm |= p_264->vui_ext_sar_height;
-                       s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
-               }
-       }
-       /* intra picture period for H.264 */
-       shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
-       /* control */
-       shm &= ~(0x1 << 16);
-       shm |= (p_264->open_gop << 16);
-       /* value */
-       if (p_264->open_gop) {
-               shm &= ~(0xFFFF);
-               shm |= p_264->open_gop_size;
-       }
-       s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p_264->cpb_size << 16);
-       }
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
-       unsigned int reg;
-       unsigned int shm;
-       unsigned int framerate;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* pictype : number of B */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* num_b_frame - 0 ~ 2 */
-       reg &= ~(0x3 << 16);
-       reg |= (p->num_b_frame << 16);
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* profile & level */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_mpeg4->level << 8);
-       /* profile - 0 ~ 2 */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->profile;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
-       /* quarter_pixel */
-       mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
-       /* qp */
-       if (!p->rc_frame) {
-               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
-               shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
-       }
-       /* frame rate */
-       if (p->rc_frame) {
-               if (p->rc_framerate_denom > 0) {
-                       framerate = p->rc_framerate_num * 1000 /
-                                               p->rc_framerate_denom;
-                       mfc_write(dev, framerate,
-                               S5P_FIMV_ENC_RC_FRAME_RATE);
-                       shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
-                       shm &= ~(0xFFFFFFFF);
-                       shm |= (1 << 31);
-                       shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
-                       shm |= (p->rc_framerate_denom & 0xFFFF);
-                       s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
-               }
-       } else {
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       }
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_mpeg4->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p->vbv_size << 16);
-       }
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
-       unsigned int reg;
-       unsigned int shm;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* qp */
-       if (!p->rc_frame) {
-               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= (p_h263->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
-       }
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_denom)
-               mfc_write(dev, p->rc_framerate_num * 1000
-                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_h263->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_h263->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_h263->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p->vbv_size << 16);
-       }
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-/* Initialize decoding */
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       s5p_mfc_set_shared_buffer(ctx);
-       /* Setup loop filter, for decoding this is only valid for MPEG4 */
-       if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
-               mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
-       mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
-               S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
-               S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
-               S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
-               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-       mfc_write(dev,
-       ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
-                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dpb;
-
-       if (flush)
-               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
-                       S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
-       else
-               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
-                       ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
-       mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-}
-
-/* Decode a single frame */
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
-                                       enum s5p_mfc_decode_arg last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
-       s5p_mfc_set_shared_buffer(ctx);
-       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
-       /* Issue different commands to instance basing on whether it
-        * is the last frame or not. */
-       switch (last_frame) {
-       case MFC_DEC_FRAME:
-               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
-               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       case MFC_DEC_LAST_FRAME:
-               mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
-               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       case MFC_DEC_RES_CHANGE:
-               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
-               S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
-               S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       }
-       mfc_debug(2, "Decoding a usual frame\n");
-       return 0;
-}
-
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
-               s5p_mfc_set_enc_params_h264(ctx);
-       else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
-               s5p_mfc_set_enc_params_mpeg4(ctx);
-       else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
-               s5p_mfc_set_enc_params_h263(ctx);
-       else {
-               mfc_err("Unknown codec for encoding (%x)\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-       s5p_mfc_set_shared_buffer(ctx);
-       mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
-               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-/* Encode a single frame */
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int cmd;
-       /* memory structure cur. frame */
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
-               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
-       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
-               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
-       s5p_mfc_set_shared_buffer(ctx);
-
-       if (ctx->state == MFCINST_FINISHING)
-               cmd = S5P_FIMV_CH_LAST_FRAME;
-       else
-               cmd = S5P_FIMV_CH_FRAME_START;
-       mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
-                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-
-       return 0;
-}
-
-static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
-{
-       unsigned long flags;
-       int new_ctx;
-       int cnt;
-
-       spin_lock_irqsave(&dev->condlock, flags);
-       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
-       cnt = 0;
-       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
-               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
-               if (++cnt > MFC_NUM_CONTEXTS) {
-                       /* No contexts to run */
-                       spin_unlock_irqrestore(&dev->condlock, flags);
-                       return -EAGAIN;
-               }
-       }
-       spin_unlock_irqrestore(&dev->condlock, flags);
-       return new_ctx;
-}
-
-static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_decode_one_frame(ctx, MFC_DEC_RES_CHANGE);
-}
-
-static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *temp_vb;
-       unsigned long flags;
-       unsigned int index;
-
-       spin_lock_irqsave(&dev->irqlock, flags);
-       /* Frames are being decoded */
-       if (list_empty(&ctx->src_queue)) {
-               mfc_debug(2, "No src buffers\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EAGAIN;
-       }
-       /* Get the next source buffer */
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       temp_vb->flags |= MFC_BUF_FLAG_USED;
-       s5p_mfc_set_dec_stream_buffer(ctx,
-               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
-                                       temp_vb->b->v4l2_planes[0].bytesused);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       index = temp_vb->b->v4l2_buf.index;
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
-               last_frame = MFC_DEC_LAST_FRAME;
-               mfc_debug(2, "Setting ctx->state to FINISHING\n");
-               ctx->state = MFCINST_FINISHING;
-       }
-       s5p_mfc_decode_one_frame(ctx, last_frame);
-       return 0;
-}
-
-static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *dst_mb;
-       struct s5p_mfc_buf *src_mb;
-       unsigned long src_y_addr, src_c_addr, dst_addr;
-       unsigned int dst_size;
-
-       spin_lock_irqsave(&dev->irqlock, flags);
-       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
-               mfc_debug(2, "no src buffers\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EAGAIN;
-       }
-       if (list_empty(&ctx->dst_queue)) {
-               mfc_debug(2, "no dst buffers\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EAGAIN;
-       }
-       if (list_empty(&ctx->src_queue)) {
-               /* send null frame */
-               s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, dev->bank2);
-               src_mb = NULL;
-       } else {
-               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
-                                                                       list);
-               src_mb->flags |= MFC_BUF_FLAG_USED;
-               if (src_mb->b->v4l2_planes[0].bytesused == 0) {
-                       /* send null frame */
-                       s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2,
-                                                               dev->bank2);
-                       ctx->state = MFCINST_FINISHING;
-               } else {
-                       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
-                                                                       0);
-                       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
-                                                                       1);
-                       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr,
-                                                               src_c_addr);
-                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
-                               ctx->state = MFCINST_FINISHING;
-               }
-       }
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_mb->flags |= MFC_BUF_FLAG_USED;
-       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
-       dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       mfc_debug(2, "encoding buffer with index=%d state=%d",
-                       src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
-       s5p_mfc_encode_one_frame(ctx);
-       return 0;
-}
-
-static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *temp_vb;
-
-       /* Initializing decoding - parsing header */
-       spin_lock_irqsave(&dev->irqlock, flags);
-       mfc_debug(2, "Preparing to init decoding\n");
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       s5p_mfc_set_dec_desc_buffer(ctx);
-       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
-       s5p_mfc_set_dec_stream_buffer(ctx,
-                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
-                               0, temp_vb->b->v4l2_planes[0].bytesused);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_init_decode(ctx);
-}
-
-static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned long dst_addr;
-       unsigned int dst_size;
-
-       s5p_mfc_set_enc_ref_buffer(ctx);
-       spin_lock_irqsave(&dev->irqlock, flags);
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
-       dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_init_encode(ctx);
-}
-
-static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *temp_vb;
-       int ret;
-
-       /*
-        * Header was parsed now starting processing
-        * First set the output frame buffers
-        */
-       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
-               mfc_err("It seems that not all destionation buffers were "
-                       "mmaped\nMFC requires that all destination are mmaped "
-                       "before starting processing\n");
-               return -EAGAIN;
-       }
-       spin_lock_irqsave(&dev->irqlock, flags);
-       if (list_empty(&ctx->src_queue)) {
-               mfc_err("Header has been deallocated in the middle of"
-                       " initialization\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EIO;
-       }
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
-       s5p_mfc_set_dec_stream_buffer(ctx,
-                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
-                               0, temp_vb->b->v4l2_planes[0].bytesused);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       ret = s5p_mfc_set_dec_frame_buffer(ctx);
-       if (ret) {
-               mfc_err("Failed to alloc frame mem\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-/* Try running an operation on hardware */
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *ctx;
-       int new_ctx;
-       unsigned int ret = 0;
-
-       if (test_bit(0, &dev->enter_suspend)) {
-               mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
-               return;
-       }
-       /* Check whether hardware is not running */
-       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
-               /* This is perfectly ok, the scheduled ctx should wait */
-               mfc_debug(1, "Couldn't lock HW\n");
-               return;
-       }
-       /* Choose the context to run */
-       new_ctx = s5p_mfc_get_new_ctx(dev);
-       if (new_ctx < 0) {
-               /* No contexts to run */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
-                       mfc_err("Failed to unlock hardware\n");
-                       return;
-               }
-               mfc_debug(1, "No ctx is scheduled to be run\n");
-               return;
-       }
-       ctx = dev->ctx[new_ctx];
-       /* Got context to run in ctx */
-       /*
-        * Last frame has already been sent to MFC.
-        * Now obtaining frames from MFC buffer
-        */
-       s5p_mfc_clock_on();
-       if (ctx->type == MFCINST_DECODER) {
-               s5p_mfc_set_dec_desc_buffer(ctx);
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
-                       break;
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
-                       break;
-               case MFCINST_INIT:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_open_inst_cmd(ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_close_inst_cmd(ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               case MFCINST_HEAD_PARSED:
-                       ret = s5p_mfc_run_init_dec_buffers(ctx);
-                       mfc_debug(1, "head parsed\n");
-                       break;
-               case MFCINST_RES_CHANGE_INIT:
-                       s5p_mfc_run_res_change(ctx);
-                       break;
-               case MFCINST_RES_CHANGE_FLUSH:
-                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
-                       break;
-               case MFCINST_RES_CHANGE_END:
-                       mfc_debug(2, "Finished remaining frames after resolution change\n");
-                       ctx->capture_state = QUEUE_FREE;
-                       mfc_debug(2, "Will re-init the codec\n");
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else if (ctx->type == MFCINST_ENCODER) {
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_enc_frame(ctx);
-                       break;
-               case MFCINST_INIT:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_open_inst_cmd(ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_close_inst_cmd(ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_enc(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else {
-               mfc_err("Invalid context type: %d\n", ctx->type);
-               ret = -EAGAIN;
-       }
-
-       if (ret) {
-               /* Free hardware lock */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       mfc_err("Failed to unlock hardware\n");
-
-               /* This is in deed imporant, as no operation has been
-                * scheduled, reduce the clock count as no one will
-                * ever do this, because no interrupt related to this try_run
-                * will ever come from hardware. */
-               s5p_mfc_clock_off();
-       }
-}
-
-
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
-{
-       struct s5p_mfc_buf *b;
-       int i;
-
-       while (!list_empty(lh)) {
-               b = list_entry(lh->next, struct s5p_mfc_buf, list);
-               for (i = 0; i < b->b->num_planes; i++)
-                       vb2_set_plane_payload(b->b, i, 0);
-               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
-               list_del(&b->list);
-       }
-}
-
index 2ad3def052f8836d844e27ef6bad80ec0d77d8dc..420abecafec0e625e1a5745cfbf5c7bf7fe05bb9 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.h
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
  *
  * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
  * Contains declarations of hw related functions.
  *
- * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd.
  * http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
 
 #include "s5p_mfc_common.h"
 
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
+struct s5p_mfc_hw_ops {
+       int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx);
+       void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx);
+       void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx);
+       void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev);
+       void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev);
+       void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx);
+       void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx);
+       int (*set_dec_stream_buffer)(struct s5p_mfc_ctx *ctx,
+                       int buf_addr, unsigned int start_num_byte,
+                       unsigned int buf_size);
+       int (*set_dec_frame_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long addr, unsigned int size);
+       void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long y_addr, unsigned long c_addr);
+       void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long *y_addr, unsigned long *c_addr);
+       int (*set_enc_ref_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*init_decode)(struct s5p_mfc_ctx *ctx);
+       int (*init_encode)(struct s5p_mfc_ctx *ctx);
+       int (*encode_one_frame)(struct s5p_mfc_ctx *ctx);
+       void (*try_run)(struct s5p_mfc_dev *dev);
+       void (*cleanup_queue)(struct list_head *lh,
+                       struct vb2_queue *vq);
+       void (*clear_int_flags)(struct s5p_mfc_dev *dev);
+       void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data,
+                       unsigned int ofs);
+       unsigned int (*read_info)(struct s5p_mfc_ctx *ctx,
+                       unsigned int ofs);
+       int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
+       int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
+       int (*get_dspl_status)(struct s5p_mfc_dev *dev);
+       int (*get_dec_status)(struct s5p_mfc_dev *dev);
+       int (*get_dec_frame_type)(struct s5p_mfc_dev *dev);
+       int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx);
+       int (*get_consumed_stream)(struct s5p_mfc_dev *dev);
+       int (*get_int_reason)(struct s5p_mfc_dev *dev);
+       int (*get_int_err)(struct s5p_mfc_dev *dev);
+       int (*err_dec)(unsigned int err);
+       int (*err_dspl)(unsigned int err);
+       int (*get_img_width)(struct s5p_mfc_dev *dev);
+       int (*get_img_height)(struct s5p_mfc_dev *dev);
+       int (*get_dpb_count)(struct s5p_mfc_dev *dev);
+       int (*get_mv_count)(struct s5p_mfc_dev *dev);
+       int (*get_inst_no)(struct s5p_mfc_dev *dev);
+       int (*get_enc_strm_size)(struct s5p_mfc_dev *dev);
+       int (*get_enc_slice_type)(struct s5p_mfc_dev *dev);
+       int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev);
+       int (*get_enc_pic_count)(struct s5p_mfc_dev *dev);
+       int (*get_sei_avail_status)(struct s5p_mfc_ctx *ctx);
+       int (*get_mvc_num_views)(struct s5p_mfc_dev *dev);
+       int (*get_mvc_view_id)(struct s5p_mfc_dev *dev);
+       unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
+};
 
-/* Decoding functions */
-int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
-                                                 unsigned int start_num_byte,
-                                                 unsigned int buf_size);
-
-/* Encoding functions */
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long y_addr, unsigned long c_addr);
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long addr, unsigned int size);
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long *y_addr, unsigned long *c_addr);
-int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
-
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
-                                       enum s5p_mfc_decode_arg last_frame);
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
-
-/* Memory allocation */
-int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
-
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
-
-#define s5p_mfc_get_dspl_y_adr()       (readl(dev->regs_base + \
-                                       S5P_FIMV_SI_DISPLAY_Y_ADR) << \
-                                       MFC_OFFSET_SHIFT)
-#define s5p_mfc_get_dec_y_adr()                (readl(dev->regs_base + \
-                                       S5P_FIMV_SI_DECODE_Y_ADR) << \
-                                       MFC_OFFSET_SHIFT)
-#define s5p_mfc_get_dspl_status()      readl(dev->regs_base + \
-                                               S5P_FIMV_SI_DISPLAY_STATUS)
-#define s5p_mfc_get_dec_status()       readl(dev->regs_base + \
-                                               S5P_FIMV_SI_DECODE_STATUS)
-#define s5p_mfc_get_frame_type()       (readl(dev->regs_base + \
-                                               S5P_FIMV_DECODE_FRAME_TYPE) \
-                                       & S5P_FIMV_DECODE_FRAME_MASK)
-#define s5p_mfc_get_consumed_stream()  readl(dev->regs_base + \
-                                               S5P_FIMV_SI_CONSUMED_BYTES)
-#define s5p_mfc_get_int_reason()       (readl(dev->regs_base + \
-                                       S5P_FIMV_RISC2HOST_CMD) & \
-                                       S5P_FIMV_RISC2HOST_CMD_MASK)
-#define s5p_mfc_get_int_err()          readl(dev->regs_base + \
-                                               S5P_FIMV_RISC2HOST_ARG2)
-#define s5p_mfc_err_dec(x)             (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
-                                                       S5P_FIMV_ERR_DEC_SHIFT)
-#define s5p_mfc_err_dspl(x)            (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
-                                                       S5P_FIMV_ERR_DSPL_SHIFT)
-#define s5p_mfc_get_img_width()                readl(dev->regs_base + \
-                                               S5P_FIMV_SI_HRESOL)
-#define s5p_mfc_get_img_height()       readl(dev->regs_base + \
-                                               S5P_FIMV_SI_VRESOL)
-#define s5p_mfc_get_dpb_count()                readl(dev->regs_base + \
-                                               S5P_FIMV_SI_BUF_NUMBER)
-#define s5p_mfc_get_inst_no()          readl(dev->regs_base + \
-                                               S5P_FIMV_RISC2HOST_ARG1)
-#define s5p_mfc_get_enc_strm_size()    readl(dev->regs_base + \
-                                               S5P_FIMV_ENC_SI_STRM_SIZE)
-#define s5p_mfc_get_enc_slice_type()   readl(dev->regs_base + \
-                                               S5P_FIMV_ENC_SI_SLICE_TYPE)
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
 
 #endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
new file mode 100644 (file)
index 0000000..bf7d010
--- /dev/null
@@ -0,0 +1,1794 @@
+/*
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v5.h"
+#include <asm/cacheflush.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#define OFFSETA(x)             (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
+#define OFFSETB(x)             (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+
+       ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+                       buf_size->dsc);
+       if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
+               ctx->dsc.alloc = NULL;
+               mfc_err("Allocating DESC buffer failed\n");
+               return -ENOMEM;
+       }
+       ctx->dsc.dma = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc);
+       BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       ctx->dsc.virt = vb2_dma_contig_memops.vaddr(ctx->dsc.alloc);
+       if (ctx->dsc.virt == NULL) {
+               vb2_dma_contig_memops.put(ctx->dsc.alloc);
+               ctx->dsc.dma = 0;
+               ctx->dsc.alloc = NULL;
+               mfc_err("Remapping DESC buffer failed\n");
+               return -ENOMEM;
+       }
+       memset(ctx->dsc.virt, 0, buf_size->dsc);
+       wmb();
+       return 0;
+}
+
+/* Release temporary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->dsc.dma) {
+               vb2_dma_contig_memops.put(ctx->dsc.alloc);
+               ctx->dsc.alloc = NULL;
+               ctx->dsc.dma = 0;
+       }
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int enc_ref_y_size = 0;
+       unsigned int enc_ref_c_size = 0;
+       unsigned int guard_width, guard_height;
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+
+               if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+                       enc_ref_c_size = ALIGN(ctx->img_width,
+                                               S5P_FIMV_NV12MT_HALIGN)
+                                               * ALIGN(ctx->img_height >> 1,
+                                               S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(enc_ref_c_size,
+                                                       S5P_FIMV_NV12MT_SALIGN);
+               } else {
+                       guard_width = ALIGN(ctx->img_width + 16,
+                                                       S5P_FIMV_NV12MT_HALIGN);
+                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                                       S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                              S5P_FIMV_NV12MT_SALIGN);
+               }
+               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+                         enc_ref_y_size, enc_ref_c_size);
+       } else {
+               return -EINVAL;
+       }
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
+                                       S5P_FIMV_DEC_VERT_NB_MV_SIZE,
+                                       S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
+                                    S5P_FIMV_DEC_UPNB_MV_SIZE +
+                                    S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                                    S5P_FIMV_DEC_STX_PARSER_SIZE +
+                                    S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
+                                    S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE +
+                            3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               ctx->bank1_size = 0;
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_INTRAMD_SIZE +
+                                  S5P_FIMV_ENC_NBORINFO_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4) +
+                                  S5P_FIMV_ENC_INTRAPRED_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       default:
+               break;
+       }
+       /* Allocate only if memory from bank 1 is necessary */
+       if (ctx->bank1_size > 0) {
+               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+               if (IS_ERR(ctx->bank1_buf)) {
+                       ctx->bank1_buf = NULL;
+                       printk(KERN_ERR
+                              "Buf alloc for decoding failed (port A)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank1_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       }
+       /* Allocate only if memory from bank 2 is necessary */
+       if (ctx->bank2_size > 0) {
+               ctx->bank2_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
+               if (IS_ERR(ctx->bank2_buf)) {
+                       ctx->bank2_buf = NULL;
+                       mfc_err("Buf alloc for decoding failed (port B)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank2_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
+               BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
+       }
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->bank1_buf) {
+               vb2_dma_contig_memops.put(ctx->bank1_buf);
+               ctx->bank1_buf = NULL;
+               ctx->bank1_phys = 0;
+               ctx->bank1_size = 0;
+       }
+       if (ctx->bank2_buf) {
+               vb2_dma_contig_memops.put(ctx->bank2_buf);
+               ctx->bank2_buf = NULL;
+               ctx->bank2_phys = 0;
+               ctx->bank2_size = 0;
+       }
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+               ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               ctx->ctx.size = buf_size->h264_ctx;
+       else
+               ctx->ctx.size = buf_size->non_h264_ctx;
+       ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
+       if (IS_ERR(ctx->ctx.alloc)) {
+               mfc_err("Allocating context buffer failed\n");
+               ctx->ctx.alloc = NULL;
+               return -ENOMEM;
+       }
+       ctx->ctx.dma = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+       BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
+       ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+       if (!ctx->ctx.virt) {
+               mfc_err("Remapping instance buffer failed\n");
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.ofs = 0;
+               ctx->ctx.dma = 0;
+               return -ENOMEM;
+       }
+       /* Zero content of the allocated memory */
+       memset(ctx->ctx.virt, 0, ctx->ctx.size);
+       wmb();
+
+       /* Initialize shared memory */
+       ctx->shm.alloc = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->shm);
+       if (IS_ERR(ctx->shm.alloc)) {
+               mfc_err("failed to allocate shared memory\n");
+               return PTR_ERR(ctx->shm.alloc);
+       }
+       /* shared memory offset only keeps the offset from base (port a) */
+       ctx->shm.ofs = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm.alloc)
+                                                               - dev->bank1;
+       BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+
+       ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
+       if (!ctx->shm.virt) {
+               vb2_dma_contig_memops.put(ctx->shm.alloc);
+               ctx->shm.alloc = NULL;
+               ctx->shm.ofs = 0;
+               mfc_err("failed to virt addr of shared memory\n");
+               return -ENOMEM;
+       }
+       memset((void *)ctx->shm.virt, 0, buf_size->shm);
+       wmb();
+       return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->ctx.alloc) {
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.ofs = 0;
+               ctx->ctx.virt = NULL;
+               ctx->ctx.dma = 0;
+       }
+       if (ctx->shm.alloc) {
+               vb2_dma_contig_memops.put(ctx->shm.alloc);
+               ctx->shm.alloc = NULL;
+               ctx->shm.ofs = 0;
+               ctx->shm.virt = NULL;
+       }
+}
+
+int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+
+       return 0;
+}
+
+void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+}
+
+static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
+                       unsigned int ofs)
+{
+       writel(data, (ctx->shm.virt + ofs));
+       wmb();
+}
+
+static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
+                               unsigned int ofs)
+{
+       rmb();
+       return readl(ctx->shm.virt + ofs);
+}
+
+void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int guard_width, guard_height;
+
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+       mfc_debug(2,
+               "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
+               ctx->img_width, ctx->img_height, ctx->buf_width,
+               ctx->buf_height);
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+               ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->chroma_size = ALIGN(ctx->buf_width *
+                               ALIGN((ctx->img_height >> 1),
+                                       S5P_FIMV_NV12MT_VALIGN),
+                               S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->mv_size = ALIGN(ctx->buf_width *
+                               ALIGN((ctx->buf_height >> 2),
+                                       S5P_FIMV_NV12MT_VALIGN),
+                               S5P_FIMV_DEC_BUF_ALIGN);
+       } else {
+               guard_width =
+                       ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
+               guard_height =
+                       ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
+               ctx->luma_size = ALIGN(guard_width * guard_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+
+               guard_width =
+                       ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
+               guard_height =
+                       ALIGN((ctx->img_height >> 1) + 4,
+                                       S5P_FIMV_NV12MT_VALIGN);
+               ctx->chroma_size = ALIGN(guard_width * guard_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+
+               ctx->mv_size = 0;
+       }
+}
+
+void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
+
+               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
+               ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
+
+               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
+               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+
+               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+
+               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
+       }
+}
+
+/* Set registers for decoding temporary buffers */
+static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+
+       mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
+       mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
+}
+
+/* Set registers for shared buffer */
+static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr,
+                 unsigned int start_num_byte, unsigned int buf_size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
+       mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
+       mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
+       s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);
+       return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int frame_size, i;
+       unsigned int frame_size_ch, frame_size_mv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+       size_t buf_addr1, buf_addr2;
+       int buf_size1, buf_size2;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+       buf_addr2 = ctx->bank2_phys;
+       buf_size2 = ctx->bank2_size;
+       dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                                               ~S5P_FIMV_DPB_COUNT_MASK;
+       mfc_write(dev, ctx->total_dpb_count | dpb,
+                                               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       s5p_mfc_set_shared_buffer(ctx);
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_H264_VERT_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               break;
+       default:
+               mfc_err("Unknown codec for decoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+               break;
+       }
+       frame_size = ctx->luma_size;
+       frame_size_ch = ctx->chroma_size;
+       frame_size_mv = ctx->mv_size;
+       mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
+                                                               frame_size_mv);
+       for (i = 0; i < ctx->total_dpb_count; i++) {
+               /* Bank2 */
+               mfc_debug(2, "Luma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.luma);
+               mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
+                                               S5P_FIMV_DEC_LUMA_ADR + i * 4);
+               mfc_debug(2, "\tChroma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.chroma);
+               mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
+                                              S5P_FIMV_DEC_CHROMA_ADR + i * 4);
+               if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+                       mfc_debug(2, "\tBuf2: %x, size: %d\n",
+                                                       buf_addr2, buf_size2);
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                                               S5P_FIMV_H264_MV_ADR + i * 4);
+                       buf_addr2 += frame_size_mv;
+                       buf_size2 -= frame_size_mv;
+               }
+       }
+       mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
+       mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
+                       buf_size1,  buf_size2, ctx->total_dpb_count);
+       if (buf_size1 < 0 || buf_size2 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated\n");
+               return -ENOMEM;
+       }
+       s5p_mfc_write_info_v5(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
+       s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
+               s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
+       mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
+                                       << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+                                               S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
+       mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
+       return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
+       mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
+}
+
+void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
+                                                       << MFC_OFFSET_SHIFT);
+       *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
+                                                       << MFC_OFFSET_SHIFT);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1, buf_addr2;
+       size_t buf_size1, buf_size2;
+       unsigned int enc_ref_y_size, enc_ref_c_size;
+       unsigned int guard_width, guard_height;
+       int i;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+       buf_addr2 = ctx->bank2_phys;
+       buf_size2 = ctx->bank2_size;
+       enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+               * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+       enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+               enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
+       } else {
+               guard_width = ALIGN(ctx->img_width + 16,
+                                               S5P_FIMV_NV12MT_HALIGN);
+               guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                               S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                      S5P_FIMV_NV12MT_SALIGN);
+       }
+       mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_UP_INTRA_MD_ADR);
+               buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
+               mfc_write(dev, OFFSETB(buf_addr2),
+                                       S5P_FIMV_H264_UP_INTRA_PRED_ADR);
+               buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
+               buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_NBOR_INFO_ADR);
+               buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       default:
+               mfc_err("Unknown codec set for encoding: %d\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       unsigned int reg;
+       unsigned int shm;
+
+       /* width */
+       mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
+       /* height */
+       mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
+       /* pictype : enable, IDR period */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       reg |= (1 << 18);
+       reg &= ~(0xFFFF);
+       reg |= p->gop_size;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+               mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
+       }
+       /* cyclic intra refresh */
+       mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       /* padding control & value */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
+       if (p->pad) {
+               /** enable */
+               reg |= (1 << 31);
+               /** cr value */
+               reg &= ~(0xFF << 16);
+               reg |= (p->pad_cr << 16);
+               /** cb value */
+               reg &= ~(0xFF << 8);
+               reg |= (p->pad_cb << 8);
+               /** y value */
+               reg &= ~(0xFF);
+               reg |= (p->pad_luma);
+       } else {
+               /** disable & all value clear */
+               reg = 0;
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /** frame-level rate control */
+       reg &= ~(0x1 << 9);
+       reg |= (p->rc_frame << 9);
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* bit rate */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_bitrate,
+                       S5P_FIMV_ENC_RC_BIT_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
+       /* reaction coefficient */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* seq header ctrl */
+       shm &= ~(0x1 << 3);
+       shm |= (p->seq_hdr_mode << 3);
+       /* frame skip mode */
+       shm &= ~(0x3 << 1);
+       shm |= (p->frame_skip_mode << 1);
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       /* fixed target bit */
+       s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_264->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_264->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* interlace  */
+       mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
+       /* height */
+       if (p_264->interlace)
+               mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
+       /* loopfilter ctrl */
+       mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
+       /* loopfilter alpha offset */
+       if (p_264->loop_filter_alpha < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_alpha) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_alpha & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
+       /* loopfilter beta offset */
+       if (p_264->loop_filter_beta < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_beta) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_beta & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
+       /* entropy coding mode */
+       if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
+               mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       /* number of ref. picture */
+       reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* num of ref. pictures of P */
+       reg &= ~(0x3 << 5);
+       reg |= (p_264->num_ref_pic_4p << 5);
+       /* max number of ref. pictures */
+       reg &= ~(0x1F);
+       reg |= p_264->max_ref_pic;
+       mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* 8x8 transform enable */
+       mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= (p->rc_mb << 8);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_264->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* macroblock adaptive scaling features */
+       if (p->rc_mb) {
+               reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
+               /* dark region */
+               reg &= ~(0x1 << 3);
+               reg |= (p_264->rc_mb_dark << 3);
+               /* smooth region */
+               reg &= ~(0x1 << 2);
+               reg |= (p_264->rc_mb_smooth << 2);
+               /* static region */
+               reg &= ~(0x1 << 1);
+               reg |= (p_264->rc_mb_static << 1);
+               /* high activity region */
+               reg &= ~(0x1);
+               reg |= p_264->rc_mb_activity;
+               mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
+       }
+       if (!p->rc_frame && !p->rc_mb) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_264->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* AR VUI control */
+       shm &= ~(0x1 << 15);
+       shm |= (p_264->vui_sar << 1);
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       if (p_264->vui_sar) {
+               /* aspect ration IDC */
+               shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);
+               shm &= ~(0xFF);
+               shm |= p_264->vui_sar_idc;
+               s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
+               if (p_264->vui_sar_idc == 0xFF) {
+                       /* sample  AR info */
+                       shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= p_264->vui_ext_sar_width << 16;
+                       shm |= p_264->vui_ext_sar_height;
+                       s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);
+               }
+       }
+       /* intra picture period for H.264 */
+       shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);
+       /* control */
+       shm &= ~(0x1 << 16);
+       shm |= (p_264->open_gop << 16);
+       /* value */
+       if (p_264->open_gop) {
+               shm &= ~(0xFFFF);
+               shm |= p_264->open_gop_size;
+       }
+       s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p_264->cpb_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+       unsigned int framerate;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_mpeg4->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* quarter_pixel */
+       mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame) {
+               if (p->rc_framerate_denom > 0) {
+                       framerate = p->rc_framerate_num * 1000 /
+                                               p->rc_framerate_denom;
+                       mfc_write(dev, framerate,
+                               S5P_FIMV_ENC_RC_FRAME_RATE);
+                       shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= (1 << 31);
+                       shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
+                       shm |= (p->rc_framerate_denom & 0xFFFF);
+                       s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);
+               }
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       }
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_mpeg4->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= (p_h263->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_h263->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_shared_buffer(ctx);
+       /* Setup loop filter, for decoding this is only valid for MPEG4 */
+       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)
+               mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
+       mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
+               S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
+               S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
+               S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
+               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       mfc_write(dev,
+       ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+
+       if (flush)
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
+                       S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       else
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                       ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
+                                       enum s5p_mfc_decode_arg last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
+       s5p_mfc_set_shared_buffer(ctx);
+       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case MFC_DEC_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_LAST_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_RES_CHANGE:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
+               S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+               S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       }
+       mfc_debug(2, "Decoding a usual frame\n");
+       return 0;
+}
+
+int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+               s5p_mfc_set_enc_params_h263(ctx);
+       else {
+               mfc_err("Unknown codec for encoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       s5p_mfc_set_shared_buffer(ctx);
+       mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
+               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int cmd;
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       s5p_mfc_set_shared_buffer(ctx);
+
+       if (ctx->state == MFCINST_FINISHING)
+               cmd = S5P_FIMV_CH_LAST_FRAME;
+       else
+               cmd = S5P_FIMV_CH_FRAME_START;
+       mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+
+       return 0;
+}
+
+static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+       int new_ctx;
+       int cnt;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+       cnt = 0;
+       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+               if (++cnt > MFC_NUM_CONTEXTS) {
+                       /* No contexts to run */
+                       spin_unlock_irqrestore(&dev->condlock, flags);
+                       return -EAGAIN;
+               }
+       }
+       spin_unlock_irqrestore(&dev->condlock, flags);
+       return new_ctx;
+}
+
+static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
+}
+
+static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       unsigned long flags;
+       unsigned int index;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+               ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       index = temp_vb->b->v4l2_buf.index;
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+               last_frame = MFC_DEC_LAST_FRAME;
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               ctx->state = MFCINST_FINISHING;
+       }
+       s5p_mfc_decode_one_frame_v5(ctx, last_frame);
+       return 0;
+}
+
+static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       unsigned int dst_size;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
+               mfc_debug(2, "no src buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->dst_queue)) {
+               mfc_debug(2, "no dst buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->src_queue)) {
+               /* send null frame */
+               s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, dev->bank2);
+               src_mb = NULL;
+       } else {
+               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               src_mb->flags |= MFC_BUF_FLAG_USED;
+               if (src_mb->b->v4l2_planes[0].bytesused == 0) {
+                       /* send null frame */
+                       s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2,
+                                                               dev->bank2);
+                       ctx->state = MFCINST_FINISHING;
+               } else {
+                       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
+                                                                       0);
+                       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
+                                                                       1);
+                       s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr,
+                                                               src_c_addr);
+                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
+                               ctx->state = MFCINST_FINISHING;
+               }
+       }
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_mb->flags |= MFC_BUF_FLAG_USED;
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       mfc_debug(2, "encoding buffer with index=%d state=%d",
+                       src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
+       s5p_mfc_encode_one_frame_v5(ctx);
+       return 0;
+}
+
+static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+
+       /* Initializing decoding - parsing header */
+       spin_lock_irqsave(&dev->irqlock, flags);
+       mfc_debug(2, "Preparing to init decoding\n");
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       s5p_mfc_set_dec_desc_buffer(ctx);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+                               0, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_decode_v5(ctx);
+}
+
+static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       s5p_mfc_set_enc_ref_buffer_v5(ctx);
+       spin_lock_irqsave(&dev->irqlock, flags);
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_encode_v5(ctx);
+}
+
+static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+       int ret;
+
+       /*
+        * Header was parsed now starting processing
+        * First set the output frame buffers
+        */
+       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+               mfc_err("It seems that not all destionation buffers were "
+                       "mmaped\nMFC requires that all destination are mmaped "
+                       "before starting processing\n");
+               return -EAGAIN;
+       }
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (list_empty(&ctx->src_queue)) {
+               mfc_err("Header has been deallocated in the middle of"
+                       " initialization\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EIO;
+       }
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+                               0, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int new_ctx;
+       unsigned int ret = 0;
+
+       if (test_bit(0, &dev->enter_suspend)) {
+               mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
+               return;
+       }
+       /* Check whether hardware is not running */
+       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(1, "Couldn't lock HW\n");
+               return;
+       }
+       /* Choose the context to run */
+       new_ctx = s5p_mfc_get_new_ctx(dev);
+       if (new_ctx < 0) {
+               /* No contexts to run */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+                       mfc_err("Failed to unlock hardware\n");
+                       return;
+               }
+               mfc_debug(1, "No ctx is scheduled to be run\n");
+               return;
+       }
+       ctx = dev->ctx[new_ctx];
+       /* Got context to run in ctx */
+       /*
+        * Last frame has already been sent to MFC.
+        * Now obtaining frames from MFC buffer
+        */
+       s5p_mfc_clock_on();
+       if (ctx->type == MFCINST_DECODER) {
+               s5p_mfc_set_dec_desc_buffer(ctx);
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
+                       break;
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_run_init_dec_buffers(ctx);
+                       mfc_debug(1, "head parsed\n");
+                       break;
+               case MFCINST_RES_CHANGE_INIT:
+                       s5p_mfc_run_res_change(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_FLUSH:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_RES_CHANGE_END:
+                       mfc_debug(2, "Finished remaining frames after resolution change\n");
+                       ctx->capture_state = QUEUE_FREE;
+                       mfc_debug(2, "Will re-init the codec\n");
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_enc(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else {
+               mfc_err("Invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Free hardware lock */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       mfc_err("Failed to unlock hardware\n");
+
+               /* This is in deed imporant, as no operation has been
+                * scheduled, reduce the clock count as no one will
+                * ever do this, because no interrupt related to this try_run
+                * will ever come from hardware. */
+               s5p_mfc_clock_off();
+       }
+}
+
+
+void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
+{
+       struct s5p_mfc_buf *b;
+       int i;
+
+       while (!list_empty(lh)) {
+               b = list_entry(lh->next, struct s5p_mfc_buf, list);
+               for (i = 0; i < b->b->num_planes; i++)
+                       vb2_set_plane_payload(b->b, i, 0);
+               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+               list_del(&b->list);
+       }
+}
+
+void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
+}
+
+int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
+}
+
+int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
+}
+
+int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
+               S5P_FIMV_DECODE_FRAME_MASK;
+}
+
+int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
+{
+       return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
+                       S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
+                       S5P_FIMV_DECODE_FRAME_MASK;
+}
+
+int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
+}
+
+int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
+{
+       int reason;
+       reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
+               S5P_FIMV_RISC2HOST_CMD_MASK;
+       switch (reason) {
+       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
+               reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+               reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
+               reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
+               reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SLEEP_RET:
+               reason = S5P_MFC_R2H_CMD_SLEEP_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+               reason = S5P_MFC_R2H_CMD_WAKEUP_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+               reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
+               reason = S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_ERR_RET:
+               reason = S5P_MFC_R2H_CMD_ERR_RET;
+               break;
+       default:
+               reason = S5P_MFC_R2H_CMD_EMPTY;
+       };
+       return reason;
+}
+
+int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
+}
+
+int s5p_mfc_err_dec_v5(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
+}
+
+int s5p_mfc_err_dspl_v5(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT;
+}
+
+int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_HRESOL);
+}
+
+int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_VRESOL);
+}
+
+int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
+}
+
+int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+       return -1;
+}
+
+int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
+}
+
+int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
+}
+
+int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
+}
+
+int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+       return -1;
+}
+
+int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT);
+}
+
+int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL);
+}
+
+int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev)
+{
+       return -1;
+}
+
+int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev)
+{
+       return -1;
+}
+
+unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
+}
+
+unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
+}
+
+unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
+}
+
+unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
+}
+
+/* Initialize opr function pointers for MFC v5 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
+       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
+       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,
+       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,
+       .release_codec_buffers = s5p_mfc_release_codec_buffers_v5,
+       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,
+       .release_instance_buffer = s5p_mfc_release_instance_buffer_v5,
+       .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,
+       .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,
+       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,
+       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,
+       .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v5,
+       .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v5,
+       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,
+       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,
+       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,
+       .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v5,
+       .init_decode = s5p_mfc_init_decode_v5,
+       .init_encode = s5p_mfc_init_encode_v5,
+       .encode_one_frame = s5p_mfc_encode_one_frame_v5,
+       .try_run = s5p_mfc_try_run_v5,
+       .cleanup_queue = s5p_mfc_cleanup_queue_v5,
+       .clear_int_flags = s5p_mfc_clear_int_flags_v5,
+       .write_info = s5p_mfc_write_info_v5,
+       .read_info = s5p_mfc_read_info_v5,
+       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,
+       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,
+       .get_dspl_status = s5p_mfc_get_dspl_status_v5,
+       .get_dec_status = s5p_mfc_get_dec_status_v5,
+       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,
+       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,
+       .get_consumed_stream = s5p_mfc_get_consumed_stream_v5,
+       .get_int_reason = s5p_mfc_get_int_reason_v5,
+       .get_int_err = s5p_mfc_get_int_err_v5,
+       .err_dec = s5p_mfc_err_dec_v5,
+       .err_dspl = s5p_mfc_err_dspl_v5,
+       .get_img_width = s5p_mfc_get_img_width_v5,
+       .get_img_height = s5p_mfc_get_img_height_v5,
+       .get_dpb_count = s5p_mfc_get_dpb_count_v5,
+       .get_mv_count = s5p_mfc_get_mv_count_v5,
+       .get_inst_no = s5p_mfc_get_inst_no_v5,
+       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,
+       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,
+       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,
+       .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v5,
+       .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v5,
+       .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v5,
+       .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v5,
+       .get_pic_type_top = s5p_mfc_get_pic_type_top_v5,
+       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
+       .get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
+       .get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
+{
+       return &s5p_mfc_ops_v5;
+}
similarity index 76%
rename from drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
index 416ebd7ba35ad3d333d15d2d4f004b31937be366..ffee39a127d52d1dd03b0fdea260dcdc967b4900 100644 (file)
@@ -1,17 +1,22 @@
 /*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.h
  *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * http://www.samsung.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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  */
 
-#ifndef S5P_MFC_SHM_H_
-#define S5P_MFC_SHM_H_
+#ifndef S5P_MFC_OPR_V5_H_
+#define S5P_MFC_OPR_V5_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
 
 enum MFC_SHM_OFS {
        EXTENEDED_DECODE_STATUS = 0x00, /* D */
@@ -71,20 +76,10 @@ enum MFC_SHM_OFS {
        DBG_HISTORY_INPUT1      = 0xD4, /* C */
        DBG_HISTORY_OUTPUT      = 0xD8, /* C */
        HIERARCHICAL_P_QP       = 0xE0, /* E, H.264 */
+       FRAME_PACK_SEI_ENABLE   = 0x168, /* C */
+       FRAME_PACK_SEI_AVAIL    = 0x16c, /* D */
+       FRAME_PACK_SEI_INFO     = 0x17c, /* E */
 };
 
-int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
-
-#define s5p_mfc_write_shm(ctx, x, ofs)         \
-       do {                                    \
-               writel(x, (ctx->shm + ofs));    \
-               wmb();                          \
-       } while (0)
-
-static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
-{
-       rmb();
-       return readl(ctx->shm + ofs);
-}
-
-#endif /* S5P_MFC_SHM_H_ */
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void);
+#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
new file mode 100644 (file)
index 0000000..50b5bee
--- /dev/null
@@ -0,0 +1,1956 @@
+/*
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#undef DEBUG
+
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/firmware.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v6.h"
+
+/* #define S5P_MFC_DEBUG_REGWRITE  */
+#ifdef S5P_MFC_DEBUG_REGWRITE
+#undef writel
+#define writel(v, r)                                                   \
+       do {                                                            \
+               pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v);     \
+       __raw_writel(v, r);                                             \
+       } while (0)
+#endif /* S5P_MFC_DEBUG_REGWRITE */
+
+#define READL(offset)          readl(dev->regs_base + (offset))
+#define WRITEL(data, offset)   writel((data), dev->regs_base + (offset))
+#define OFFSETA(x)             (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
+#define OFFSETB(x)             (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       /* NOP */
+
+       return 0;
+}
+
+/* Release temproary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       /* NOP */
+}
+
+int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+       return -1;
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int mb_width, mb_height;
+
+       mb_width = MB_WIDTH(ctx->img_width);
+       mb_height = MB_HEIGHT(ctx->img_height);
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
+                       ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height),
+                       S5P_FIMV_TMV_BUFFER_ALIGN_V6);
+               ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
+                               S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
+                               S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
+               ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
+                               S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
+                               S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
+               ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
+                                       ctx->img_width, ctx->img_height,
+                                       mb_width, mb_height),
+                                       S5P_FIMV_ME_BUFFER_ALIGN_V6);
+
+               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+                         ctx->luma_dpb_size, ctx->chroma_dpb_size);
+       } else {
+               return -EINVAL;
+       }
+
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size =
+                       ctx->scratch_buf_size +
+                       (ctx->mv_count * ctx->mv_size);
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               ctx->bank1_size = 0;
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_VP8_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->dpb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+       case S5P_MFC_CODEC_H263_ENC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->dpb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2_size = 0;
+               break;
+       default:
+               break;
+       }
+
+       /* Allocate only if memory from bank 1 is necessary */
+       if (ctx->bank1_size > 0) {
+               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+               if (IS_ERR(ctx->bank1_buf)) {
+                       ctx->bank1_buf = 0;
+                       pr_err("Buf alloc for decoding failed (port A)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank1_phys = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       }
+
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->bank1_buf) {
+               vb2_dma_contig_memops.put(ctx->bank1_buf);
+               ctx->bank1_buf = 0;
+               ctx->bank1_phys = 0;
+               ctx->bank1_size = 0;
+       }
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+       mfc_debug_enter();
+
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               ctx->ctx.size = buf_size->h264_dec_ctx;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+       case S5P_MFC_CODEC_H263_DEC:
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+       case S5P_MFC_CODEC_MPEG2_DEC:
+       case S5P_MFC_CODEC_VP8_DEC:
+               ctx->ctx.size = buf_size->other_dec_ctx;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->ctx.size = buf_size->h264_enc_ctx;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+       case S5P_MFC_CODEC_H263_ENC:
+               ctx->ctx.size = buf_size->other_enc_ctx;
+               break;
+       default:
+               ctx->ctx.size = 0;
+               mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
+               break;
+       }
+
+       ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
+       if (IS_ERR(ctx->ctx.alloc)) {
+               mfc_err("Allocating context buffer failed.\n");
+               return PTR_ERR(ctx->ctx.alloc);
+       }
+
+       ctx->ctx.dma = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+
+       ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+       if (!ctx->ctx.virt) {
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.dma = 0;
+               ctx->ctx.virt = NULL;
+
+               mfc_err("Remapping context buffer failed.\n");
+               return -ENOMEM;
+       }
+
+       memset(ctx->ctx.virt, 0, ctx->ctx.size);
+       wmb();
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug_enter();
+
+       if (ctx->ctx.alloc) {
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.dma = 0;
+               ctx->ctx.virt = NULL;
+       }
+
+       mfc_debug_leave();
+}
+
+/* Allocate context buffers for SYS_INIT */
+int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+       mfc_debug_enter();
+
+       dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx);
+       if (IS_ERR(dev->ctx_buf.alloc)) {
+               mfc_err("Allocating DESC buffer failed.\n");
+               return PTR_ERR(dev->ctx_buf.alloc);
+       }
+
+       dev->ctx_buf.dma = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+                       dev->ctx_buf.alloc);
+
+       dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc);
+       if (!dev->ctx_buf.virt) {
+               vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+               dev->ctx_buf.alloc = NULL;
+               dev->ctx_buf.dma = 0;
+
+               mfc_err("Remapping DESC buffer failed.\n");
+               return -ENOMEM;
+       }
+
+       memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
+       wmb();
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Release context buffers for SYS_INIT */
+void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+       if (dev->ctx_buf.alloc) {
+               vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+               dev->ctx_buf.alloc = NULL;
+               dev->ctx_buf.dma = 0;
+               dev->ctx_buf.virt = NULL;
+       }
+}
+
+static int calc_plane(int width, int height)
+{
+       int mbX, mbY;
+
+       mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+       mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6);
+
+       if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6)
+               mbY = (mbY + 1) / 2 * 2;
+
+       return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) *
+               (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+}
+
+void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
+{
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
+       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
+       mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
+                       "buffer dimensions: %dx%d\n", ctx->img_width,
+                       ctx->img_height, ctx->buf_width, ctx->buf_height);
+
+       ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
+       ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+               ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
+                               ctx->img_height);
+               ctx->mv_size = ALIGN(ctx->mv_size, 16);
+       } else {
+               ctx->mv_size = 0;
+       }
+}
+
+void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int mb_width, mb_height;
+
+       mb_width = MB_WIDTH(ctx->img_width);
+       mb_height = MB_HEIGHT(ctx->img_height);
+
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
+       ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
+       ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr,
+                 unsigned int start_num_byte, unsigned int strm_size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
+
+       mfc_debug_enter();
+       mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
+               "buf_size: 0x%08x (%d)\n",
+               ctx->inst_no, buf_addr, strm_size, strm_size);
+       WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6);
+       WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6);
+       WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE_V6);
+       WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int frame_size, i;
+       unsigned int frame_size_ch, frame_size_mv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1;
+       int buf_size1;
+       int align_gap;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+
+       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+       mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
+       mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
+
+       WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB_V6);
+       WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6);
+       WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6);
+
+       WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6);
+       WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6);
+       buf_addr1 += ctx->scratch_buf_size;
+       buf_size1 -= ctx->scratch_buf_size;
+
+       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){
+               WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6);
+               WRITEL(ctx->mv_count, S5P_FIMV_D_NUM_MV_V6);
+       }
+
+       frame_size = ctx->luma_size;
+       frame_size_ch = ctx->chroma_size;
+       frame_size_mv = ctx->mv_size;
+       mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
+                       frame_size, frame_size_ch, frame_size_mv);
+
+       for (i = 0; i < ctx->total_dpb_count; i++) {
+               /* Bank2 */
+               mfc_debug(2, "Luma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.luma);
+               WRITEL(ctx->dst_bufs[i].cookie.raw.luma,
+                               S5P_FIMV_D_LUMA_DPB_V6 + i * 4);
+               mfc_debug(2, "\tChroma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.chroma);
+               WRITEL(ctx->dst_bufs[i].cookie.raw.chroma,
+                               S5P_FIMV_D_CHROMA_DPB_V6 + i * 4);
+       }
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+               for (i = 0; i < ctx->mv_count; i++) {
+                       /* To test alignment */
+                       align_gap = buf_addr1;
+                       buf_addr1 = ALIGN(buf_addr1, 16);
+                       align_gap = buf_addr1 - align_gap;
+                       buf_size1 -= align_gap;
+
+                       mfc_debug(2, "\tBuf1: %x, size: %d\n",
+                                       buf_addr1, buf_size1);
+                       WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER_V6 + i * 4);
+                       buf_addr1 += frame_size_mv;
+                       buf_size1 -= frame_size_mv;
+               }
+       }
+
+       mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n",
+                       buf_addr1, buf_size1, ctx->total_dpb_count);
+       if (buf_size1 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated.\n");
+               return -ENOMEM;
+       }
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+       mfc_debug(2, "After setting buffers.\n");
+       return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */
+       WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6);
+
+       mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d",
+               addr, size);
+
+       return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */
+       WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6);
+
+       mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr);
+       mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
+}
+
+void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long enc_recon_y_addr, enc_recon_c_addr;
+
+       *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6);
+       *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6);
+
+       enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6);
+       enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6);
+
+       mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr);
+       mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1, buf_size1;
+       int i;
+
+       mfc_debug_enter();
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+
+       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+
+       for (i = 0; i < ctx->dpb_count; i++) {
+               WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i));
+               buf_addr1 += ctx->luma_dpb_size;
+               WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i));
+               buf_addr1 += ctx->chroma_dpb_size;
+               WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i));
+               buf_addr1 += ctx->me_buffer_size;
+               buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
+                       ctx->me_buffer_size);
+       }
+
+       WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6);
+       WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6);
+       buf_addr1 += ctx->scratch_buf_size;
+       buf_size1 -= ctx->scratch_buf_size;
+
+       WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0_V6);
+       buf_addr1 += ctx->tmv_buffer_size >> 1;
+       WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1_V6);
+       buf_addr1 += ctx->tmv_buffer_size >> 1;
+       buf_size1 -= ctx->tmv_buffer_size;
+
+       mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n",
+                       buf_addr1, buf_size1, ctx->dpb_count);
+       if (buf_size1 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated.\n");
+               return -ENOMEM;
+       }
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE_V6);
+       if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
+       } else if (ctx->slice_mode ==
+                       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+               WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
+       } else {
+               WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
+               WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       /* width */
+       WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH_V6); /* 16 align */
+       /* height */
+       WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT_V6); /* 16 align */
+
+       /* cropped width */
+       WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6);
+       /* cropped height */
+       WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
+       /* cropped offset */
+       WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET_V6);
+
+       /* pictype : IDR period */
+       reg = 0;
+       reg |= p->gop_size & 0xFFFF;
+       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       ctx->slice_mode = p->slice_mode;
+       reg = 0;
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               reg |= (0x1 << 3);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               ctx->slice_size.mb = p->slice_mb;
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+               reg |= (0x1 << 3);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               ctx->slice_size.bits = p->slice_bit;
+       } else {
+               reg &= ~(0x1 << 3);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+       }
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       /* cyclic intra refresh */
+       WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE_V6);
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       if (p->intra_refresh_mb == 0)
+               reg &= ~(0x1 << 4);
+       else
+               reg |= (0x1 << 4);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       reg &= ~(0x1 << 9);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+               reg &= ~(0x1 << 7);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+               reg &= ~(0x1 << 7);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+               reg |= (0x1 << 7);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+       }
+
+       /* memory structure recon. frame */
+       /* 0: Linear, 1: 2D tiled */
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       reg |= (0x1 << 8);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* padding control & value */
+       WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL_V6);
+       if (p->pad) {
+               reg = 0;
+               /** enable */
+               reg |= (1 << 31);
+               /** cr value */
+               reg |= ((p->pad_cr & 0xFF) << 16);
+               /** cb value */
+               reg |= ((p->pad_cb & 0xFF) << 8);
+               /** y value */
+               reg |= p->pad_luma & 0xFF;
+               WRITEL(reg, S5P_FIMV_E_PADDING_CTRL_V6);
+       }
+
+       /* rate control config. */
+       reg = 0;
+       /* frame-level rate control */
+       reg |= ((p->rc_frame & 0x1) << 9);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* bit rate */
+       if (p->rc_frame)
+               WRITEL(p->rc_bitrate,
+                       S5P_FIMV_E_RC_BIT_RATE_V6);
+       else
+               WRITEL(1, S5P_FIMV_E_RC_BIT_RATE_V6);
+
+       /* reaction coefficient */
+       if (p->rc_frame) {
+               if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
+                       WRITEL(1, S5P_FIMV_E_RC_RPARAM_V6);
+               else                                      /* loose CBR */
+                       WRITEL(2, S5P_FIMV_E_RC_RPARAM_V6);
+       }
+
+       /* seq header ctrl */
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       reg &= ~(0x1 << 2);
+       reg |= ((p->seq_hdr_mode & 0x1) << 2);
+
+       /* frame skip mode */
+       reg &= ~(0x3);
+       reg |= (p->frame_skip_mode & 0x3);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* 'DROP_CONTROL_ENABLE', disable */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       reg &= ~(0x1 << 10);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* setting for MV range [16, 256] */
+       reg = 0;
+       reg &= ~(0x3FFF);
+       reg = 256;
+       WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE_V6);
+
+       reg = 0;
+       reg &= ~(0x3FFF);
+       reg = 256;
+       WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION_V6);
+       WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR_V6);
+       WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE_V6);
+       WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL_V6);
+       WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE_V6);
+       WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT_V6);
+       WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6);
+       WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+       unsigned int reg = 0;
+       int i;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
+       reg &= ~(0x3 << 16);
+       reg |= ((p->num_b_frame & 0x3) << 16);
+       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg |= ((p_h264->level & 0xFF) << 8);
+       /** profile - 0 ~ 3 */
+       reg |= p_h264->profile & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+       /* rate control config. */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h264->rc_frame_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_h264->rc_min_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+       /* other QPs */
+       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_h264->rc_frame_qp & 0x3F;
+               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               WRITEL(p_h264->cpb_size & 0xFFFF,
+                               S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+               if (p->rc_frame)
+                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+       }
+
+       /* interlace */
+       reg = 0;
+       reg |= ((p_h264->interlace & 0x1) << 3);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* height */
+       if (p_h264->interlace) {
+               WRITEL(ctx->img_height >> 1,
+                               S5P_FIMV_E_FRAME_HEIGHT_V6); /* 32 align */
+               /* cropped height */
+               WRITEL(ctx->img_height >> 1,
+                               S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
+       }
+
+       /* loop filter ctrl */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x3 << 1);
+       reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* loopfilter alpha offset */
+       if (p_h264->loop_filter_alpha < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_h264->loop_filter_alpha & 0xF);
+       }
+       WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6);
+
+       /* loopfilter beta offset */
+       if (p_h264->loop_filter_beta < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_h264->loop_filter_beta) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_h264->loop_filter_beta & 0xF);
+       }
+       WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6);
+
+       /* entropy coding mode */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1);
+       reg |= p_h264->entropy_mode & 0x1;
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* number of ref. picture */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 7);
+       reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* 8x8 transform enable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x3 << 12);
+       reg |= ((p_h264->_8x8_transform & 0x3) << 12);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* macroblock adaptive scaling features */
+       WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG_V6);
+       if (p->rc_mb) {
+               reg = 0;
+               /** dark region */
+               reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
+               /** smooth region */
+               reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
+               /** static region */
+               reg |= ((p_h264->rc_mb_static & 0x1) << 1);
+               /** high activity region */
+               reg |= p_h264->rc_mb_activity & 0x1;
+               WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG_V6);
+       }
+
+       /* aspect ratio VUI */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 5);
+       reg |= ((p_h264->vui_sar & 0x1) << 5);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO_V6);
+       WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR_V6);
+       if (p_h264->vui_sar) {
+               /* aspect ration IDC */
+               reg = 0;
+               reg |= p_h264->vui_sar_idc & 0xFF;
+               WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO_V6);
+               if (p_h264->vui_sar_idc == 0xFF) {
+                       /* extended SAR */
+                       reg = 0;
+                       reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
+                       reg |= p_h264->vui_ext_sar_height & 0xFFFF;
+                       WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR_V6);
+               }
+       }
+
+       /* intra picture period for H.264 open GOP */
+       /* control */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 4);
+       reg |= ((p_h264->open_gop & 0x1) << 4);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+       /* value */
+       WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD_V6);
+       if (p_h264->open_gop) {
+               reg = 0;
+               reg |= p_h264->open_gop_size & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD_V6);
+       }
+
+       /* 'WEIGHTED_BI_PREDICTION' for B is disable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x3 << 9);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 14);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* ASO */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 6);
+       reg |= ((p_h264->aso & 0x1) << 6);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* hier qp enable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 8);
+       reg |= ((p_h264->open_gop & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+       reg = 0;
+       if (p_h264->hier_qp && p_h264->hier_qp_layer) {
+               reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
+               reg |= p_h264->hier_qp_layer & 0x7;
+               WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
+               /* QP value for each layer */
+               for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++)
+                       WRITEL(p_h264->hier_qp_layer_qp[i],
+                               S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 +
+                               i * 4);
+       }
+       /* number of coding layer should be zero when hierarchical is disable */
+       WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
+
+       /* frame packing SEI generation */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 25);
+       reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+       if (p_h264->sei_frame_packing) {
+               reg = 0;
+               /** current frame0 flag */
+               reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
+               /** arrangement type */
+               reg |= p_h264->sei_fp_arrangement_type & 0x3;
+               WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6);
+       }
+
+       if (p_h264->fmo) {
+               switch (p_h264->fmo_map_type) {
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+                       if (p_h264->fmo_slice_grp > 4)
+                               p_h264->fmo_slice_grp = 4;
+                       for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
+                               WRITEL(p_h264->fmo_run_len[i] - 1,
+                               S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 +
+                               i * 4);
+                       break;
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+                       if (p_h264->fmo_slice_grp > 4)
+                               p_h264->fmo_slice_grp = 4;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
+                       if (p_h264->fmo_slice_grp > 2)
+                               p_h264->fmo_slice_grp = 2;
+                       WRITEL(p_h264->fmo_chg_dir & 0x1,
+                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6);
+                       /* the valid range is 0 ~ number of macroblocks -1 */
+                       WRITEL(p_h264->fmo_chg_rate,
+                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6);
+                       break;
+               default:
+                       mfc_err("Unsupported map type for FMO: %d\n",
+                                       p_h264->fmo_map_type);
+                       p_h264->fmo_map_type = 0;
+                       p_h264->fmo_slice_grp = 1;
+                       break;
+               }
+
+               WRITEL(p_h264->fmo_map_type,
+                               S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6);
+               WRITEL(p_h264->fmo_slice_grp - 1,
+                               S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
+       } else {
+               WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
+       reg &= ~(0x3 << 16);
+       reg |= ((p->num_b_frame & 0x3) << 16);
+       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg |= ((p_mpeg4->level & 0xFF) << 8);
+       /** profile - 0 ~ 1 */
+       reg |= p_mpeg4->profile & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+       /* rate control config. */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_frame_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_mpeg4->rc_min_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+       /* other QPs */
+       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_mpeg4->rc_frame_qp & 0x3F;
+               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+               if (p->rc_frame)
+                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+       }
+
+       /* Disable HEC */
+       WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS_V6);
+       WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* profile & level */
+       reg = 0;
+       /** profile */
+       reg |= (0x1 << 4);
+       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+       /* rate control config. */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_frame_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_h263->rc_min_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+       /* other QPs */
+       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_h263->rc_frame_qp & 0x3F;
+               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+               if (p->rc_frame)
+                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int reg = 0;
+       int fmo_aso_ctrl = 0;
+
+       mfc_debug_enter();
+       mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no,
+                       S5P_FIMV_CH_SEQ_HEADER_V6);
+       mfc_debug(2, "BUFs: %08x %08x %08x\n",
+                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
+                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
+                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6));
+
+       /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
+       reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6);
+
+       /* When user sets desplay_delay to 0,
+        * It works as "display_delay enable" and delay set to 0.
+        * If user wants display_delay disable, It should be
+        * set to negative value. */
+       if (ctx->display_delay >= 0) {
+               reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6);
+               WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6);
+       }
+       /* Setup loop filter, for decoding this is only valid for MPEG4 */
+       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) {
+               mfc_debug(2, "Set loop filter to: %d\n",
+                               ctx->loop_filter_mpeg4);
+               reg |= (ctx->loop_filter_mpeg4 <<
+                               S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6);
+       }
+       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
+               reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
+
+       WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6);
+
+       /* 0: NV12(CbCr), 1: NV21(CrCb) */
+       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
+               WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
+       else
+               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+
+       /* sei parse */
+       WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6);
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+       if (flush)
+               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
+       else
+               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
+       WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
+                       enum s5p_mfc_decode_arg last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       WRITEL(ctx->dec_dst_flag, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6);
+       WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE_V6);
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case 0:
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_CH_FRAME_START_V6, NULL);
+               break;
+       case 1:
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_CH_LAST_FRAME_V6, NULL);
+               break;
+       default:
+               mfc_err("Unsupported last frame arg.\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "Decoding a usual frame.\n");
+       return 0;
+}
+
+int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+               s5p_mfc_set_enc_params_h263(ctx);
+       else {
+               mfc_err("Unknown codec for encoding (%x).\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+       return 0;
+}
+
+int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+       int i;
+
+       if (p_h264->aso) {
+               for (i = 0; i < 8; i++)
+                       WRITEL(p_h264->aso_slice_order[i],
+                               S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 + i * 4);
+       }
+       return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_debug(2, "++\n");
+
+       /* memory structure cur. frame */
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_h264_set_aso_slice_order_v6(ctx);
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_FRAME_START_V6, NULL);
+
+       mfc_debug(2, "--\n");
+
+       return 0;
+}
+
+static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+       int new_ctx;
+       int cnt;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
+                                                       dev->ctx_work_bits);
+       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+       cnt = 0;
+       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+               cnt++;
+               if (cnt > MFC_NUM_CONTEXTS) {
+                       /* No contexts to run */
+                       spin_unlock_irqrestore(&dev->condlock, flags);
+                       return -EAGAIN;
+               }
+       }
+       spin_unlock_irqrestore(&dev->condlock, flags);
+       return new_ctx;
+}
+
+static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+                       vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_decode_one_frame_v6(ctx, 1);
+}
+
+static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       unsigned long flags;
+       int last_frame = 0;
+       unsigned int index;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+                       ctx->consumed_stream,
+                       temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       index = temp_vb->b->v4l2_buf.index;
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+               last_frame = 1;
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               ctx->state = MFCINST_FINISHING;
+       }
+       s5p_mfc_decode_one_frame_v6(ctx, last_frame);
+
+       return 0;
+}
+
+static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       /*
+       unsigned int src_y_size, src_c_size;
+       */
+       unsigned int dst_size;
+       unsigned int index;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "no src buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+
+       if (list_empty(&ctx->dst_queue)) {
+               mfc_debug(2, "no dst buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+
+       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       src_mb->flags |= MFC_BUF_FLAG_USED;
+       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
+
+       mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr);
+       mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr);
+
+       s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_mb->flags |= MFC_BUF_FLAG_USED;
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+
+       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       index = src_mb->b->v4l2_buf.index;
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_encode_one_frame_v6(ctx);
+
+       return 0;
+}
+
+static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+
+       /* Initializing decoding - parsing header */
+       spin_lock_irqsave(&dev->irqlock, flags);
+       mfc_debug(2, "Preparing to init decoding.\n");
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
+                       temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_decode_v6(ctx);
+}
+
+static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_encode_v6(ctx);
+}
+
+static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+       /* Header was parsed now start processing
+        * First set the output frame buffers
+        * s5p_mfc_alloc_dec_buffers(ctx); */
+
+       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+               mfc_err("It seems that not all destionation buffers were\n"
+                       "mmaped.MFC requires that all destination are mmaped\n"
+                       "before starting processing.\n");
+               return -EAGAIN;
+       }
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem.\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+
+       ret = s5p_mfc_alloc_codec_buffers_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to allocate encoding buffers.\n");
+               return -ENOMEM;
+       }
+
+       /* Header was generated now starting processing
+        * First set the reference frame buffers
+        */
+       if (ctx->capture_state != QUEUE_BUFS_REQUESTED) {
+               mfc_err("It seems that destionation buffers were not\n"
+                       "requested.MFC requires that header should be generated\n"
+                       "before allocating codec buffer.\n");
+               return -EAGAIN;
+       }
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem.\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int new_ctx;
+       unsigned int ret = 0;
+
+       mfc_debug(1, "Try run dev: %p\n", dev);
+
+       /* Check whether hardware is not running */
+       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(1, "Couldn't lock HW.\n");
+               return;
+       }
+
+       /* Choose the context to run */
+       new_ctx = s5p_mfc_get_new_ctx(dev);
+       if (new_ctx < 0) {
+               /* No contexts to run */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+                       mfc_err("Failed to unlock hardware.\n");
+                       return;
+               }
+
+               mfc_debug(1, "No ctx is scheduled to be run.\n");
+               return;
+       }
+
+       mfc_debug(1, "New context: %d\n", new_ctx);
+       ctx = dev->ctx[new_ctx];
+       mfc_debug(1, "Seting new context to %p\n", ctx);
+       /* Got context to run in ctx */
+       mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
+               ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt);
+       mfc_debug(1, "ctx->state=%d\n", ctx->state);
+       /* Last frame has already been sent to MFC
+        * Now obtaining frames from MFC buffer */
+
+       s5p_mfc_clock_on();
+       if (ctx->type == MFCINST_DECODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_dec_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_run_init_dec_buffers(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_INIT:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_FLUSH:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_END:
+                       mfc_debug(2, "Finished remaining frames after resolution change.\n");
+                       ctx->capture_state = QUEUE_FREE;
+                       mfc_debug(2, "Will re-init the codec`.\n");
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_enc(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED: /* Only for MFC6.x */
+                       ret = s5p_mfc_run_init_enc_buffers(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else {
+               mfc_err("invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Free hardware lock */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       mfc_err("Failed to unlock hardware.\n");
+
+               /* This is in deed imporant, as no operation has been
+                * scheduled, reduce the clock count as no one will
+                * ever do this, because no interrupt related to this try_run
+                * will ever come from hardware. */
+               s5p_mfc_clock_off();
+       }
+}
+
+
+void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
+{
+       struct s5p_mfc_buf *b;
+       int i;
+
+       while (!list_empty(lh)) {
+               b = list_entry(lh->next, struct s5p_mfc_buf, list);
+               for (i = 0; i < b->b->num_planes; i++)
+                       vb2_set_plane_payload(b->b, i, 0);
+               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+               list_del(&b->list);
+       }
+}
+
+void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6);
+}
+
+void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
+               unsigned int ofs)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_clock_on();
+       WRITEL(data, ofs);
+       s5p_mfc_clock_off();
+}
+
+unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+
+       s5p_mfc_clock_on();
+       ret = READL(ofs);
+       s5p_mfc_clock_off();
+
+       return ret;
+}
+
+int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+}
+
+int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+}
+
+int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6);
+}
+
+int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6);
+}
+
+int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) &
+               S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
+{
+       return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) &
+               S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6);
+}
+
+int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) &
+               S5P_FIMV_RISC2HOST_CMD_MASK;
+}
+
+int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6);
+}
+
+int s5p_mfc_err_dec_v6(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6;
+}
+
+int s5p_mfc_err_dspl_v6(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6;
+}
+
+int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6);
+}
+
+int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6);
+}
+
+int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6);
+}
+
+int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6);
+}
+
+int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6);
+}
+
+int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6);
+}
+
+int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6);
+}
+
+int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6);
+}
+
+int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6);
+}
+
+int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx)
+{
+       return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6);
+}
+
+int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6);
+}
+
+int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6);
+}
+
+unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6);
+}
+
+unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6);
+}
+
+unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6);
+}
+
+unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6);
+}
+
+/* Initialize opr function pointers for MFC v6 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = {
+       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6,
+       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6,
+       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6,
+       .release_codec_buffers = s5p_mfc_release_codec_buffers_v6,
+       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6,
+       .release_instance_buffer = s5p_mfc_release_instance_buffer_v6,
+       .alloc_dev_context_buffer =
+               s5p_mfc_alloc_dev_context_buffer_v6,
+       .release_dev_context_buffer =
+               s5p_mfc_release_dev_context_buffer_v6,
+       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6,
+       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6,
+       .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v6,
+       .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v6,
+       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6,
+       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6,
+       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6,
+       .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v6,
+       .init_decode = s5p_mfc_init_decode_v6,
+       .init_encode = s5p_mfc_init_encode_v6,
+       .encode_one_frame = s5p_mfc_encode_one_frame_v6,
+       .try_run = s5p_mfc_try_run_v6,
+       .cleanup_queue = s5p_mfc_cleanup_queue_v6,
+       .clear_int_flags = s5p_mfc_clear_int_flags_v6,
+       .write_info = s5p_mfc_write_info_v6,
+       .read_info = s5p_mfc_read_info_v6,
+       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6,
+       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6,
+       .get_dspl_status = s5p_mfc_get_dspl_status_v6,
+       .get_dec_status = s5p_mfc_get_dec_status_v6,
+       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6,
+       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6,
+       .get_consumed_stream = s5p_mfc_get_consumed_stream_v6,
+       .get_int_reason = s5p_mfc_get_int_reason_v6,
+       .get_int_err = s5p_mfc_get_int_err_v6,
+       .err_dec = s5p_mfc_err_dec_v6,
+       .err_dspl = s5p_mfc_err_dspl_v6,
+       .get_img_width = s5p_mfc_get_img_width_v6,
+       .get_img_height = s5p_mfc_get_img_height_v6,
+       .get_dpb_count = s5p_mfc_get_dpb_count_v6,
+       .get_mv_count = s5p_mfc_get_mv_count_v6,
+       .get_inst_no = s5p_mfc_get_inst_no_v6,
+       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6,
+       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6,
+       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6,
+       .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v6,
+       .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v6,
+       .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v6,
+       .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v6,
+       .get_pic_type_top = s5p_mfc_get_pic_type_top_v6,
+       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6,
+       .get_crop_info_h = s5p_mfc_get_crop_info_h_v6,
+       .get_crop_info_v = s5p_mfc_get_crop_info_v_v6,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void)
+{
+       return &s5p_mfc_ops_v6;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
new file mode 100644 (file)
index 0000000..ab164ef
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef S5P_MFC_OPR_V6_H_
+#define S5P_MFC_OPR_V6_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
+
+#define MFC_CTRL_MODE_CUSTOM   MFC_CTRL_MODE_SFR
+
+#define MB_WIDTH(x_size)               DIV_ROUND_UP(x_size, 16)
+#define MB_HEIGHT(y_size)              DIV_ROUND_UP(y_size, 16)
+#define S5P_MFC_DEC_MV_SIZE_V6(x, y)   (MB_WIDTH(x) * \
+                                       (((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
+
+/* Definition */
+#define ENC_MULTI_SLICE_MB_MAX         ((1 << 30) - 1)
+#define ENC_MULTI_SLICE_BIT_MIN                2800
+#define ENC_INTRA_REFRESH_MB_MAX       ((1 << 18) - 1)
+#define ENC_VBV_BUF_SIZE_MAX           ((1 << 30) - 1)
+#define ENC_H264_LOOP_FILTER_AB_MIN    -12
+#define ENC_H264_LOOP_FILTER_AB_MAX    12
+#define ENC_H264_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
+#define ENC_H263_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
+#define ENC_H264_PROFILE_MAX           3
+#define ENC_H264_LEVEL_MAX             42
+#define ENC_MPEG4_VOP_TIME_RES_MAX     ((1 << 16) - 1)
+#define FRAME_DELTA_H264_H263          1
+#define TIGHT_CBR_MAX                  10
+
+/* Definitions for shared memory compatibility */
+#define PIC_TIME_TOP_V6                S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6
+#define PIC_TIME_BOT_V6                S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6
+#define CROP_INFO_H_V6         S5P_FIMV_D_DISPLAY_CROP_INFO1_V6
+#define CROP_INFO_V_V6         S5P_FIMV_D_DISPLAY_CROP_INFO2_V6
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void);
+#endif /* S5P_MFC_OPR_V6_H_ */
index 0503d14ac94e141931ca250f744f82db4476822c..367db755228932f410c6157e06f67d8ac00b477f 100644 (file)
@@ -20,7 +20,6 @@
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_pm.h"
 
-#define MFC_CLKNAME            "sclk_mfc"
 #define MFC_GATE_CLK_NAME      "mfc"
 
 #define CLK_DEBUG
@@ -51,7 +50,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
                goto err_p_ip_clk;
        }
 
-       pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME);
+       pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name);
        if (IS_ERR(pm->clock)) {
                mfc_err("Failed to get MFC clock\n");
                ret = PTR_ERR(pm->clock);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
deleted file mode 100644 (file)
index b5933d2..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifdef CONFIG_ARCH_EXYNOS4
-#include <linux/dma-mapping.h>
-#endif
-#include <linux/io.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-
-int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
-
-       ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
-                                                       SHARED_BUF_SIZE);
-       if (IS_ERR(ctx->shm_alloc)) {
-               mfc_err("failed to allocate shared memory\n");
-               return PTR_ERR(ctx->shm_alloc);
-       }
-       /* shm_ofs only keeps the offset from base (port a) */
-       ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
-                                                               - dev->bank1;
-       BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
-       if (!ctx->shm) {
-               vb2_dma_contig_memops.put(ctx->shm_alloc);
-               ctx->shm_ofs = 0;
-               ctx->shm_alloc = NULL;
-               mfc_err("failed to virt addr of shared memory\n");
-               return -ENOMEM;
-       }
-       memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
-       wmb();
-       return 0;
-}
-
index 403d7f17bfab1277adba82ed59d0650f99dd16aa..9fd9d1c5b218a5b51ff0522b9969db06e795706c 100644 (file)
@@ -1376,6 +1376,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
        __u32 pixfmt = pix->pixelformat;
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
+       struct mx2_fmt_cfg *emma_prp;
        unsigned int width_limit;
        int ret;
 
@@ -1438,12 +1439,11 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
                __func__, pcdev->s_width, pcdev->s_height);
 
        /* If the sensor does not support image size try PrP resizing */
-       pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code,
+       emma_prp = mx27_emma_prp_get_format(xlate->code,
                                                   xlate->host_fmt->fourcc);
 
-       memset(pcdev->resizing, 0, sizeof(pcdev->resizing));
        if ((mf.width != pix->width || mf.height != pix->height) &&
-               pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
+               emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
                if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0)
                        dev_dbg(icd->parent, "%s: can't resize\n", __func__);
        }
@@ -1655,6 +1655,7 @@ static int __devinit mx27_camera_emma_init(struct platform_device *pdev)
        irq_emma = platform_get_irq(pdev, 1);
        if (!res_emma || !irq_emma) {
                dev_err(pcdev->dev, "no EMMA resources\n");
+               err = -ENODEV;
                goto out;
        }
 
index 3be92944f8e7efd7e44d8ff0f7acf37c8f8af084..d3f0b84e2d7086e24b4e75a863e34d23464cda15 100644 (file)
@@ -950,11 +950,11 @@ static int soc_camera_s_selection(struct file *file, void *fh,
 
        /* In all these cases cropping emulation will not help */
        if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-           (s->target != V4L2_SEL_TGT_COMPOSE_ACTIVE &&
-            s->target != V4L2_SEL_TGT_CROP_ACTIVE))
+           (s->target != V4L2_SEL_TGT_COMPOSE &&
+            s->target != V4L2_SEL_TGT_CROP))
                return -EINVAL;
 
-       if (s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+       if (s->target == V4L2_SEL_TGT_COMPOSE) {
                /* No output size change during a running capture! */
                if (is_streaming(ici, icd) &&
                    (icd->user_width != s->r.width ||
@@ -974,7 +974,7 @@ static int soc_camera_s_selection(struct file *file, void *fh,
 
        ret = ici->ops->set_selection(icd, s);
        if (!ret &&
-           s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+           s->target == V4L2_SEL_TGT_COMPOSE) {
                icd->user_width = s->r.width;
                icd->user_height = s->r.height;
                if (!icd->streamer)
@@ -1184,7 +1184,8 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        sd->grp_id = soc_camera_grp_id(icd);
        v4l2_set_subdev_hostdata(sd, icd);
 
-       if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL))
+       ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL);
+       if (ret < 0)
                goto ectrl;
 
        /* At this point client .probe() should have run already */
@@ -1529,12 +1530,11 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
 {
        struct soc_camera_link *icl = pdev->dev.platform_data;
        struct soc_camera_device *icd;
-       int ret;
 
        if (!icl)
                return -EINVAL;
 
-       icd = kzalloc(sizeof(*icd), GFP_KERNEL);
+       icd = devm_kzalloc(&pdev->dev, sizeof(*icd), GFP_KERNEL);
        if (!icd)
                return -ENOMEM;
 
@@ -1543,19 +1543,10 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
        icd->pdev = &pdev->dev;
        platform_set_drvdata(pdev, icd);
 
-       ret = soc_camera_device_register(icd);
-       if (ret < 0)
-               goto escdevreg;
-
        icd->user_width         = DEFAULT_WIDTH;
        icd->user_height        = DEFAULT_HEIGHT;
 
-       return 0;
-
-escdevreg:
-       kfree(icd);
-
-       return ret;
+       return soc_camera_device_register(icd);
 }
 
 /*
@@ -1572,8 +1563,6 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
 
        list_del(&icd->list);
 
-       kfree(icd);
-
        return 0;
 }
 
@@ -1586,18 +1575,7 @@ static struct platform_driver __refdata soc_camera_pdrv = {
        },
 };
 
-static int __init soc_camera_init(void)
-{
-       return platform_driver_register(&soc_camera_pdrv);
-}
-
-static void __exit soc_camera_exit(void)
-{
-       platform_driver_unregister(&soc_camera_pdrv);
-}
-
-module_init(soc_camera_init);
-module_exit(soc_camera_exit);
+module_platform_driver(soc_camera_pdrv);
 
 MODULE_DESCRIPTION("Image capture bus driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
index e5024cfd27a713ffa77403471275b62e6ba264e3..4ef55ec8045e432fcc9576e130e902bc92446bed 100644 (file)
@@ -308,7 +308,7 @@ static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
                                        READCHAN_BLERD) >> 10;
                        rds = radio->registers[RDSD];
                        break;
-               };
+               }
 
                /* Fill the V4L2 RDS buffer */
                put_unaligned_le16(rds, &tmpbuf);
index be076f7181e728b1ab177ca340290a2c1ae29dc4..62f3edec39bc262022f5b6310b19a9efb3502497 100644 (file)
@@ -446,7 +446,7 @@ static void si470x_int_in_callback(struct urb *urb)
                                                READCHAN_BLERD) >> 10;
                                rds = radio->registers[RDSD];
                                break;
-                       };
+                       }
 
                        /* Fill the V4L2 RDS buffer */
                        put_unaligned_le16(rds, &tmpbuf);
index a9e6d17015ef545cc11aa3fc4562acd403a41683..e3079c142c5f87af79ee9e11a4268b7ae46c5283 100644 (file)
@@ -1009,7 +1009,7 @@ static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
 
        default:
                rval = -EINVAL;
-       };
+       }
 
        return rval;
 }
@@ -1081,7 +1081,7 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
        default:
                rval = -EINVAL;
                break;
-       };
+       }
 
 exit:
        return rval;
@@ -1130,7 +1130,7 @@ static int si4713_write_econtrol_tune(struct si4713_device *sdev,
        default:
                rval = -EINVAL;
                goto unlock;
-       };
+       }
 
        if (sdev->power_state)
                rval = si4713_tx_tune_power(sdev, power, antcap);
@@ -1420,7 +1420,7 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
        default:
                rval = -EINVAL;
                break;
-       };
+       }
 
 exit:
        return rval;
@@ -1473,7 +1473,7 @@ static int si4713_read_econtrol_tune(struct si4713_device *sdev,
                break;
        default:
                rval = -EINVAL;
-       };
+       }
 
 unlock:
        mutex_unlock(&sdev->mutex);
@@ -1698,7 +1698,7 @@ static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
        default:
                rval = -EINVAL;
                break;
-       };
+       }
 
        return rval;
 }
index 647dd951b0e8c31772e66bcdc333a54c3f839574..d05ac15b5de48673cafbd9825afa8925c3a3c5e7 100644 (file)
@@ -881,10 +881,13 @@ static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask)
 static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier)
 {
        struct ene_device *dev = rdev->priv;
-       u32 period = 2000000 / carrier;
+       u32 period;
 
        dbg("TX: attempt to set tx carrier to %d kHz", carrier);
+       if (carrier == 0)
+               return -EINVAL;
 
+       period = 2000000 / carrier;
        if (period && (period > ENE_CIRMOD_PRD_MAX ||
                        period < ENE_CIRMOD_PRD_MIN)) {
 
index 1e4c68a5cecfedfa24c2053dd1b67db88f83e5a3..51d7057aca0443414f8325e119a1da81a2e03840 100644 (file)
@@ -28,6 +28,7 @@
 #include <media/rc-core.h>
 
 #define DRIVER_NAME "iguanair"
+#define BUF_SIZE 152
 
 struct iguanair {
        struct rc_dev *rc;
@@ -35,26 +36,23 @@ struct iguanair {
        struct device *dev;
        struct usb_device *udev;
 
-       int pipe_out;
        uint16_t version;
        uint8_t bufsize;
+       uint8_t cycle_overhead;
 
        struct mutex lock;
 
        /* receiver support */
        bool receiver_on;
-       dma_addr_t dma_in;
+       dma_addr_t dma_in, dma_out;
        uint8_t *buf_in;
-       struct urb *urb_in;
+       struct urb *urb_in, *urb_out;
        struct completion completion;
 
        /* transmit support */
        bool tx_overflow;
        uint32_t carrier;
-       uint8_t cycle_overhead;
-       uint8_t channels;
-       uint8_t busy4;
-       uint8_t busy7;
+       struct send_packet *packet;
 
        char name[64];
        char phys[64];
@@ -73,7 +71,8 @@ struct iguanair {
 #define DIR_IN                 0xdc
 #define DIR_OUT                        0xcd
 
-#define MAX_PACKET_SIZE                8u
+#define MAX_IN_PACKET          8u
+#define MAX_OUT_PACKET         (sizeof(struct send_packet) + BUF_SIZE)
 #define TIMEOUT                        1000
 #define RX_RESOLUTION          21333
 
@@ -191,20 +190,25 @@ static void iguanair_rx(struct urb *urb)
                dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
 }
 
-static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
+static void iguanair_irq_out(struct urb *urb)
 {
-       int rc, transferred;
+       struct iguanair *ir = urb->context;
+
+       if (urb->status)
+               dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status);
+}
+
+static int iguanair_send(struct iguanair *ir, unsigned size)
+{
+       int rc;
 
        INIT_COMPLETION(ir->completion);
 
-       rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size,
-                                                       &transferred, TIMEOUT);
+       ir->urb_out->transfer_buffer_length = size;
+       rc = usb_submit_urb(ir->urb_out, GFP_KERNEL);
        if (rc)
                return rc;
 
-       if (transferred != size)
-               return -EIO;
-
        if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
                return -ETIMEDOUT;
 
@@ -213,14 +217,13 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
 
 static int iguanair_get_features(struct iguanair *ir)
 {
-       struct packet packet;
        int rc;
 
-       packet.start = 0;
-       packet.direction = DIR_OUT;
-       packet.cmd = CMD_GET_VERSION;
+       ir->packet->header.start = 0;
+       ir->packet->header.direction = DIR_OUT;
+       ir->packet->header.cmd = CMD_GET_VERSION;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
        if (rc) {
                dev_info(ir->dev, "failed to get version\n");
                goto out;
@@ -235,17 +238,23 @@ static int iguanair_get_features(struct iguanair *ir)
        ir->bufsize = 150;
        ir->cycle_overhead = 65;
 
-       packet.cmd = CMD_GET_BUFSIZE;
+       ir->packet->header.cmd = CMD_GET_BUFSIZE;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
        if (rc) {
                dev_info(ir->dev, "failed to get buffer size\n");
                goto out;
        }
 
-       packet.cmd = CMD_GET_FEATURES;
+       if (ir->bufsize > BUF_SIZE) {
+               dev_info(ir->dev, "buffer size %u larger than expected\n",
+                                                               ir->bufsize);
+               ir->bufsize = BUF_SIZE;
+       }
+
+       ir->packet->header.cmd = CMD_GET_FEATURES;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
        if (rc) {
                dev_info(ir->dev, "failed to get features\n");
                goto out;
@@ -257,13 +266,18 @@ out:
 
 static int iguanair_receiver(struct iguanair *ir, bool enable)
 {
-       struct packet packet = { 0, DIR_OUT, enable ?
-                               CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
+       int rc;
+
+       ir->packet->header.start = 0;
+       ir->packet->header.direction = DIR_OUT;
+       ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF;
 
        if (enable)
                ir_raw_event_reset(ir->rc);
 
-       return iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
+
+       return rc;
 }
 
 /*
@@ -308,8 +322,8 @@ static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier)
                fours = (cycles - sevens * 7) / 4;
 
                /* magic happens here */
-               ir->busy7 = (4 - sevens) * 2;
-               ir->busy4 = 110 - fours;
+               ir->packet->busy7 = (4 - sevens) * 2;
+               ir->packet->busy4 = 110 - fours;
        }
 
        mutex_unlock(&ir->lock);
@@ -325,7 +339,7 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
                return 4;
 
        mutex_lock(&ir->lock);
-       ir->channels = mask;
+       ir->packet->channels = mask << 4;
        mutex_unlock(&ir->lock);
 
        return 0;
@@ -337,16 +351,9 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
        uint8_t space;
        unsigned i, size, periods, bytes;
        int rc;
-       struct send_packet *packet;
 
        mutex_lock(&ir->lock);
 
-       packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL);
-       if (!packet) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
        /* convert from us to carrier periods */
        for (i = space = size = 0; i < count; i++) {
                periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
@@ -356,11 +363,11 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
                        break;
                }
                while (periods > 127) {
-                       packet->payload[size++] = 127 | space;
+                       ir->packet->payload[size++] = 127 | space;
                        periods -= 127;
                }
 
-               packet->payload[size++] = periods | space;
+               ir->packet->payload[size++] = periods | space;
                space ^= 0x80;
        }
 
@@ -369,36 +376,19 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
                goto out;
        }
 
-       packet->header.start = 0;
-       packet->header.direction = DIR_OUT;
-       packet->header.cmd = CMD_SEND;
-       packet->length = size;
-       packet->channels = ir->channels << 4;
-       packet->busy7 = ir->busy7;
-       packet->busy4 = ir->busy4;
-
-       if (ir->receiver_on) {
-               rc = iguanair_receiver(ir, false);
-               if (rc) {
-                       dev_warn(ir->dev, "disable receiver before transmit failed\n");
-                       goto out;
-               }
-       }
+       ir->packet->header.start = 0;
+       ir->packet->header.direction = DIR_OUT;
+       ir->packet->header.cmd = CMD_SEND;
+       ir->packet->length = size;
 
        ir->tx_overflow = false;
 
-       rc = iguanair_send(ir, packet, size + 8);
+       rc = iguanair_send(ir, sizeof(*ir->packet) + size);
 
        if (rc == 0 && ir->tx_overflow)
                rc = -EOVERFLOW;
 
-       if (ir->receiver_on) {
-               if (iguanair_receiver(ir, true))
-                       dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
-       }
-
 out:
-       kfree(packet);
        mutex_unlock(&ir->lock);
 
        return rc ? rc : count;
@@ -411,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev)
 
        mutex_lock(&ir->lock);
 
-       BUG_ON(ir->receiver_on);
-
        rc = iguanair_receiver(ir, true);
        if (rc == 0)
                ir->receiver_on = true;
@@ -443,7 +431,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        struct usb_device *udev = interface_to_usbdev(intf);
        struct iguanair *ir;
        struct rc_dev *rc;
-       int ret, pipein;
+       int ret, pipein, pipeout;
        struct usb_host_interface *idesc;
 
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
@@ -453,11 +441,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
                goto out;
        }
 
-       ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL,
+       ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL,
                                                                &ir->dma_in);
+       ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL,
+                                                               &ir->dma_out);
        ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+       ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
 
-       if (!ir->buf_in || !ir->urb_in) {
+       if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
                ret = -ENOMEM;
                goto out;
        }
@@ -472,13 +463,18 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        ir->rc = rc;
        ir->dev = &intf->dev;
        ir->udev = udev;
-       ir->pipe_out = usb_sndintpipe(udev,
-                               idesc->endpoint[1].desc.bEndpointAddress);
        mutex_init(&ir->lock);
+
        init_completion(&ir->completion);
+       pipeout = usb_sndintpipe(udev,
+                               idesc->endpoint[1].desc.bEndpointAddress);
+       usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET,
+                                               iguanair_irq_out, ir, 1);
+       ir->urb_out->transfer_dma = ir->dma_out;
+       ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
        pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
-       usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE,
+       usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET,
                                                         iguanair_rx, ir, 1);
        ir->urb_in->transfer_dma = ir->dma_in;
        ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -528,11 +524,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        return 0;
 out2:
        usb_kill_urb(ir->urb_in);
+       usb_kill_urb(ir->urb_out);
 out:
        if (ir) {
                usb_free_urb(ir->urb_in);
-               usb_free_coherent(udev, MAX_PACKET_SIZE, ir->buf_in,
-                                                               ir->dma_in);
+               usb_free_urb(ir->urb_out);
+               usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
+               usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet,
+                                                               ir->dma_out);
        }
        rc_free_device(rc);
        kfree(ir);
@@ -546,8 +545,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf)
        rc_unregister_device(ir->rc);
        usb_set_intfdata(intf, NULL);
        usb_kill_urb(ir->urb_in);
+       usb_kill_urb(ir->urb_out);
        usb_free_urb(ir->urb_in);
-       usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in);
+       usb_free_urb(ir->urb_out);
+       usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
+       usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out);
        kfree(ir);
 }
 
@@ -565,6 +567,7 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
        }
 
        usb_kill_urb(ir->urb_in);
+       usb_kill_urb(ir->urb_out);
 
        mutex_unlock(&ir->lock);
 
index 569124b03de3f8ecfa67321a536e144b628b81cd..870c93052fd0a0a97dc2138f1f5694d52507feba 100644 (file)
@@ -203,13 +203,13 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
        /* TX settings */
        case LIRC_SET_TRANSMITTER_MASK:
                if (!dev->s_tx_mask)
-                       return -EINVAL;
+                       return -ENOSYS;
 
                return dev->s_tx_mask(dev, val);
 
        case LIRC_SET_SEND_CARRIER:
                if (!dev->s_tx_carrier)
-                       return -EINVAL;
+                       return -ENOSYS;
 
                return dev->s_tx_carrier(dev, val);
 
index c64e9e30045db6c23469dcca884ff2578e83a5e9..2fa71d0d72d7e6364f751918b9d258e49c24a410 100644 (file)
 #include <linux/module.h>
 
 static struct rc_map_table msi_digivox_ii[] = {
-       { 0x0002, KEY_2 },
-       { 0x0003, KEY_UP },              /* up */
-       { 0x0004, KEY_3 },
-       { 0x0005, KEY_CHANNELDOWN },
-       { 0x0008, KEY_5 },
-       { 0x0009, KEY_0 },
-       { 0x000b, KEY_8 },
-       { 0x000d, KEY_DOWN },            /* down */
-       { 0x0010, KEY_9 },
-       { 0x0011, KEY_7 },
-       { 0x0014, KEY_VOLUMEUP },
-       { 0x0015, KEY_CHANNELUP },
-       { 0x0016, KEY_OK },
-       { 0x0017, KEY_POWER2 },
-       { 0x001a, KEY_1 },
-       { 0x001c, KEY_4 },
-       { 0x001d, KEY_6 },
-       { 0x001f, KEY_VOLUMEDOWN },
+       { 0x0302, KEY_2 },
+       { 0x0303, KEY_UP },              /* up */
+       { 0x0304, KEY_3 },
+       { 0x0305, KEY_CHANNELDOWN },
+       { 0x0308, KEY_5 },
+       { 0x0309, KEY_0 },
+       { 0x030b, KEY_8 },
+       { 0x030d, KEY_DOWN },            /* down */
+       { 0x0310, KEY_9 },
+       { 0x0311, KEY_7 },
+       { 0x0314, KEY_VOLUMEUP },
+       { 0x0315, KEY_CHANNELUP },
+       { 0x0316, KEY_OK },
+       { 0x0317, KEY_POWER2 },
+       { 0x031a, KEY_1 },
+       { 0x031c, KEY_4 },
+       { 0x031d, KEY_6 },
+       { 0x031f, KEY_VOLUMEDOWN },
 };
 
 static struct rc_map_list msi_digivox_ii_map = {
index 699eef39128bf3eacf91a08d1a1026a1dfac1653..2ea913a44ae887b8cfe48503e68c707201ae2a88 100644 (file)
@@ -517,6 +517,9 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier)
        struct nvt_dev *nvt = dev->priv;
        u16 val;
 
+       if (carrier == 0)
+               return -EINVAL;
+
        nvt_cir_reg_write(nvt, 1, CIR_CP);
        val = 3000000 / (carrier) - 1;
        nvt_cir_reg_write(nvt, val & 0xff, CIR_CC);
index 49731b1a9c57f09a5e9aa43a199e7f5f4e5d766a..9f5a17bb5ef5df9d09e09519a2424dbac2e0e158 100644 (file)
@@ -890,6 +890,9 @@ static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
        struct device *dev = rr3->dev;
 
        rr3_dbg(dev, "Setting modulation frequency to %u", carrier);
+       if (carrier == 0)
+               return -EINVAL;
+
        rr3->carrier = carrier;
 
        return carrier;
index 30ae1f24abc3b536ec6e0735c3a3be9f5f270a74..7c9b5f33113b225405a33a30edd2098c4f6ffa52 100644 (file)
@@ -184,7 +184,7 @@ enum wbcir_txstate {
 };
 
 /* Misc */
-#define WBCIR_NAME     "Winbond CIR"
+#define WBCIR_NAME     "winbond-cir"
 #define WBCIR_ID_FAMILY          0xF1 /* Family ID for the WPCD376I    */
 #define        WBCIR_ID_CHIP            0x04 /* Chip ID for the WPCD376I       */
 #define INVALID_SCANCODE   0x7FFFFFFF /* Invalid with all protos       */
index 0ed9091ff48eb02d951b2888614534788cfb688b..2e1a02e360ff0cd7279fed8ca20b80a3ee0b8ad8 100644 (file)
@@ -245,7 +245,7 @@ struct mt2063_state {
 /*
  * mt2063_write - Write data into the I2C bus
  */
-static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
+static int mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
 {
        struct dvb_frontend *fe = state->frontend;
        int ret;
@@ -277,9 +277,9 @@ static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
 /*
  * mt2063_write - Write register data into the I2C bus, caching the value
  */
-static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
+static int mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
 {
-       u32 status;
+       int status;
 
        dprintk(2, "\n");
 
@@ -298,10 +298,10 @@ static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
 /*
  * mt2063_read - Read data from the I2C bus
  */
-static u32 mt2063_read(struct mt2063_state *state,
+static int mt2063_read(struct mt2063_state *state,
                           u8 subAddress, u8 *pData, u32 cnt)
 {
-       u32 status = 0; /* Status to be returned        */
+       int status = 0; /* Status to be returned        */
        struct dvb_frontend *fe = state->frontend;
        u32 i = 0;
 
@@ -816,7 +816,7 @@ static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
  */
 static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
 {
-       u32 status = 0;
+       int status = 0;
        u32 fm, fp;             /*  restricted range on LO's        */
        pAS_Info->bSpurAvoided = 0;
        pAS_Info->nSpursFound = 0;
@@ -935,14 +935,14 @@ static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
  *
  * This function returns 0, if no lock, 1 if locked and a value < 1 if error
  */
-static unsigned int mt2063_lockStatus(struct mt2063_state *state)
+static int mt2063_lockStatus(struct mt2063_state *state)
 {
        const u32 nMaxWait = 100;       /*  wait a maximum of 100 msec   */
        const u32 nPollRate = 2;        /*  poll status bits every 2 ms */
        const u32 nMaxLoops = nMaxWait / nPollRate;
        const u8 LO1LK = 0x80;
        u8 LO2LK = 0x08;
-       u32 status;
+       int status;
        u32 nDelays = 0;
 
        dprintk(2, "\n");
@@ -1069,7 +1069,7 @@ static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
 static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
                                        enum MT2063_DNC_Output_Enable nValue)
 {
-       u32 status = 0; /* Status to be returned        */
+       int status = 0; /* Status to be returned        */
        u8 val = 0;
 
        dprintk(2, "\n");
@@ -1203,7 +1203,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
 static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
                                  enum mt2063_delivery_sys Mode)
 {
-       u32 status = 0; /* Status to be returned        */
+       int status = 0; /* Status to be returned        */
        u8 val;
        u32 longval;
 
@@ -1345,7 +1345,7 @@ static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
 static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
                                     enum MT2063_Mask_Bits Bits)
 {
-       u32 status = 0;
+       int status = 0;
 
        dprintk(2, "\n");
        Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD);   /* Only valid bits for this tuner */
@@ -1374,7 +1374,7 @@ static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
  */
 static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
 {
-       u32 status;
+       int status;
 
        dprintk(2, "\n");
        if (Shutdown == 1)
@@ -1540,7 +1540,7 @@ static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
 static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
 {                              /* RF input center frequency   */
 
-       u32 status = 0;
+       int status = 0;
        u32 LO1;                /*  1st LO register value           */
        u32 Num1;               /*  Numerator for LO1 reg. value    */
        u32 f_IF1;              /*  1st IF requested                */
@@ -1803,7 +1803,7 @@ static const u8 MT2063B3_defaults[] = {
 
 static int mt2063_init(struct dvb_frontend *fe)
 {
-       u32 status;
+       int status;
        struct mt2063_state *state = fe->tuner_priv;
        u8 all_resets = 0xF0;   /* reset/load bits */
        const u8 *def = NULL;
@@ -2249,8 +2249,8 @@ struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
        dprintk(2, "\n");
 
        state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (!state)
+               return NULL;
 
        state->config = config;
        state->i2c = i2c;
@@ -2261,18 +2261,15 @@ struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
 
        printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
        return fe;
-
-error:
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL_GPL(mt2063_attach);
 
+#if 0
 /*
  * Ancillary routines visible outside mt2063
  * FIXME: Remove them in favor of using standard tuner callbacks
  */
-unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
+static int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
 {
        struct mt2063_state *state = fe->tuner_priv;
        int err = 0;
@@ -2285,9 +2282,8 @@ unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
 
        return err;
 }
-EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown);
 
-unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
+static int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
 {
        struct mt2063_state *state = fe->tuner_priv;
        int err = 0;
@@ -2300,7 +2296,7 @@ unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
 
        return err;
 }
-EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits);
+#endif
 
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 MODULE_DESCRIPTION("MT2063 Silicon tuner");
index 3f5cfd93713f17d17668f798659c872558861a9a..ab24170c15719029d1f76deb0f06fca78f015bbf 100644 (file)
@@ -23,10 +23,6 @@ static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
        return NULL;
 }
 
-/* FIXME: Should use the standard DVB attachment interfaces */
-unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe);
-unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe);
-
 #endif /* CONFIG_DVB_MT2063 */
 
 #endif /* __MT2063_H__ */
index 221171eeb0c32ab8d7e34c036abba3e70789e81b..18c77afe2e4ff8f32345a56d6aae199de1062c74 100644 (file)
@@ -187,7 +187,8 @@ int tda18271_read_extended(struct dvb_frontend *fe)
        return (ret == 2 ? 0 : ret);
 }
 
-int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
+                       bool lock_i2c)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -198,7 +199,6 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
 
        BUG_ON((len == 0) || (idx + len > sizeof(buf)));
 
-
        switch (priv->small_i2c) {
        case TDA18271_03_BYTE_CHUNK_INIT:
                max = 3;
@@ -214,7 +214,19 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
                max = 39;
        }
 
-       tda18271_i2c_gate_ctrl(fe, 1);
+
+       /*
+        * If lock_i2c is true, it will take the I2C bus for tda18271 private
+        * usage during the entire write ops, as otherwise, bad things could
+        * happen.
+        * During device init, several write operations will happen. So,
+        * tda18271_init_regs controls the I2C lock directly,
+        * disabling lock_i2c here.
+        */
+       if (lock_i2c) {
+               tda18271_i2c_gate_ctrl(fe, 1);
+               i2c_lock_adapter(priv->i2c_props.adap);
+       }
        while (len) {
                if (max > len)
                        max = len;
@@ -226,14 +238,17 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
                msg.len = max + 1;
 
                /* write registers */
-               ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+               ret = __i2c_transfer(priv->i2c_props.adap, &msg, 1);
                if (ret != 1)
                        break;
 
                idx += max;
                len -= max;
        }
-       tda18271_i2c_gate_ctrl(fe, 0);
+       if (lock_i2c) {
+               i2c_unlock_adapter(priv->i2c_props.adap);
+               tda18271_i2c_gate_ctrl(fe, 0);
+       }
 
        if (ret != 1)
                tda_err("ERROR: idx = 0x%x, len = %d, "
@@ -242,10 +257,16 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
        return (ret == 1 ? 0 : ret);
 }
 
+int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+{
+       return __tda18271_write_regs(fe, idx, len, true);
+}
+
 /*---------------------------------------------------------------------*/
 
-int tda18271_charge_pump_source(struct dvb_frontend *fe,
-                               enum tda18271_pll pll, int force)
+static int __tda18271_charge_pump_source(struct dvb_frontend *fe,
+                                        enum tda18271_pll pll, int force,
+                                        bool lock_i2c)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -255,9 +276,16 @@ int tda18271_charge_pump_source(struct dvb_frontend *fe,
        regs[r_cp] &= ~0x20;
        regs[r_cp] |= ((force & 1) << 5);
 
-       return tda18271_write_regs(fe, r_cp, 1);
+       return __tda18271_write_regs(fe, r_cp, 1, lock_i2c);
+}
+
+int tda18271_charge_pump_source(struct dvb_frontend *fe,
+                               enum tda18271_pll pll, int force)
+{
+       return __tda18271_charge_pump_source(fe, pll, force, true);
 }
 
+
 int tda18271_init_regs(struct dvb_frontend *fe)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
@@ -267,6 +295,13 @@ int tda18271_init_regs(struct dvb_frontend *fe)
                i2c_adapter_id(priv->i2c_props.adap),
                priv->i2c_props.addr);
 
+       /*
+        * Don't let any other I2C transfer to happen at adapter during init,
+        * as those could cause bad things
+        */
+       tda18271_i2c_gate_ctrl(fe, 1);
+       i2c_lock_adapter(priv->i2c_props.adap);
+
        /* initialize registers */
        switch (priv->id) {
        case TDA18271HDC1:
@@ -352,28 +387,28 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_EB22] = 0x48;
        regs[R_EB23] = 0xb0;
 
-       tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+       __tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS, false);
 
        /* setup agc1 gain */
        regs[R_EB17] = 0x00;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
        regs[R_EB17] = 0x03;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
        regs[R_EB17] = 0x43;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
        regs[R_EB17] = 0x4c;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
 
        /* setup agc2 gain */
        if ((priv->id) == TDA18271HDC1) {
                regs[R_EB20] = 0xa0;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
                regs[R_EB20] = 0xa7;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
                regs[R_EB20] = 0xe7;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
                regs[R_EB20] = 0xec;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
        }
 
        /* image rejection calibration */
@@ -391,21 +426,21 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD2] = 0x08;
        regs[R_MD3] = 0x00;
 
-       tda18271_write_regs(fe, R_EP3, 11);
+       __tda18271_write_regs(fe, R_EP3, 11, false);
 
        if ((priv->id) == TDA18271HDC2) {
                /* main pll cp source on */
-               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
+               __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1, false);
                msleep(1);
 
                /* main pll cp source off */
-               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
+               __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0, false);
        }
 
        msleep(5); /* pll locking */
 
        /* launch detector */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
        msleep(5); /* wanted low measurement */
 
        regs[R_EP5] = 0x85;
@@ -413,11 +448,11 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_CD1] = 0x66;
        regs[R_CD2] = 0x70;
 
-       tda18271_write_regs(fe, R_EP3, 7);
+       __tda18271_write_regs(fe, R_EP3, 7, false);
        msleep(5); /* pll locking */
 
        /* launch optimization algorithm */
-       tda18271_write_regs(fe, R_EP2, 1);
+       __tda18271_write_regs(fe, R_EP2, 1, false);
        msleep(30); /* image low optimization completion */
 
        /* mid-band */
@@ -428,11 +463,11 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD1] = 0x73;
        regs[R_MD2] = 0x1a;
 
-       tda18271_write_regs(fe, R_EP3, 11);
+       __tda18271_write_regs(fe, R_EP3, 11, false);
        msleep(5); /* pll locking */
 
        /* launch detector */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
        msleep(5); /* wanted mid measurement */
 
        regs[R_EP5] = 0x86;
@@ -440,11 +475,11 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_CD1] = 0x66;
        regs[R_CD2] = 0xa0;
 
-       tda18271_write_regs(fe, R_EP3, 7);
+       __tda18271_write_regs(fe, R_EP3, 7, false);
        msleep(5); /* pll locking */
 
        /* launch optimization algorithm */
-       tda18271_write_regs(fe, R_EP2, 1);
+       __tda18271_write_regs(fe, R_EP2, 1, false);
        msleep(30); /* image mid optimization completion */
 
        /* high-band */
@@ -456,30 +491,33 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD1] = 0x71;
        regs[R_MD2] = 0xcd;
 
-       tda18271_write_regs(fe, R_EP3, 11);
+       __tda18271_write_regs(fe, R_EP3, 11, false);
        msleep(5); /* pll locking */
 
        /* launch detector */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
        msleep(5); /* wanted high measurement */
 
        regs[R_EP5] = 0x87;
        regs[R_CD1] = 0x65;
        regs[R_CD2] = 0x50;
 
-       tda18271_write_regs(fe, R_EP3, 7);
+       __tda18271_write_regs(fe, R_EP3, 7, false);
        msleep(5); /* pll locking */
 
        /* launch optimization algorithm */
-       tda18271_write_regs(fe, R_EP2, 1);
+       __tda18271_write_regs(fe, R_EP2, 1, false);
        msleep(30); /* image high optimization completion */
 
        /* return to normal mode */
        regs[R_EP4] = 0x64;
-       tda18271_write_regs(fe, R_EP4, 1);
+       __tda18271_write_regs(fe, R_EP4, 1, false);
 
        /* synchronize */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
+
+       i2c_unlock_adapter(priv->i2c_props.adap);
+       tda18271_i2c_gate_ctrl(fe, 0);
 
        return 0;
 }
index 824f1911ee21bcdcf3282ef33ffece13a1f3b654..3d7526e28d426f8ca119f4d3b1326abd469b7622 100644 (file)
@@ -500,7 +500,7 @@ static int af9015_read_config(struct dvb_usb_device *d)
                case 3:
                        state->af9013_config[i].clock = 25000000;
                        break;
-               };
+               }
                dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n",
                                __func__, i, val,
                                state->af9013_config[i].clock);
@@ -568,7 +568,7 @@ static int af9015_read_config(struct dvb_usb_device *d)
                                        "supported, please report!\n",
                                        KBUILD_MODNAME, val);
                        return -ENODEV;
-               };
+               }
 
                state->af9013_config[i].tuner = val;
                dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n",
index aabd3fc03ea7e1594c00aab276364b857e9459ff..ea27eaff4e34fdc77d9739d82b4620698a58fca7 100644 (file)
@@ -520,7 +520,7 @@ static int af9035_read_config(struct dvb_usb_device *d)
                        dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \
                                        "supported, please report!",
                                        KBUILD_MODNAME, tmp);
-               };
+               }
 
                /* tuner IF frequency */
                ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp);
index 8d7fef84afd8b5d0d2b93c1d49ec7e7306f3d94a..83684ed023cd9bba08a20ae9cfe682f636da5a36 100644 (file)
@@ -93,7 +93,7 @@ static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        /* call the universal NEC remote processor, to find out the key's state and event */
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
-               deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_rc("key: %*ph\n", 5, key);
        ret = 0;
 out:
        kfree(key);
index 0a98548ecd172448bed6c60b0cf9a5ee182c6ca8..9fd1527494ebd65ab200c38f13a20e28330034a1 100644 (file)
@@ -172,8 +172,7 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                if (*event != d->last_event)
                        st->rc_counter = 0;
 
-               deb_rc("key: %x %x %x %x %x\n",
-                      key[0], key[1], key[2], key[3], key[4]);
+               deb_rc("key: %*ph\n", 5, key);
        }
        return 0;
 }
index a76bbb29ca36eeb0c5a3cfc0b42fe9a7ae422df8..af0d4321845b575589ca5a045eb2490f207d1d42 100644 (file)
@@ -473,7 +473,7 @@ int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        dvb_usb_generic_rw(d,&cmd,1,key,5,0);
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
-               deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_info("key: %*ph\n", 5, key);
        return 0;
 }
 EXPORT_SYMBOL(dibusb_rc_query);
index ff34419a4c88438ca74ac0eac19180d9fbeafd07..772bde3c5020a63b026567cf6e62ba44f2c8714b 100644 (file)
@@ -253,7 +253,7 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        }
 
        if (key[0] != 0)
-               deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_rc("key: %*ph\n", 5, key);
        return 0;
 }
 
index 66f205c112b2fe784d5bff6dc1ed0033ee606d68..c357fb3b0a883c382a6c480a0c9567f665f8d10e 100644 (file)
@@ -84,7 +84,7 @@ static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        dvb_usb_generic_rw(d,&cmd,1,key,5,0);
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
-               deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_info("key: %*ph\n", 5, key);
        return 0;
 }
 
index 288af29a8bb74294195119343b50151b9f044ec9..661bb75be955c7f6ba474382675aa50755b2ed4f 100644 (file)
@@ -358,7 +358,7 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
 
        if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
                goto done;
-       deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
+       deb("%*ph\n", 4, read);
 
        if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
                goto done;
index acefaa89cc53724fa69d8c2afe1831990d8ed433..7a8c8c18590fdcb16c561cff57ea6d2abc6f875e 100644 (file)
@@ -677,6 +677,7 @@ static struct usb_device_id technisat_usb2_id_table[] = {
        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
        { 0 }           /* Terminating entry */
 };
+MODULE_DEVICE_TABLE(usb, technisat_usb2_id_table);
 
 /* device description */
 static struct dvb_usb_device_properties technisat_usb2_devices = {
index f7297ae76b4888f8a8aafc3b52e09f4b0066fd3d..16a84f9f46d8421e9c902a2b9886a950f1e6bc4d 100644 (file)
@@ -2203,7 +2203,7 @@ EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
 
 static inline void em28xx_set_model(struct em28xx *dev)
 {
-       memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board));
+       dev->board = em28xx_boards[dev->model];
 
        /* Those are the default values for the majority of boards
           Use those values if not specified otherwise at boards entry
index 913e5227897a3c4b68a7ad51ec254c7bb51d41e0..13ae821949e9f5f3007aaf77554e63e1551cc28e 100644 (file)
@@ -574,18 +574,19 @@ static void pctv_520e_init(struct em28xx *dev)
                i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
 };
 
-static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val)
+static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct em28xx *dev = fe->dvb->priv;
 #ifdef CONFIG_GPIOLIB
        struct em28xx_dvb *dvb = dev->dvb;
        int ret;
        unsigned long flags;
 
-       if (val)
-               flags = GPIOF_OUT_INIT_LOW;
+       if (c->lna == 1)
+               flags = GPIOF_OUT_INIT_HIGH; /* enable LNA */
        else
-               flags = GPIOF_OUT_INIT_HIGH;
+               flags = GPIOF_OUT_INIT_LOW; /* disable LNA */
 
        ret = gpio_request_one(dvb->lna_gpio, flags, NULL);
        if (ret)
@@ -595,8 +596,8 @@ static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val)
 
        return ret;
 #else
-       dev_warn(&dev->udev->dev, "%s: LNA control is disabled\n",
-                       KBUILD_MODNAME);
+       dev_warn(&dev->udev->dev, "%s: LNA control is disabled (lna=%u)\n",
+                       KBUILD_MODNAME, c->lna);
        return 0;
 #endif
 }
index b62740846061d583bfed4d5c56365c7fb89586c9..34a26e0cfe77565f81924b325fb06a9d78750009 100644 (file)
@@ -100,12 +100,21 @@ int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value)
 
 void stk1160_select_input(struct stk1160 *dev)
 {
+       int route;
        static const u8 gctrl[] = {
-               0x98, 0x90, 0x88, 0x80
+               0x98, 0x90, 0x88, 0x80, 0x98
        };
 
-       if (dev->ctl_input < ARRAY_SIZE(gctrl))
+       if (dev->ctl_input == STK1160_SVIDEO_INPUT)
+               route = SAA7115_SVIDEO3;
+       else
+               route = SAA7115_COMPOSITE0;
+
+       if (dev->ctl_input < ARRAY_SIZE(gctrl)) {
+               v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
+                               route, 0, 0);
                stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]);
+       }
 }
 
 /* TODO: We should break this into pieces */
@@ -351,8 +360,6 @@ static int stk1160_probe(struct usb_interface *interface,
 
        /* i2c reset saa711x */
        v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
-                               0, 0, 0);
        v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
 
        /* reset stk1160 to default values */
index fe6e857969cadb0c2807a788f1c59973e9219229..6694f9e2ca576c59fd0028992036b8cea101af04 100644 (file)
@@ -419,7 +419,12 @@ static int vidioc_enum_input(struct file *file, void *priv,
        if (i->index > STK1160_MAX_INPUT)
                return -EINVAL;
 
-       sprintf(i->name, "Composite%d", i->index);
+       /* S-Video special handling */
+       if (i->index == STK1160_SVIDEO_INPUT)
+               sprintf(i->name, "S-Video");
+       else
+               sprintf(i->name, "Composite%d", i->index);
+
        i->type = V4L2_INPUT_TYPE_CAMERA;
        i->std = dev->vdev.tvnorms;
        return 0;
index 3feba0033f98df4439795121c2004a1c5048b256..68c8707d36abed789d196ccd3e8a5d528b0b78ac 100644 (file)
@@ -46,7 +46,8 @@
 
 #define STK1160_MIN_PKT_SIZE 3072
 
-#define STK1160_MAX_INPUT 3
+#define STK1160_MAX_INPUT 4
+#define STK1160_SVIDEO_INPUT 4
 
 #define STK1160_I2C_TIMEOUT 100
 
index 5577381b5bf057357c6c4f591e4eb09269c2eb38..18a91fae6bc1869e644ffa05e5e103e13b67a3dc 100644 (file)
@@ -122,21 +122,27 @@ static struct vb2_ops uvc_queue_qops = {
        .buf_finish = uvc_buffer_finish,
 };
 
-void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
                    int drop_corrupted)
 {
+       int ret;
+
        queue->queue.type = type;
        queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
        queue->queue.drv_priv = queue;
        queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
        queue->queue.ops = &uvc_queue_qops;
        queue->queue.mem_ops = &vb2_vmalloc_memops;
-       vb2_queue_init(&queue->queue);
+       ret = vb2_queue_init(&queue->queue);
+       if (ret)
+               return ret;
 
        mutex_init(&queue->mutex);
        spin_lock_init(&queue->irqlock);
        INIT_LIST_HEAD(&queue->irqqueue);
        queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
+
+       return 0;
 }
 
 /* -----------------------------------------------------------------------------
index 1c15b4227bdbd3886ff0e2db32ad00d73b10524e..57c3076a4625b09d4b75d05671c3bfbe38eb9109 100644 (file)
@@ -1755,7 +1755,9 @@ int uvc_video_init(struct uvc_streaming *stream)
        atomic_set(&stream->active, 0);
 
        /* Initialize the video buffers queue. */
-       uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+       ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+       if (ret)
+               return ret;
 
        /* Alternate setting 0 should be the default, yet the XBox Live Vision
         * Cam (and possibly other devices) crash or otherwise misbehave if
index 3764040475bbe75647cd7b14f3a66f1e6383aef7..af216ec45e390fa1bc8863372fd742b6b43b53da 100644 (file)
@@ -600,7 +600,7 @@ extern struct uvc_driver uvc_driver;
 extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
 
 /* Video buffers queue management. */
-extern void uvc_queue_init(struct uvc_video_queue *queue,
+extern int uvc_queue_init(struct uvc_video_queue *queue,
                enum v4l2_buf_type type, int drop_corrupted);
 extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
                struct v4l2_requestbuffers *rb);
index 631cdc0e0bdaab5524b0f9a6eff5bc8208791a2b..f6ee201d9347de19c52d12c7d0f15d86fb09eeec 100644 (file)
@@ -384,6 +384,25 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Extended SAR",
                NULL,
        };
+       static const char * const h264_fp_arrangement_type[] = {
+               "Checkerboard",
+               "Column",
+               "Row",
+               "Side by Side",
+               "Top Bottom",
+               "Temporal",
+               NULL,
+       };
+       static const char * const h264_fmo_map_type[] = {
+               "Interleaved Slices",
+               "Scattered Slices",
+               "Foreground with Leftover",
+               "Box Out",
+               "Raster Scan",
+               "Wipe Scan",
+               "Explicit",
+               NULL,
+       };
        static const char * const mpeg_mpeg4_level[] = {
                "0",
                "0b",
@@ -508,6 +527,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                return h264_profile;
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
                return vui_sar_idc;
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+               return h264_fp_arrangement_type;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
+               return h264_fmo_map_type;
        case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
                return mpeg_mpeg4_level;
        case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
@@ -643,6 +666,22 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:        return "Horizontal Size of SAR";
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:           return "Aspect Ratio VUI Enable";
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:              return "VUI Aspect Ratio IDC";
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:        return "H264 Enable Frame Packing SEI";
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0:   return "H264 Set Curr. Frame as Frame0";
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:  return "H264 FP Arrangement Type";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO:                      return "H264 Flexible MB Ordering";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:             return "H264 Map Type for FMO";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP:          return "H264 FMO Number of Slice Groups";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION:     return "H264 FMO Direction of Change";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE:          return "H264 FMO Size of 1st Slice Grp";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH:           return "H264 FMO No. of Consecutive MBs";
+       case V4L2_CID_MPEG_VIDEO_H264_ASO:                      return "H264 Arbitrary Slice Ordering";
+       case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER:          return "H264 ASO Slice Order";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:      return "Enable H264 Hierarchical Coding";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: return "H264 Hierarchical Coding Type";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
+                                                               return "H264 Set QP Value for HC Layers";
        case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:              return "MPEG4 I-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:              return "MPEG4 P-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:              return "MPEG4 B-Frame QP Value";
@@ -657,6 +696,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_VBV_SIZE:                      return "VBV Buffer Size";
        case V4L2_CID_MPEG_VIDEO_DEC_PTS:                       return "Video Decoder PTS";
        case V4L2_CID_MPEG_VIDEO_DEC_FRAME:                     return "Video Decoder Frame Count";
+       case V4L2_CID_MPEG_VIDEO_VBV_DELAY:                     return "Initial Delay for VBV Control";
 
        /* CAMERA controls */
        /* Keep the order of the 'case's the same as in videodev2.h! */
@@ -749,6 +789,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_IMAGE_PROC_CLASS:         return "Image Processing Controls";
        case V4L2_CID_LINK_FREQ:                return "Link Frequency";
        case V4L2_CID_PIXEL_RATE:               return "Pixel Rate";
+       case V4L2_CID_TEST_PATTERN:             return "Test Pattern";
 
        /* DV controls */
        case V4L2_CID_DV_CLASS:                 return "Digital Video Controls";
@@ -853,6 +894,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
        case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
        case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
        case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
        case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
@@ -862,6 +905,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_DV_TX_MODE:
        case V4L2_CID_DV_TX_RGB_RANGE:
        case V4L2_CID_DV_RX_RGB_RANGE:
+       case V4L2_CID_TEST_PATTERN:
                *type = V4L2_CTRL_TYPE_MENU;
                break;
        case V4L2_CID_LINK_FREQ:
@@ -1648,6 +1692,36 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
 
+/* Helper function for standard menu controls with driver defined menu */
+struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
+                       const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
+                       s32 mask, s32 def, const char * const *qmenu)
+{
+       enum v4l2_ctrl_type type;
+       const char *name;
+       u32 flags;
+       s32 step;
+       s32 min;
+
+       /* v4l2_ctrl_new_std_menu_items() should only be called for
+        * standard controls without a standard menu.
+        */
+       if (v4l2_ctrl_get_menu(id)) {
+               handler_set_err(hdl, -EINVAL);
+               return NULL;
+       }
+
+       v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+       if (type != V4L2_CTRL_TYPE_MENU || qmenu == NULL) {
+               handler_set_err(hdl, -EINVAL);
+               return NULL;
+       }
+       return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def,
+                            flags, qmenu, NULL, NULL);
+
+}
+EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
+
 /* Helper function for standard integer menu controls */
 struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
                        const struct v4l2_ctrl_ops *ops,
index 9d3e46c446ad7cf502ca49fe6dcaa1d85ec09277..8f388ff31ebb8732fd1793778c578f9395df777a 100644 (file)
@@ -157,8 +157,7 @@ static const char *v4l2_memory_names[] = {
        [V4L2_MEMORY_OVERLAY] = "overlay",
 };
 
-#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
-                          arr[a] : "unknown")
+#define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown")
 
 /* ------------------------------------------------------------------ */
 /* debug help functions                                               */
@@ -2188,6 +2187,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
        int ret = 0;
 
        switch (cmd) {
+       case VIDIOC_PREPARE_BUF:
        case VIDIOC_QUERYBUF:
        case VIDIOC_QBUF:
        case VIDIOC_DQBUF: {
@@ -2211,6 +2211,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                struct v4l2_subdev_edid *edid = parg;
 
                if (edid->blocks) {
+                       if (edid->blocks > 256) {
+                               ret = -EINVAL;
+                               break;
+                       }
                        *user_ptr = (void __user *)edid->edid;
                        *kernel_ptr = (void *)&edid->edid;
                        *array_size = edid->blocks * 128;
index e6a26b433e87ffe74728a5e3b93ca353d6e1d83d..432df119af278dd953a492fece76552a4c8d3e86 100644 (file)
@@ -276,6 +276,9 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
  */
 static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
+       if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
+               return 0;
+
        /* Is memory for copying plane information present? */
        if (NULL == b->m.planes) {
                dprintk(1, "Multi-planar buffer passed but "
@@ -331,10 +334,9 @@ static bool __buffers_in_use(struct vb2_queue *q)
  * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
  * returned to userspace
  */
-static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 {
        struct vb2_queue *q = vb->vb2_queue;
-       int ret;
 
        /* Copy back data such as timestamp, flags, etc. */
        memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
@@ -342,14 +344,11 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        b->reserved = vb->v4l2_buf.reserved;
 
        if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
-               ret = __verify_planes_array(vb, b);
-               if (ret)
-                       return ret;
-
                /*
                 * Fill in plane-related data if userspace provided an array
-                * for it. The memory and size is verified above.
+                * for it. The caller has already verified memory and size.
                 */
+               b->length = vb->num_planes;
                memcpy(b->m.planes, vb->v4l2_planes,
                        b->length * sizeof(struct v4l2_plane));
        } else {
@@ -391,8 +390,6 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 
        if (__buffer_in_use(q, vb))
                b->flags |= V4L2_BUF_FLAG_MAPPED;
-
-       return 0;
 }
 
 /**
@@ -411,6 +408,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
        struct vb2_buffer *vb;
+       int ret;
 
        if (b->type != q->type) {
                dprintk(1, "querybuf: wrong buffer type\n");
@@ -422,8 +420,10 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
                return -EINVAL;
        }
        vb = q->bufs[b->index];
-
-       return __fill_v4l2_buffer(vb, b);
+       ret = __verify_planes_array(vb, b);
+       if (!ret)
+               __fill_v4l2_buffer(vb, b);
+       return ret;
 }
 EXPORT_SYMBOL(vb2_querybuf);
 
@@ -813,24 +813,16 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 EXPORT_SYMBOL_GPL(vb2_buffer_done);
 
 /**
- * __fill_vb2_buffer() - fill a vb2_buffer with information provided in
- * a v4l2_buffer by the userspace
+ * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
+ * v4l2_buffer by the userspace. The caller has already verified that struct
+ * v4l2_buffer has a valid number of planes.
  */
-static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
+static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
                                struct v4l2_plane *v4l2_planes)
 {
        unsigned int plane;
-       int ret;
 
        if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-               /*
-                * Verify that the userspace gave us a valid array for
-                * plane information.
-                */
-               ret = __verify_planes_array(vb, b);
-               if (ret)
-                       return ret;
-
                /* Fill in driver-provided information for OUTPUT types */
                if (V4L2_TYPE_IS_OUTPUT(b->type)) {
                        /*
@@ -872,8 +864,6 @@ static int __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;
-
-       return 0;
 }
 
 /**
@@ -888,10 +878,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
        int ret;
        int write = !V4L2_TYPE_IS_OUTPUT(q->type);
 
-       /* Verify and copy relevant information provided by the userspace */
-       ret = __fill_vb2_buffer(vb, b, planes);
-       if (ret)
-               return ret;
+       /* Copy relevant information provided by the userspace */
+       __fill_vb2_buffer(vb, b, planes);
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
                /* Skip the plane if already verified */
@@ -966,7 +954,8 @@ err:
  */
 static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
-       return __fill_vb2_buffer(vb, b, vb->v4l2_planes);
+       __fill_vb2_buffer(vb, b, vb->v4l2_planes);
+       return 0;
 }
 
 /**
@@ -1059,7 +1048,9 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
                dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state);
                return -EINVAL;
        }
-
+       ret = __verify_planes_array(vb, b);
+       if (ret < 0)
+               return ret;
        ret = __buf_prepare(vb, b);
        if (ret < 0)
                return ret;
@@ -1147,6 +1138,9 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
                ret = -EINVAL;
                goto unlock;
        }
+       ret = __verify_planes_array(vb, b);
+       if (ret)
+               goto unlock;
 
        switch (vb->state) {
        case VB2_BUF_STATE_DEQUEUED:
@@ -1243,8 +1237,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
                 * the locks or return an error if one occurred.
                 */
                call_qop(q, wait_finish, q);
-               if (ret)
+               if (ret) {
+                       dprintk(1, "Sleep was interrupted\n");
                        return ret;
+               }
        }
        return 0;
 }
@@ -1255,7 +1251,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
  * Will sleep if required for nonblocking == false.
  */
 static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
-                               int nonblocking)
+                               struct v4l2_buffer *b, int nonblocking)
 {
        unsigned long flags;
        int ret;
@@ -1273,10 +1269,16 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
         */
        spin_lock_irqsave(&q->done_lock, flags);
        *vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry);
-       list_del(&(*vb)->done_entry);
+       /*
+        * Only remove the buffer from done_list if v4l2_buffer can handle all
+        * the planes.
+        */
+       ret = __verify_planes_array(*vb, b);
+       if (!ret)
+               list_del(&(*vb)->done_entry);
        spin_unlock_irqrestore(&q->done_lock, flags);
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -1335,12 +1337,9 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
                dprintk(1, "dqbuf: invalid buffer type\n");
                return -EINVAL;
        }
-
-       ret = __vb2_get_done_vb(q, &vb, nonblocking);
-       if (ret < 0) {
-               dprintk(1, "dqbuf: error getting next done buffer\n");
+       ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
+       if (ret < 0)
                return ret;
-       }
 
        ret = call_qop(q, buf_finish, vb);
        if (ret) {
index ec6209dd7c397b9238cc1b495e5b849d966a3fdf..debaa75b0552d6daeefc24e4d5ee4dd929baca76 100644 (file)
@@ -725,10 +725,10 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
        DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C),
-       /* Other alt C1 column, these are still configured as alt C */
-       DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C),
-       DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C),
-       DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C),
+       /* Other alt C1 column */
+       DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1),
 };
 
 /* We use this macro to define the groups applicable to a function */
@@ -860,6 +860,284 @@ static const struct nmk_function nmk_db8500_functions[] = {
        FUNCTION(spi2),
 };
 
+static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = {
+       PRCM_GPIOCR_ALTCX(23,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_CLK_a */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_CLK_a */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(24,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE or U2_RXD ??? */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_VAL_a */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(25,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[0] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[0] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(26,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[1] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[1] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(27,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[2] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[2] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(28,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[3] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[3] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(29,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(30,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(31,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(32,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(68,   true, PRCM_IDX_GPIOCR1, 18,     /* REMAP_SELECT_ON */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(69,   true, PRCM_IDX_GPIOCR1, 18,     /* REMAP_SELECT_ON */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(70,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D23 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_CLK */
+       ),
+       PRCM_GPIOCR_ALTCX(71,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D22 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D3 */
+       ),
+       PRCM_GPIOCR_ALTCX(72,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D21 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D2 */
+       ),
+       PRCM_GPIOCR_ALTCX(73,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D20 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D1 */
+       ),
+       PRCM_GPIOCR_ALTCX(74,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D19 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D0 */
+       ),
+       PRCM_GPIOCR_ALTCX(75,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D18 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 0,      /* DBG_UARTMOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(76,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D17 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 0,      /* DBG_UARTMOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(77,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D16 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_VAL */
+       ),
+       PRCM_GPIOCR_ALTCX(86,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O3 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(87,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O2 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(88,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I3 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(89,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I2 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(90,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O1 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(91,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O0 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(92,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I1 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(93,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I0 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(96,   true, PRCM_IDX_GPIOCR2, 3,      /* RF_INT */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(97,   true, PRCM_IDX_GPIOCR2, 1,      /* RF_CTRL */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(151,  false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_CTL */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS17 */
+       ),
+       PRCM_GPIOCR_ALTCX(152,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_CLK */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_CLK */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS16 */
+       ),
+       PRCM_GPIOCR_ALTCX(153,  true, PRCM_IDX_GPIOCR1, 1,      /* UARTMOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D15 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS15 */
+       ),
+       PRCM_GPIOCR_ALTCX(154,  true, PRCM_IDX_GPIOCR1, 1,      /* UARTMOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D14 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS14 */
+       ),
+       PRCM_GPIOCR_ALTCX(155,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D13 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS13 */
+       ),
+       PRCM_GPIOCR_ALTCX(156,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D12 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS12 */
+       ),
+       PRCM_GPIOCR_ALTCX(157,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D11 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS11 */
+       ),
+       PRCM_GPIOCR_ALTCX(158,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D10 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS10 */
+       ),
+       PRCM_GPIOCR_ALTCX(159,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D9 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS9 */
+       ),
+       PRCM_GPIOCR_ALTCX(160,  false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D8 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS8 */
+       ),
+       PRCM_GPIOCR_ALTCX(161,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO7 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D7 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS7 */
+       ),
+       PRCM_GPIOCR_ALTCX(162,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO6 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D6 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS6 */
+       ),
+       PRCM_GPIOCR_ALTCX(163,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO5 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D5 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS5 */
+       ),
+       PRCM_GPIOCR_ALTCX(164,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO4 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D4 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS4 */
+       ),
+       PRCM_GPIOCR_ALTCX(165,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO3 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D3 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS3 */
+       ),
+       PRCM_GPIOCR_ALTCX(166,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO2 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D2 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS2 */
+       ),
+       PRCM_GPIOCR_ALTCX(167,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO1 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D1 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS1 */
+       ),
+       PRCM_GPIOCR_ALTCX(168,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO0 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D0 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS0 */
+       ),
+       PRCM_GPIOCR_ALTCX(170,  true, PRCM_IDX_GPIOCR2, 2,      /* RF_INT */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(171,  true, PRCM_IDX_GPIOCR2, 0,      /* RF_CTRL */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(215,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_TXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(216,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_FRM */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(217,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_CLK */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(218,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_RXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+};
+
+static const u16 db8500_prcm_gpiocr_regs[] = {
+       [PRCM_IDX_GPIOCR1] = 0x138,
+       [PRCM_IDX_GPIOCR2] = 0x574,
+};
+
 static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
        .gpio_ranges = nmk_db8500_ranges,
        .gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges),
@@ -869,6 +1147,9 @@ static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
        .nfunctions = ARRAY_SIZE(nmk_db8500_functions),
        .groups = nmk_db8500_groups,
        .ngroups = ARRAY_SIZE(nmk_db8500_groups),
+       .altcx_pins = db8500_altcx_pins,
+       .npins_altcx = ARRAY_SIZE(db8500_altcx_pins),
+       .prcm_gpiocr_registers = db8500_prcm_gpiocr_regs,
 };
 
 void __devinit
index 3daf665c84c3fbed73fdc2187a5c54cbe4d8fd18..52fc30181f7ea908848a48a6d095373a1d1619d6 100644 (file)
@@ -778,50 +778,50 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
        DB8540_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
        DB8540_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
 
-       /* Other alt C1 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(spi3_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsrefclk_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobspwrctrl_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsclkout_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart1_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modprcmudbg_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsresout_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccgpo_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modxmip_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(i2c6_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2txrx_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2ctsrts_oc1_1, NMK_GPIO_ALT_C),
+       /* Other alt C1 column */
+       DB8540_PIN_GROUP(spi3_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(u2_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobsrefclk_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobspwrctrl_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobsclkout_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(moduart1_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modprcmudbg_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobsresout_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modaccgpo_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modxmip_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(i2c6_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(u2txrx_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(u2ctsrts_oc1_1, NMK_GPIO_ALT_C1),
 
-       /* Other alt C2 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(hxclk_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccuart_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmmod_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduartstmmux_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(hxgpio_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(sbag_oc2_2, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsservice_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart0_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmape_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modxmip_oc2_1, NMK_GPIO_ALT_C),
+       /* Other alt C2 column */
+       DB8540_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(hxclk_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(modaccuart_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(stmmod_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(moduartstmmux_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(hxgpio_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(sbag_oc2_2, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(modobsservice_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(moduart0_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(stmape_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(u2_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(modxmip_oc2_1, NMK_GPIO_ALT_C2),
 
-       /* Other alt C3 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(modaccgpo_oc3_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(tpui_oc3_1, NMK_GPIO_ALT_C),
+       /* Other alt C3 column */
+       DB8540_PIN_GROUP(modaccgpo_oc3_1, NMK_GPIO_ALT_C3),
+       DB8540_PIN_GROUP(tpui_oc3_1, NMK_GPIO_ALT_C3),
 
-       /* Other alt C4 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart1txrx_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart1rtscts_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C),
+       /* Other alt C4 column */
+       DB8540_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(moduart1txrx_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(moduart1rtscts_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4),
 
 };
 
@@ -981,6 +981,265 @@ static const struct nmk_function nmk_db8540_functions[] = {
        FUNCTION(usb)
 };
 
+static const struct prcm_gpiocr_altcx_pin_desc db8540_altcx_pins[] = {
+       PRCM_GPIOCR_ALTCX(8,    true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_CLK */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(9,    true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_RXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(10,   true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_FRM */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(11,   true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_TXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(23,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_CLK_a */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_CLK_a */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(24,   true, PRCM_IDX_GPIOCR3, 30,     /* U2_RXD_g */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_VAL_a */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(25,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[0] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[0] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(26,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[1] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[1] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(27,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[2] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[2] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(28,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[3] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[3] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(64,   true, PRCM_IDX_GPIOCR1, 15,     /* MODOBS_REFCLK_REQ */
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_CTL */
+                               true, PRCM_IDX_GPIOCR2, 23      /* HW_OBS_APE_PRCMU[17] */
+       ),
+       PRCM_GPIOCR_ALTCX(65,   true, PRCM_IDX_GPIOCR1, 19,     /* MODOBS_PWRCTRL0 */
+                               true, PRCM_IDX_GPIOCR1, 24,     /* Hx_CLK */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_CLK */
+                               true, PRCM_IDX_GPIOCR2, 24      /* HW_OBS_APE_PRCMU[16] */
+       ),
+       PRCM_GPIOCR_ALTCX(66,   true, PRCM_IDX_GPIOCR1, 15,     /* MODOBS_CLKOUT1 */
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[15] */
+                               true, PRCM_IDX_GPIOCR2, 25      /* HW_OBS_APE_PRCMU[15] */
+       ),
+       PRCM_GPIOCR_ALTCX(67,   true, PRCM_IDX_GPIOCR1, 1,      /* MODUART1_TXD_a */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* MODACCUART_TXD_a */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[14] */
+                               true, PRCM_IDX_GPIOCR2, 26      /* HW_OBS_APE_PRCMU[14] */
+       ),
+       PRCM_GPIOCR_ALTCX(70,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[17] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_CLK_b */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[13] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[13] */
+       ),
+       PRCM_GPIOCR_ALTCX(71,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[16] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[3] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[12] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[12] */
+       ),
+       PRCM_GPIOCR_ALTCX(72,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[15] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[2] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[11] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[11] */
+       ),
+       PRCM_GPIOCR_ALTCX(73,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[14] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[1] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[10] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[10] */
+       ),
+       PRCM_GPIOCR_ALTCX(74,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[13] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[0] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[9] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[9] */
+       ),
+       PRCM_GPIOCR_ALTCX(75,   true, PRCM_IDX_GPIOCR1, 12,     /* MODOBS_RESOUT0_N */
+                               true, PRCM_IDX_GPIOCR2, 1,      /* MODUART_STMMUX_RXD_b */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[8] */
+                               true, PRCM_IDX_GPIOCR2, 28      /* HW_OBS_APE_PRCMU[8] */
+       ),
+       PRCM_GPIOCR_ALTCX(76,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[12] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[7] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[7] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[7] */
+       ),
+       PRCM_GPIOCR_ALTCX(77,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[11] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[6] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[6] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[6] */
+       ),
+       PRCM_GPIOCR_ALTCX(78,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[10] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[5] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[5] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[5] */
+       ),
+       PRCM_GPIOCR_ALTCX(79,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[9] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[4] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[4] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[4] */
+       ),
+       PRCM_GPIOCR_ALTCX(80,   true, PRCM_IDX_GPIOCR1, 26,     /* MODACC_GPO[0] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[3] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[3] */
+                               true, PRCM_IDX_GPIOCR2, 30      /* HW_OBS_APE_PRCMU[3] */
+       ),
+       PRCM_GPIOCR_ALTCX(81,   true, PRCM_IDX_GPIOCR2, 17,     /* MODACC_GPO[1] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[2] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[2] */
+                               true, PRCM_IDX_GPIOCR2, 30      /* HW_OBS_APE_PRCMU[2] */
+       ),
+       PRCM_GPIOCR_ALTCX(82,   true, PRCM_IDX_GPIOCR3, 8,      /* MOD_PRCMU_DEBUG[8] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[1] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[1] */
+                               true, PRCM_IDX_GPIOCR2, 31      /* HW_OBS_APE_PRCMU[1] */
+       ),
+       PRCM_GPIOCR_ALTCX(83,   true, PRCM_IDX_GPIOCR3, 8,      /* MOD_PRCMU_DEBUG[7] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[0] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[0] */
+                               true, PRCM_IDX_GPIOCR2, 31      /* HW_OBS_APE_PRCMU[0] */
+       ),
+       PRCM_GPIOCR_ALTCX(84,   true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[6] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_CLK_b */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[23] */
+                               true, PRCM_IDX_GPIOCR1, 16      /* MODUART1_RXD_b */
+       ),
+       PRCM_GPIOCR_ALTCX(85,   true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[5] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[3] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[22] */
+                               true, PRCM_IDX_GPIOCR1, 16      /* MODUART1_TXD_b */
+       ),
+       PRCM_GPIOCR_ALTCX(86,   true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[0] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[0] */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* TPIU_D[25] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[0] */
+       ),
+       PRCM_GPIOCR_ALTCX(87,   true, PRCM_IDX_GPIOCR3, 0,      /* MODACC_GPO_a[5] */
+                               true, PRCM_IDX_GPIOCR2, 3,      /* U2_RXD_c */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[24] */
+                               true, PRCM_IDX_GPIOCR1, 21      /* MODUART_STMMUX_RXD_c */
+       ),
+       PRCM_GPIOCR_ALTCX(151,  true, PRCM_IDX_GPIOCR1, 18,     /* REMAP0 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(152,  true, PRCM_IDX_GPIOCR1, 18,     /* REMAP1 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(153,  true, PRCM_IDX_GPIOCR3, 2,      /* KP_O_b[6] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[2] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[21] */
+                               true, PRCM_IDX_GPIOCR1, 0       /* MODUART1_RTS */
+       ),
+       PRCM_GPIOCR_ALTCX(154,  true, PRCM_IDX_GPIOCR3, 2,      /* KP_I_b[6] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[1] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[20] */
+                               true, PRCM_IDX_GPIOCR1, 0       /* MODUART1_CTS */
+       ),
+       PRCM_GPIOCR_ALTCX(155,  true, PRCM_IDX_GPIOCR3, 3,      /* KP_O_b[5] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[0] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[19] */
+                               true, PRCM_IDX_GPIOCR1, 5       /* MODACCUART_RXD_c */
+       ),
+       PRCM_GPIOCR_ALTCX(156,  true, PRCM_IDX_GPIOCR3, 3,      /* KP_O_b[4] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_VAL_b */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[18] */
+                               true, PRCM_IDX_GPIOCR1, 5       /* MODACCUART_TXD_b */
+       ),
+       PRCM_GPIOCR_ALTCX(157,  true, PRCM_IDX_GPIOCR3, 4,      /* KP_I_b[5] */
+                               true, PRCM_IDX_GPIOCR1, 23,     /* MODOBS_SERVICE_N */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[17] */
+                               true, PRCM_IDX_GPIOCR1, 14      /* MODACCUART_RTS */
+       ),
+       PRCM_GPIOCR_ALTCX(158,  true, PRCM_IDX_GPIOCR3, 4,      /* KP_I_b[4] */
+                               true, PRCM_IDX_GPIOCR2, 0,      /* U2_TXD_c */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[16] */
+                               true, PRCM_IDX_GPIOCR1, 14      /* MODACCUART_CTS */
+       ),
+       PRCM_GPIOCR_ALTCX(159,  true, PRCM_IDX_GPIOCR3, 5,      /* KP_O_b[3] */
+                               true, PRCM_IDX_GPIOCR3, 10,     /* MODUART0_RXD */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[31] */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(160,  true, PRCM_IDX_GPIOCR3, 5,      /* KP_I_b[3] */
+                               true, PRCM_IDX_GPIOCR3, 10,     /* MODUART0_TXD */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[30] */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(161,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[4] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_CLK_b */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[29] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_CLK_c */
+       ),
+       PRCM_GPIOCR_ALTCX(162,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[3] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[3] */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[28] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[3] */
+       ),
+       PRCM_GPIOCR_ALTCX(163,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[2] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[2] */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[27] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[2] */
+       ),
+       PRCM_GPIOCR_ALTCX(164,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[1] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[1] */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[26] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[1] */
+       ),
+       PRCM_GPIOCR_ALTCX(204,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_RXD_f */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(205,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_TXD_f */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(206,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_CTSn_b */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(207,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_RTSn_b */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+};
+
+static const u16 db8540_prcm_gpiocr_regs[] = {
+       [PRCM_IDX_GPIOCR1] = 0x138,
+       [PRCM_IDX_GPIOCR2] = 0x574,
+       [PRCM_IDX_GPIOCR3] = 0x2bc,
+};
+
 static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
        .gpio_ranges = nmk_db8540_ranges,
        .gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges),
@@ -990,6 +1249,9 @@ static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
        .nfunctions = ARRAY_SIZE(nmk_db8540_functions),
        .groups = nmk_db8540_groups,
        .ngroups = ARRAY_SIZE(nmk_db8540_groups),
+       .altcx_pins = db8540_altcx_pins,
+       .npins_altcx = ARRAY_SIZE(db8540_altcx_pins),
+       .prcm_gpiocr_registers = db8540_prcm_gpiocr_regs,
 };
 
 void __devinit
index 6030a513f3c488506de4d80cd3cfae6c25ce69b2..fec9c30133d43b2731a9fe8d765ba05106d5eda1 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/pinctrl/pinconf.h>
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
+#include <linux/mfd/dbx500-prcmu.h>
 
 #include <asm/mach/irq.h>
 
@@ -237,6 +238,89 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
        dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
 }
 
+static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
+       unsigned offset, unsigned alt_num)
+{
+       int i;
+       u16 reg;
+       u8 bit;
+       u8 alt_index;
+       const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
+       const u16 *gpiocr_regs;
+
+       if (alt_num > PRCM_IDX_GPIOCR_ALTC_MAX) {
+               dev_err(npct->dev, "PRCM GPIOCR: alternate-C%i is invalid\n",
+                       alt_num);
+               return;
+       }
+
+       for (i = 0 ; i < npct->soc->npins_altcx ; i++) {
+               if (npct->soc->altcx_pins[i].pin == offset)
+                       break;
+       }
+       if (i == npct->soc->npins_altcx) {
+               dev_dbg(npct->dev, "PRCM GPIOCR: pin %i is not found\n",
+                       offset);
+               return;
+       }
+
+       pin_desc = npct->soc->altcx_pins + i;
+       gpiocr_regs = npct->soc->prcm_gpiocr_registers;
+
+       /*
+        * If alt_num is NULL, just clear current ALTCx selection
+        * to make sure we come back to a pure ALTC selection
+        */
+       if (!alt_num) {
+               for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
+                       if (pin_desc->altcx[i].used == true) {
+                               reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+                               bit = pin_desc->altcx[i].control_bit;
+                               if (prcmu_read(reg) & BIT(bit)) {
+                                       prcmu_write_masked(reg, BIT(bit), 0);
+                                       dev_dbg(npct->dev,
+                                               "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
+                                               offset, i+1);
+                               }
+                       }
+               }
+               return;
+       }
+
+       alt_index = alt_num - 1;
+       if (pin_desc->altcx[alt_index].used == false) {
+               dev_warn(npct->dev,
+                       "PRCM GPIOCR: pin %i: alternate-C%i does not exist\n",
+                       offset, alt_num);
+               return;
+       }
+
+       /*
+        * Check if any other ALTCx functions are activated on this pin
+        * and disable it first.
+        */
+       for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
+               if (i == alt_index)
+                       continue;
+               if (pin_desc->altcx[i].used == true) {
+                       reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+                       bit = pin_desc->altcx[i].control_bit;
+                       if (prcmu_read(reg) & BIT(bit)) {
+                               prcmu_write_masked(reg, BIT(bit), 0);
+                               dev_dbg(npct->dev,
+                                       "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
+                                       offset, i+1);
+                       }
+               }
+       }
+
+       reg = gpiocr_regs[pin_desc->altcx[alt_index].reg_index];
+       bit = pin_desc->altcx[alt_index].control_bit;
+       dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n",
+               offset, alt_index+1);
+       prcmu_write_masked(reg, BIT(bit), BIT(bit));
+}
+
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
                             pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
 {
@@ -1287,9 +1371,19 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, nmk_chip);
 
-       nmk_chip->domain = irq_domain_add_legacy(np, NMK_GPIO_PER_CHIP,
-                                               NOMADIK_GPIO_TO_IRQ(pdata->first_gpio),
-                                               0, &nmk_gpio_irq_simple_ops, nmk_chip);
+       if (np) {
+               /* The DT case will just grab a set of IRQ numbers */
+               nmk_chip->domain = irq_domain_add_linear(np, NMK_GPIO_PER_CHIP,
+                               &nmk_gpio_irq_simple_ops, nmk_chip);
+       } else {
+               /* Non-DT legacy mode, use hardwired IRQ numbers */
+               int irq_start;
+
+               irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio);
+               nmk_chip->domain = irq_domain_add_simple(NULL,
+                               NMK_GPIO_PER_CHIP, irq_start,
+                               &nmk_gpio_irq_simple_ops, nmk_chip);
+       }
        if (!nmk_chip->domain) {
                dev_err(&dev->dev, "failed to create irqdomain\n");
                ret = -ENOSYS;
@@ -1441,7 +1535,7 @@ static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
         * IOFORCE will switch *all* ports to their sleepmode setting to as
         * to avoid glitches. (Not just one port!)
         */
-       glitch = (g->altsetting == NMK_GPIO_ALT_C);
+       glitch = ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C);
 
        if (glitch) {
                spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
@@ -1491,8 +1585,21 @@ static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
                 */
                nmk_gpio_disable_lazy_irq(nmk_chip, bit);
 
-               __nmk_gpio_set_mode_safe(nmk_chip, bit, g->altsetting, glitch);
+               __nmk_gpio_set_mode_safe(nmk_chip, bit,
+                       (g->altsetting & NMK_GPIO_ALT_C), glitch);
                clk_disable(nmk_chip->clk);
+
+               /*
+                * Call PRCM GPIOCR config function in case ALTC
+                * has been selected:
+                * - If selection is a ALTCx, some bits in PRCM GPIOCR registers
+                *   must be set.
+                * - If selection is pure ALTC and previous selection was ALTCx,
+                *   then some bits in PRCM GPIOCR registers must be cleared.
+                */
+               if ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C)
+                       nmk_prcm_altcx_set_mode(npct, g->pins[i],
+                               g->altsetting >> NMK_GPIO_ALT_CX_SHIFT);
        }
 
        /* When all pins are successfully reconfigured we get here */
index 5c99f1c62dfd1a1524f3d833b37d36c83c96a3c1..eef316e979a02a1156c8ede6ca10c3b039e5d7fc 100644 (file)
@@ -8,6 +8,78 @@
 #define PINCTRL_NMK_DB8500     1
 #define PINCTRL_NMK_DB8540     2
 
+#define PRCM_GPIOCR_ALTCX(pin_num,\
+       altc1_used, altc1_ri, altc1_cb,\
+       altc2_used, altc2_ri, altc2_cb,\
+       altc3_used, altc3_ri, altc3_cb,\
+       altc4_used, altc4_ri, altc4_cb)\
+{\
+       .pin = pin_num,\
+       .altcx[PRCM_IDX_GPIOCR_ALTC1] = {\
+               .used = altc1_used,\
+               .reg_index = altc1_ri,\
+               .control_bit = altc1_cb\
+       },\
+       .altcx[PRCM_IDX_GPIOCR_ALTC2] = {\
+               .used = altc2_used,\
+               .reg_index = altc2_ri,\
+               .control_bit = altc2_cb\
+       },\
+       .altcx[PRCM_IDX_GPIOCR_ALTC3] = {\
+               .used = altc3_used,\
+               .reg_index = altc3_ri,\
+               .control_bit = altc3_cb\
+       },\
+       .altcx[PRCM_IDX_GPIOCR_ALTC4] = {\
+               .used = altc4_used,\
+               .reg_index = altc4_ri,\
+               .control_bit = altc4_cb\
+       },\
+}
+
+/**
+ * enum prcm_gpiocr_reg_index
+ * Used to reference an PRCM GPIOCR register address.
+ */
+enum prcm_gpiocr_reg_index {
+       PRCM_IDX_GPIOCR1,
+       PRCM_IDX_GPIOCR2,
+       PRCM_IDX_GPIOCR3
+};
+/**
+ * enum prcm_gpiocr_altcx_index
+ * Used to reference an Other alternate-C function.
+ */
+enum prcm_gpiocr_altcx_index {
+       PRCM_IDX_GPIOCR_ALTC1,
+       PRCM_IDX_GPIOCR_ALTC2,
+       PRCM_IDX_GPIOCR_ALTC3,
+       PRCM_IDX_GPIOCR_ALTC4,
+       PRCM_IDX_GPIOCR_ALTC_MAX,
+};
+
+/**
+ * struct prcm_gpio_altcx - Other alternate-C function
+ * @used: other alternate-C function availability
+ * @reg_index: PRCM GPIOCR register index used to control the function
+ * @control_bit: PRCM GPIOCR bit used to control the function
+ */
+struct prcm_gpiocr_altcx {
+       bool used:1;
+       u8 reg_index:2;
+       u8 control_bit:5;
+} __packed;
+
+/**
+ * struct prcm_gpio_altcx_pin_desc - Other alternate-C pin
+ * @pin: The pin number
+ * @altcx: array of other alternate-C[1-4] functions
+ */
+struct prcm_gpiocr_altcx_pin_desc {
+       unsigned short pin;
+       struct prcm_gpiocr_altcx altcx[PRCM_IDX_GPIOCR_ALTC_MAX];
+};
+
 /**
  * struct nmk_function - Nomadik pinctrl mux function
  * @name: The name of the function, exported to pinctrl core.
@@ -50,6 +122,9 @@ struct nmk_pingroup {
  * @nfunction: The number of entries in @functions.
  * @groups:    An array describing all pin groups the pin SoC supports.
  * @ngroups:   The number of entries in @groups.
+ * @altcx_pins:        The pins that support Other alternate-C function on this SoC
+ * @npins_altcx: The number of Other alternate-C pins
+ * @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC
  */
 struct nmk_pinctrl_soc_data {
        struct pinctrl_gpio_range *gpio_ranges;
@@ -60,6 +135,9 @@ struct nmk_pinctrl_soc_data {
        unsigned nfunctions;
        const struct nmk_pingroup *groups;
        unsigned ngroups;
+       const struct prcm_gpiocr_altcx_pin_desc *altcx_pins;
+       unsigned npins_altcx;
+       const u16 *prcm_gpiocr_registers;
 };
 
 #ifdef CONFIG_PINCTRL_STN8815
index 2944ff88fdc0b2ea9705850e080a755aca440a8d..f4abfe238f98cb6bb6a4c53607bd4adf2a447ebc 100644 (file)
@@ -478,7 +478,6 @@ static void xencons_backend_changed(struct xenbus_device *dev,
        case XenbusStateInitialising:
        case XenbusStateInitialised:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -488,6 +487,10 @@ static void xencons_backend_changed(struct xenbus_device *dev,
                xenbus_switch_state(dev, XenbusStateConnected);
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 131dec04794ee3ee1af70c2fd3f1dd2220774070..48220e129f854435292065c5e928f95d982a4ad3 100644 (file)
@@ -48,6 +48,7 @@
 #include <xen/xenbus.h>
 #include <xen/xen.h>
 #include "xenbus_comms.h"
+#include <asm/xen/hypervisor.h>
 
 struct xs_stored_msg {
        struct list_head list;
@@ -618,7 +619,24 @@ static struct xenbus_watch *find_watch(const char *token)
 
        return NULL;
 }
+/*
+ * Certain older XenBus toolstack cannot handle reading values that are
+ * not populated. Some Xen 3.4 installation are incapable of doing this
+ * so if we are running on anything older than 4 do not attempt to read
+ * control/platform-feature-xs_reset_watches.
+ */
+static bool xen_strict_xenbus_quirk()
+{
+       uint32_t eax, ebx, ecx, edx, base;
+
+       base = xen_cpuid_base();
+       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
 
+       if ((eax >> 16) < 4)
+               return true;
+       return false;
+
+}
 static void xs_reset_watches(void)
 {
        int err, supported = 0;
@@ -626,6 +644,9 @@ static void xs_reset_watches(void)
        if (!xen_hvm_domain() || xen_initial_domain())
                return;
 
+       if (xen_strict_xenbus_quirk())
+               return;
+
        err = xenbus_scanf(XBT_NIL, "control",
                        "platform-feature-xs_reset_watches", "%d", &supported);
        if (err != 1 || !supported)
index 96c5c249b08628309e860367e11470e9ae5bd0e9..9069694e70eb9eee8b1bf4e229f29f7959ce3b46 100644 (file)
@@ -21,7 +21,6 @@ enum alarmtimer_restart {
 
 #define ALARMTIMER_STATE_INACTIVE      0x00
 #define ALARMTIMER_STATE_ENQUEUED      0x01
-#define ALARMTIMER_STATE_CALLBACK      0x02
 
 /**
  * struct alarm - Alarm timer structure
@@ -35,6 +34,7 @@ enum alarmtimer_restart {
  */
 struct alarm {
        struct timerqueue_node  node;
+       struct hrtimer          timer;
        enum alarmtimer_restart (*function)(struct alarm *, ktime_t now);
        enum alarmtimer_type    type;
        int                     state;
@@ -43,39 +43,12 @@ struct alarm {
 
 void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
                enum alarmtimer_restart (*function)(struct alarm *, ktime_t));
-void alarm_start(struct alarm *alarm, ktime_t start);
+int alarm_start(struct alarm *alarm, ktime_t start);
 int alarm_try_to_cancel(struct alarm *alarm);
 int alarm_cancel(struct alarm *alarm);
 
 u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);
 
-/*
- * A alarmtimer is active, when it is enqueued into timerqueue or the
- * callback function is running.
- */
-static inline int alarmtimer_active(const struct alarm *timer)
-{
-       return timer->state != ALARMTIMER_STATE_INACTIVE;
-}
-
-/*
- * Helper function to check, whether the timer is on one of the queues
- */
-static inline int alarmtimer_is_queued(struct alarm *timer)
-{
-       return timer->state & ALARMTIMER_STATE_ENQUEUED;
-}
-
-/*
- * Helper function to check, whether the timer is running the callback
- * function
- */
-static inline int alarmtimer_callback_running(struct alarm *timer)
-{
-       return timer->state & ALARMTIMER_STATE_CALLBACK;
-}
-
-
 /* Provide way to access the rtc device being used by alarmtimers */
 struct rtc_device *alarmtimer_get_rtcdev(void);
 
index fbe89e17124e9924bc3185e7a571d91bcada28f5..4dceaf8ae1525e57a0d6f7911e8dddac7047da4d 100644 (file)
@@ -319,22 +319,6 @@ static inline void __clocksource_updatefreq_khz(struct clocksource *cs, u32 khz)
        __clocksource_updatefreq_scale(cs, 1000, khz);
 }
 
-#ifdef CONFIG_GENERIC_TIME_VSYSCALL
-extern void
-update_vsyscall(struct timespec *ts, struct timespec *wtm,
-                       struct clocksource *c, u32 mult);
-extern void update_vsyscall_tz(void);
-#else
-static inline void
-update_vsyscall(struct timespec *ts, struct timespec *wtm,
-                       struct clocksource *c, u32 mult)
-{
-}
-
-static inline void update_vsyscall_tz(void)
-{
-}
-#endif
 
 extern void timekeeping_notify(struct clocksource *clock);
 
index 20e5eac2ffd3f70688e35b7964fbdc0e172e8c4a..827cce7e33e330510c012e9857c40a77ea13b106 100644 (file)
@@ -24,6 +24,6 @@
 #define _DVBVERSION_H_
 
 #define DVB_API_VERSION 5
-#define DVB_API_VERSION_MINOR 8
+#define DVB_API_VERSION_MINOR 9
 
 #endif /*_DVBVERSION_H_*/
index 05e3c2c7a8cf81e2184f49a531a8158fa45639b4..6b87413da9d68877bf3f65f5d85023b1f9702fc4 100644 (file)
 #define SH_DIV(NOM,DEN,LSH) (   (((NOM) / (DEN)) << (LSH))              \
                              + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN))
 
-#ifdef CLOCK_TICK_RATE
 /* LATCH is used in the interval timer and ftape setup. */
-# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
+#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ)  /* For divider */
 
-/*
- * HZ is the requested value. However the CLOCK_TICK_RATE may not allow
- * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy)
- */
-# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8))
-#else
-# define SHIFTED_HZ (HZ << 8)
-#endif
+extern int register_refined_jiffies(long clock_tick_rate);
 
 /* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */
-#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8))
+#define TICK_NSEC ((NSEC_PER_SEC+HZ/2)/HZ)
 
 /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
 #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
 
-/*
- * TICK_USEC_TO_NSEC is the time between ticks in nsec assuming SHIFTED_HZ and
- * a value TUSEC for TICK_USEC (can be set bij adjtimex)
- */
-#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV(TUSEC * USER_HZ * 1000, SHIFTED_HZ, 8))
-
 /* some arch's have a small-data section that can be accessed register-relative
  * but that can only take up to, say, 4-byte variables. jiffies being part of
  * an 8-byte variable may not be correctly accessed unless we force the issue
index c45b1e8d4c2ec73ff0fe608ac2b96ba9d0d34607..bf34e17cee7f6eb9c9068d811c37dae3b8c10fe0 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
  *
- * S5P series MIPI CSI slave device support
+ * Samsung S5P/Exynos SoC series MIPI CSIS device support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #ifndef __PLAT_SAMSUNG_MIPI_CSIS_H_
 #define __PLAT_SAMSUNG_MIPI_CSIS_H_ __FILE__
 
-struct platform_device;
-
 /**
  * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
- * @clk_rate: bus clock frequency
- * @lanes: number of data lanes used
- * @alignment: data alignment in bits
- * @hs_settle: HS-RX settle time
- * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
- *                driver or true in case this regulator has no enable function
- * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ * @clk_rate:    bus clock frequency
+ * @wclk_source: CSI wrapper clock selection: 0 - bus clock, 1 - ext. SCLK_CAM
+ * @lanes:       number of data lanes used
+ * @hs_settle:   HS-RX settle time
  */
 struct s5p_platform_mipi_csis {
        unsigned long clk_rate;
+       u8 wclk_source;
        u8 lanes;
-       u8 alignment;
        u8 hs_settle;
-       bool fixed_phy_vdd;
-       int (*phy_enable)(struct platform_device *pdev, bool on);
 };
 
 /**
  * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
- * @pdev: MIPI-CSIS platform device
- * @on: true to enable D-PHY and deassert its reset
- *     false to disable D-PHY
+ * @id:     MIPI-CSIS harware instance index (0...1)
+ * @on:     true to enable D-PHY and deassert its reset
+ *          false to disable D-PHY
+ * @return: 0 on success, or negative error code on failure
  */
-int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
+int s5p_csis_phy_enable(int id, bool on);
 
 #endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
new file mode 100644 (file)
index 0000000..e1d558e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * You SHOULD NOT be including this unless you're vsyscall
+ * handling code or timekeeping internal code!
+ */
+
+#ifndef _LINUX_TIMEKEEPER_INTERNAL_H
+#define _LINUX_TIMEKEEPER_INTERNAL_H
+
+#include <linux/clocksource.h>
+#include <linux/jiffies.h>
+#include <linux/time.h>
+
+/* Structure holding internal timekeeping values. */
+struct timekeeper {
+       /* Current clocksource used for timekeeping. */
+       struct clocksource      *clock;
+       /* NTP adjusted clock multiplier */
+       u32                     mult;
+       /* The shift value of the current clocksource. */
+       u32                     shift;
+       /* Number of clock cycles in one NTP interval. */
+       cycle_t                 cycle_interval;
+       /* Number of clock shifted nano seconds in one NTP interval. */
+       u64                     xtime_interval;
+       /* shifted nano seconds left over when rounding cycle_interval */
+       s64                     xtime_remainder;
+       /* Raw nano seconds accumulated per NTP interval. */
+       u32                     raw_interval;
+
+       /* Current CLOCK_REALTIME time in seconds */
+       u64                     xtime_sec;
+       /* Clock shifted nano seconds */
+       u64                     xtime_nsec;
+
+       /* Difference between accumulated time and NTP time in ntp
+        * shifted nano seconds. */
+       s64                     ntp_error;
+       /* Shift conversion between clock shifted nano seconds and
+        * ntp shifted nano seconds. */
+       u32                     ntp_error_shift;
+
+       /*
+        * wall_to_monotonic is what we need to add to xtime (or xtime corrected
+        * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
+        * at zero at system boot time, so wall_to_monotonic will be negative,
+        * however, we will ALWAYS keep the tv_nsec part positive so we can use
+        * the usual normalization.
+        *
+        * wall_to_monotonic is moved after resume from suspend for the
+        * monotonic time not to jump. We need to add total_sleep_time to
+        * wall_to_monotonic to get the real boot based time offset.
+        *
+        * - wall_to_monotonic is no longer the boot time, getboottime must be
+        * used instead.
+        */
+       struct timespec         wall_to_monotonic;
+       /* Offset clock monotonic -> clock realtime */
+       ktime_t                 offs_real;
+       /* time spent in suspend */
+       struct timespec         total_sleep_time;
+       /* Offset clock monotonic -> clock boottime */
+       ktime_t                 offs_boot;
+       /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
+       struct timespec         raw_time;
+       /* Seqlock for all timekeeper values */
+       seqlock_t               lock;
+};
+
+static inline struct timespec tk_xtime(struct timekeeper *tk)
+{
+       struct timespec ts;
+
+       ts.tv_sec = tk->xtime_sec;
+       ts.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
+       return ts;
+}
+
+
+#ifdef CONFIG_GENERIC_TIME_VSYSCALL
+
+extern void update_vsyscall(struct timekeeper *tk);
+extern void update_vsyscall_tz(void);
+
+#elif defined(CONFIG_GENERIC_TIME_VSYSCALL_OLD)
+
+extern void update_vsyscall_old(struct timespec *ts, struct timespec *wtm,
+                               struct clocksource *c, u32 mult);
+extern void update_vsyscall_tz(void);
+
+static inline void update_vsyscall(struct timekeeper *tk)
+{
+       struct timespec xt;
+
+       xt = tk_xtime(tk);
+       update_vsyscall_old(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);
+}
+
+#else
+
+static inline void update_vsyscall(struct timekeeper *tk)
+{
+}
+static inline void update_vsyscall_tz(void)
+{
+}
+#endif
+
+#endif /* _LINUX_TIMEKEEPER_INTERNAL_H */
index 421d24c7f686ad407129bdd20fd6c7245cf3bbe6..f56c945cecd4ecb008eb713e1989b5af920dad3e 100644 (file)
@@ -349,6 +349,7 @@ enum v4l2_mpeg_video_multi_slice_mode {
 #define V4L2_CID_MPEG_VIDEO_VBV_SIZE                   (V4L2_CID_MPEG_BASE+222)
 #define V4L2_CID_MPEG_VIDEO_DEC_PTS                    (V4L2_CID_MPEG_BASE+223)
 #define V4L2_CID_MPEG_VIDEO_DEC_FRAME                  (V4L2_CID_MPEG_BASE+224)
+#define V4L2_CID_MPEG_VIDEO_VBV_DELAY                  (V4L2_CID_MPEG_BASE+225)
 
 #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP            (V4L2_CID_MPEG_BASE+300)
 #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP            (V4L2_CID_MPEG_BASE+301)
@@ -439,6 +440,46 @@ enum v4l2_mpeg_video_h264_vui_sar_idc {
        V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1            = 16,
        V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED       = 17,
 };
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING             (V4L2_CID_MPEG_BASE+368)
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0                (V4L2_CID_MPEG_BASE+369)
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE       (V4L2_CID_MPEG_BASE+370)
+enum v4l2_mpeg_video_h264_sei_fp_arrangement_type {
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHECKERBOARD       = 0,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN             = 1,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW                = 2,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE       = 3,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM         = 4,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL           = 5,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO                   (V4L2_CID_MPEG_BASE+371)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE          (V4L2_CID_MPEG_BASE+372)
+enum v4l2_mpeg_video_h264_fmo_map_type {
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES            = 0,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES              = 1,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER     = 2,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT                       = 3,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN                   = 4,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN                     = 5,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT                      = 6,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP       (V4L2_CID_MPEG_BASE+373)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION  (V4L2_CID_MPEG_BASE+374)
+enum v4l2_mpeg_video_h264_fmo_change_dir {
+       V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT       = 0,
+       V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT        = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE       (V4L2_CID_MPEG_BASE+375)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH                (V4L2_CID_MPEG_BASE+376)
+#define V4L2_CID_MPEG_VIDEO_H264_ASO                   (V4L2_CID_MPEG_BASE+377)
+#define V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER       (V4L2_CID_MPEG_BASE+378)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING           (V4L2_CID_MPEG_BASE+379)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE      (V4L2_CID_MPEG_BASE+380)
+enum v4l2_mpeg_video_h264_hierarchical_coding_type {
+       V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B      = 0,
+       V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P      = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER     (V4L2_CID_MPEG_BASE+381)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP  (V4L2_CID_MPEG_BASE+382)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP   (V4L2_CID_MPEG_BASE+400)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP   (V4L2_CID_MPEG_BASE+401)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP   (V4L2_CID_MPEG_BASE+402)
@@ -757,5 +798,6 @@ enum v4l2_jpeg_chroma_subsampling {
 
 #define V4L2_CID_LINK_FREQ                     (V4L2_CID_IMAGE_PROC_CLASS_BASE + 1)
 #define V4L2_CID_PIXEL_RATE                    (V4L2_CID_IMAGE_PROC_CLASS_BASE + 2)
+#define V4L2_CID_TEST_PATTERN                  (V4L2_CID_IMAGE_PROC_CLASS_BASE + 3)
 
 #endif
index 5ea7f753a3488757ab7f2a06132fd7a8b2ce46e8..7d64e0e1a18b2543b7bc35ad20e202e6b1282d60 100644 (file)
@@ -92,6 +92,11 @@ enum v4l2_mbus_pixelcode {
 
        /* JPEG compressed formats - next is 0x4002 */
        V4L2_MBUS_FMT_JPEG_1X8 = 0x4001,
+
+       /* Vendor specific formats - next is 0x5002 */
+
+       /* S5C73M3 sensor specific interleaved UYVY and JPEG */
+       V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8 = 0x5001,
 };
 
 /**
index 61395ef85a003a55ff8ce390bf52b582e4454db3..873adbe82988a8415cd25da1b4d7951873e22762 100644 (file)
@@ -366,7 +366,9 @@ struct v4l2_pix_format {
 
 /* two non contiguous planes - one Y, one Cr + Cb interleaved  */
 #define V4L2_PIX_FMT_NV12M   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
+#define V4L2_PIX_FMT_NV21M   v4l2_fourcc('N', 'M', '2', '1') /* 21  Y/CrCb 4:2:0  */
 #define V4L2_PIX_FMT_NV12MT  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 16x16 macroblocks */
 
 /* three non contiguous planes - Y, Cb, Cr */
 #define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
@@ -403,6 +405,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
 #define V4L2_PIX_FMT_H264     v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
 #define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
+#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
 #define V4L2_PIX_FMT_H263     v4l2_fourcc('H', '2', '6', '3') /* H263          */
 #define V4L2_PIX_FMT_MPEG1    v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES     */
 #define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
@@ -410,6 +413,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_XVID     v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid           */
 #define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
 #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
+#define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -437,6 +441,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
 #define V4L2_PIX_FMT_JPGL      v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
+#define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
index 8bc1b3c0e6790501d1853e59841867f5709afed4..a7ca4884c46cc8a386a42a7d9f9eaae6c35dc8ba 100644 (file)
@@ -35,7 +35,7 @@ struct osd_config_info {
 struct vpbe_output {
        struct v4l2_output output;
        /*
-        * If output capabilities include dv_preset, list supported presets
+        * If output capabilities include dv_timings, list supported timings
         * below
         */
        char *subdev_name;
@@ -120,16 +120,16 @@ struct vpbe_device_ops {
        unsigned int (*get_output)(struct vpbe_device *vpbe_dev);
 
        /* Set DV preset at current output */
-       int (*s_dv_preset)(struct vpbe_device *vpbe_dev,
-                          struct v4l2_dv_preset *dv_preset);
+       int (*s_dv_timings)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_timings *dv_timings);
 
        /* Get DV presets supported at the output */
-       int (*g_dv_preset)(struct vpbe_device *vpbe_dev,
-                          struct v4l2_dv_preset *dv_preset);
+       int (*g_dv_timings)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_timings *dv_timings);
 
        /* Enumerate the DV Presets supported at the output */
-       int (*enum_dv_presets)(struct vpbe_device *vpbe_dev,
-                              struct v4l2_dv_enum_preset *preset_info);
+       int (*enum_dv_timings)(struct vpbe_device *vpbe_dev,
+                              struct v4l2_enum_dv_timings *timings_info);
 
        /* Set std at the output */
        int (*s_std)(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id);
index 727f55170e41cc7dd74accb196b4a75776ed0ce2..9b85396514be33390705fdc34c4bad826fd609e1 100644 (file)
@@ -32,11 +32,6 @@ enum vpbe_enc_timings_type {
        VPBE_ENC_TIMINGS_INVALID = 0x8,
 };
 
-union vpbe_timings {
-       v4l2_std_id std_id;
-       unsigned int dv_preset;
-};
-
 /*
  * struct vpbe_enc_mode_info
  * @name: ptr to name string of the standard, "NTSC", "PAL" etc
@@ -73,7 +68,8 @@ union vpbe_timings {
 struct vpbe_enc_mode_info {
        unsigned char *name;
        enum vpbe_enc_timings_type timings_type;
-       union vpbe_timings timings;
+       v4l2_std_id std_id;
+       struct v4l2_dv_timings dv_timings;
        unsigned int interlaced;
        unsigned int xres;
        unsigned int yres;
index 6b57334f402996341e584fcc0177054140663ba5..cc78c2eb16da25a689ece25ad1dfc931c6dcf211 100644 (file)
@@ -32,7 +32,7 @@ struct venc_platform_data {
        int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
                            int field);
        int (*setup_clock)(enum vpbe_enc_timings_type type,
-                          unsigned int mode);
+                          unsigned int pixclock);
        int (*setup_if_config)(enum v4l2_mbus_pixelcode pixcode);
        /* Number of LCD outputs supported */
        int num_lcd_outputs;
index d8f6ab1943e4e492679b1b4ae58ac1244496cc72..3882e0675ccfd45e718dbd8dc38bedd51af02120 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 
 #define VPIF_CAPTURE_MAX_CHANNELS      2
+#define VPIF_DISPLAY_MAX_CHANNELS      2
 
 enum vpif_if_type {
        VPIF_IF_BT656,
@@ -37,29 +38,38 @@ struct vpif_interface {
 struct vpif_subdev_info {
        const char *name;
        struct i2c_board_info board_info;
-       u32 input;
-       u32 output;
-       unsigned can_route:1;
-       struct vpif_interface vpif_if;
+};
+
+struct vpif_output {
+       struct v4l2_output output;
+       const char *subdev_name;
+       u32 input_route;
+       u32 output_route;
+};
+
+struct vpif_display_chan_config {
+       const struct vpif_output *outputs;
+       int output_count;
+       bool clip_en;
 };
 
 struct vpif_display_config {
        int (*set_clock)(int, int);
        struct vpif_subdev_info *subdevinfo;
        int subdev_count;
-       const char **output;
-       int output_count;
+       struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
        const char *card_name;
-       bool ch2_clip_en;
-       bool ch3_clip_en;
 };
 
 struct vpif_input {
        struct v4l2_input input;
        const char *subdev_name;
+       u32 input_route;
+       u32 output_route;
 };
 
 struct vpif_capture_chan_config {
+       struct vpif_interface vpif_if;
        const struct vpif_input *inputs;
        int input_count;
 };
index 09421a611d73df78ed1d3d6af80571e0511956ce..eaea62a382f886a414b803d4f86119117a46f262 100644 (file)
@@ -30,7 +30,6 @@ struct i2c_board_info;
  * @board_info: pointer to I2C subdevice's board info
  * @clk_frequency: frequency of the clock the host interface provides to sensor
  * @bus_type: determines bus type, MIPI, ITU-R BT.601 etc.
- * @csi_data_align: MIPI-CSI interface data alignment in bits
  * @i2c_bus_num: i2c control bus id the sensor is attached to
  * @mux_id: FIMC camera interface multiplexer index (separate for MIPI and ITU)
  * @clk_id: index of the SoC peripheral clock for sensors
@@ -40,7 +39,6 @@ struct s5p_fimc_isp_info {
        struct i2c_board_info *board_info;
        unsigned long clk_frequency;
        enum cam_bus_type bus_type;
-       u16 csi_data_align;
        u16 i2c_bus_num;
        u16 mux_id;
        u16 flags;
index 801adb466bd25cdde14eac5e7314ed4061f52707..96509119f28f42daa6ce3794cea050f4d8768603 100644 (file)
@@ -351,6 +351,29 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
                        const struct v4l2_ctrl_ops *ops,
                        u32 id, s32 max, s32 mask, s32 def);
 
+/** v4l2_ctrl_new_std_menu_items() - Create a new standard V4L2 menu control
+  * with driver specific menu.
+  * @hdl:      The control handler.
+  * @ops:      The control ops.
+  * @id:       The control ID.
+  * @max:      The control's maximum value.
+  * @mask:     The control's skip mask for menu controls. This makes it
+  *            easy to skip menu items that are not valid. If bit X is set,
+  *            then menu item X is skipped. Of course, this only works for
+  *            menus with <= 32 menu items. There are no menus that come
+  *            close to that number, so this is OK. Should we ever need more,
+  *            then this will have to be extended to a u64 or a bit array.
+  * @def:      The control's default value.
+  * @qmenu:    The new menu.
+  *
+  * Same as v4l2_ctrl_new_std_menu(), but @qmenu will be the driver specific
+  * menu of this control.
+  *
+  */
+struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
+                       const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
+                       s32 mask, s32 def, const char * const *qmenu);
+
 /** v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
   * @hdl:      The control handler.
   * @ops:      The control ops.
index 2ecd7377153bb9bf7dbf5f5706466c6bf42bfdbf..b137a5e1151a5be0ad55c036f721ff6cb4bbe4e4 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef _V4L2_SUBDEV_H
 #define _V4L2_SUBDEV_H
 
+#include <linux/types.h>
 #include <linux/v4l2-subdev.h>
 #include <media/media-entity.h>
 #include <media/v4l2-common.h>
@@ -45,6 +46,7 @@ struct v4l2_fh;
 struct v4l2_subdev;
 struct v4l2_subdev_fh;
 struct tuner_setup;
+struct v4l2_mbus_frame_desc;
 
 /* decode_vbi_line */
 struct v4l2_decode_vbi_line {
@@ -226,6 +228,36 @@ struct v4l2_subdev_audio_ops {
        int (*s_stream)(struct v4l2_subdev *sd, int enable);
 };
 
+/* Indicates the @length field specifies maximum data length. */
+#define V4L2_MBUS_FRAME_DESC_FL_LEN_MAX                (1U << 0)
+/* Indicates user defined data format, i.e. non standard frame format. */
+#define V4L2_MBUS_FRAME_DESC_FL_BLOB           (1U << 1)
+
+/**
+ * struct v4l2_mbus_frame_desc_entry - media bus frame description structure
+ * @flags: V4L2_MBUS_FRAME_DESC_FL_* flags
+ * @pixelcode: media bus pixel code, valid if FRAME_DESC_FL_BLOB is not set
+ * @length: number of octets per frame, valid for compressed or unspecified
+ *          formats
+ */
+struct v4l2_mbus_frame_desc_entry {
+       u16 flags;
+       u32 pixelcode;
+       u32 length;
+};
+
+#define V4L2_FRAME_DESC_ENTRY_MAX      4
+
+/**
+ * struct v4l2_mbus_frame_desc - media bus data frame description
+ * @entry: frame descriptors array
+ * @num_entries: number of entries in @entry array
+ */
+struct v4l2_mbus_frame_desc {
+       struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
+       unsigned short num_entries;
+};
+
 /*
    s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
        video input devices.
@@ -274,6 +306,10 @@ struct v4l2_subdev_audio_ops {
    s_mbus_config: set a certain mediabus configuration. This operation is added
        for compatibility with soc-camera drivers and should not be used by new
        software.
+
+   s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev
+       can adjust @size to a lower value and must not write more data to the
+       buffer starting at @data than the original value of @size.
  */
 struct v4l2_subdev_video_ops {
        int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
@@ -327,6 +363,8 @@ struct v4l2_subdev_video_ops {
                             struct v4l2_mbus_config *cfg);
        int (*s_mbus_config)(struct v4l2_subdev *sd,
                             const struct v4l2_mbus_config *cfg);
+       int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf,
+                          unsigned int *size);
 };
 
 /*
@@ -455,6 +493,12 @@ struct v4l2_subdev_ir_ops {
                                struct v4l2_subdev_ir_parameters *params);
 };
 
+/**
+ * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations
+ * @get_frame_desc: get the current low level media bus frame parameters.
+ * @get_frame_desc: set the low level media bus frame parameters, @fd array
+ *                  may be adjusted by the subdev driver to device capabilities.
+ */
 struct v4l2_subdev_pad_ops {
        int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                              struct v4l2_subdev_mbus_code_enum *code);
@@ -483,6 +527,10 @@ struct v4l2_subdev_pad_ops {
                             struct v4l2_subdev_format *source_fmt,
                             struct v4l2_subdev_format *sink_fmt);
 #endif /* CONFIG_MEDIA_CONTROLLER */
+       int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
+                             struct v4l2_mbus_frame_desc *fd);
+       int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
+                             struct v4l2_mbus_frame_desc *fd);
 };
 
 struct v4l2_subdev_ops {
index a4827f46ee97fffd0021874dabc49877ae67ca4b..956a04682865bbf19b456448b83af6112240dd6f 100644 (file)
@@ -43,4 +43,23 @@ struct xen_hvm_pagetable_dying {
 typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
 DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t);
  
+enum hvmmem_type_t {
+    HVMMEM_ram_rw,             /* Normal read/write guest RAM */
+    HVMMEM_ram_ro,             /* Read-only; writes are discarded */
+    HVMMEM_mmio_dm,            /* Reads and write go to the device model */
+};
+
+#define HVMOP_get_mem_type    15
+/* Return hvmmem_type_t for the specified pfn. */
+struct xen_hvm_get_mem_type {
+    /* Domain to be queried. */
+    domid_t domid;
+    /* OUT variable. */
+    uint16_t mem_type;
+    uint16_t pad[2]; /* align next field on 8-byte boundary */
+    /* IN variable. */
+    uint64_t pfn;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_get_mem_type);
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
index 4c93533da42cbd66fd29f84b4e66c8c7e881c9ff..89e4cf672dfe90e0d1fb75fb667d551dc7094f93 100644 (file)
@@ -496,6 +496,12 @@ config RCU_USER_QS
          excluded from the global RCU state machine and thus doesn't
          to keep the timer tick on for RCU.
 
+         Unless you want to hack and help the development of the full
+         tickless feature, you shouldn't enable this option. It adds
+         unnecessary overhead.
+
+         If unsure say N
+
 config RCU_USER_QS_FORCE
        bool "Force userspace extended QS by default"
        depends on RCU_USER_QS
@@ -504,6 +510,12 @@ config RCU_USER_QS_FORCE
          test this feature that treats userspace as an extended quiescent
          state until we have a real user like a full adaptive nohz option.
 
+         Unless you want to hack and help the development of the full
+         tickless feature, you shouldn't enable this option. It adds
+         unnecessary overhead.
+
+         If unsure say N
+
 config RCU_FANOUT
        int "Tree-based hierarchical RCU fanout value"
        range 2 64 if 64BIT
index 49a77727db42603e8e0ac963416d0f6b57823636..4e69e24d3d7d94b4c895735765e06f2f47a95db0 100644 (file)
@@ -148,7 +148,8 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
  * @host_data: Controller private data pointer
  *
  * Allocates a legacy irq_domain if irq_base is positive or a linear
- * domain otherwise.
+ * domain otherwise. For the legacy domain, IRQ descriptors will also
+ * be allocated.
  *
  * This is intended to implement the expected behaviour for most
  * interrupt controllers which is that a linear mapping should
@@ -162,11 +163,33 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
                                         const struct irq_domain_ops *ops,
                                         void *host_data)
 {
-       if (first_irq > 0)
-               return irq_domain_add_legacy(of_node, size, first_irq, 0,
+       if (first_irq > 0) {
+               int irq_base;
+
+               if (IS_ENABLED(CONFIG_SPARSE_IRQ)) {
+                       /*
+                        * Set the descriptor allocator to search for a
+                        * 1-to-1 mapping, such as irq_alloc_desc_at().
+                        * Use of_node_to_nid() which is defined to
+                        * numa_node_id() on platforms that have no custom
+                        * implementation.
+                        */
+                       irq_base = irq_alloc_descs(first_irq, first_irq, size,
+                                                  of_node_to_nid(of_node));
+                       if (irq_base < 0) {
+                               WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+                                    first_irq);
+                               irq_base = first_irq;
+                       }
+               } else
+                       irq_base = first_irq;
+
+               return irq_domain_add_legacy(of_node, size, irq_base, 0,
                                             ops, host_data);
-       else
-               return irq_domain_add_linear(of_node, size, ops, host_data);
+       }
+
+       /* A linear domain is the default */
+       return irq_domain_add_linear(of_node, size, ops, host_data);
 }
 
 /**
index 4fb2376ddf0660575970a29db0637ac4c70c2020..74df86bd9204aef5ec9d14ca8b4b0094777bef87 100644 (file)
@@ -74,6 +74,7 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
        .orphan_nxttail = &sname##_state.orphan_nxtlist, \
        .orphan_donetail = &sname##_state.orphan_donelist, \
        .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
+       .onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \
        .name = #sname, \
 }
 
@@ -1197,7 +1198,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
        raw_spin_unlock_irq(&rnp->lock);
 
        /* Exclude any concurrent CPU-hotplug operations. */
-       get_online_cpus();
+       mutex_lock(&rsp->onoff_mutex);
 
        /*
         * Set the quiescent-state-needed bits in all the rcu_node
@@ -1234,7 +1235,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
                cond_resched();
        }
 
-       put_online_cpus();
+       mutex_unlock(&rsp->onoff_mutex);
        return 1;
 }
 
@@ -1700,6 +1701,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
        /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */
 
        /* Exclude any attempts to start a new grace period. */
+       mutex_lock(&rsp->onoff_mutex);
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
 
        /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
@@ -1744,6 +1746,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
        init_callback_list(rdp);
        /* Disallow further callbacks on this CPU. */
        rdp->nxttail[RCU_NEXT_TAIL] = NULL;
+       mutex_unlock(&rsp->onoff_mutex);
 }
 
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
@@ -2648,6 +2651,9 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
+       /* Exclude new grace periods. */
+       mutex_lock(&rsp->onoff_mutex);
+
        /* Set up local state, ensuring consistent view of global state. */
        raw_spin_lock_irqsave(&rnp->lock, flags);
        rdp->beenonline = 1;     /* We have now been online. */
@@ -2662,14 +2668,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
        rcu_prepare_for_idle_init(cpu);
        raw_spin_unlock(&rnp->lock);            /* irqs remain disabled. */
 
-       /*
-        * A new grace period might start here.  If so, we won't be part
-        * of it, but that is OK, as we are currently in a quiescent state.
-        */
-
-       /* Exclude any attempts to start a new GP on large systems. */
-       raw_spin_lock(&rsp->onofflock);         /* irqs already disabled. */
-
        /* Add CPU to rcu_node bitmasks. */
        rnp = rdp->mynode;
        mask = rdp->grpmask;
@@ -2693,8 +2691,9 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
                raw_spin_unlock(&rnp->lock); /* irqs already disabled. */
                rnp = rnp->parent;
        } while (rnp != NULL && !(rnp->qsmaskinit & mask));
+       local_irq_restore(flags);
 
-       raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
+       mutex_unlock(&rsp->onoff_mutex);
 }
 
 static void __cpuinit rcu_prepare_cpu(int cpu)
index 5faf05d683265222127e6496668b6821018ff999..a240f032848eec8d00e156da54fce3cd24a4b525 100644 (file)
@@ -394,11 +394,17 @@ struct rcu_state {
        struct rcu_head **orphan_donetail;      /* Tail of above. */
        long qlen_lazy;                         /* Number of lazy callbacks. */
        long qlen;                              /* Total number of callbacks. */
+       /* End of fields guarded by onofflock. */
+
+       struct mutex onoff_mutex;               /* Coordinate hotplug & GPs. */
+
        struct mutex barrier_mutex;             /* Guards barrier fields. */
        atomic_t barrier_cpu_count;             /* # CPUs waiting on. */
        struct completion barrier_completion;   /* Wake at barrier end. */
        unsigned long n_barrier_done;           /* ++ at start and end of */
                                                /*  _rcu_barrier(). */
+       /* End of fields guarded by barrier_mutex. */
+
        unsigned long jiffies_force_qs;         /* Time at which to invoke */
                                                /*  force_quiescent_state(). */
        unsigned long n_force_qs;               /* Number of calls to */
index bd7c39450b1b160714e9abc2f690a7ac3e086739..2d8927fda712f5ee1e19f1fe364fbad557d8a736 100644 (file)
@@ -6122,6 +6122,17 @@ static void sched_init_numa(void)
         * numbers.
         */
 
+       /*
+        * Here, we should temporarily reset sched_domains_numa_levels to 0.
+        * If it fails to allocate memory for array sched_domains_numa_masks[][],
+        * the array will contain less then 'level' members. This could be
+        * dangerous when we use it to iterate array sched_domains_numa_masks[][]
+        * in other functions.
+        *
+        * We reset it to 'level' at the end of this function.
+        */
+       sched_domains_numa_levels = 0;
+
        sched_domains_numa_masks = kzalloc(sizeof(void *) * level, GFP_KERNEL);
        if (!sched_domains_numa_masks)
                return;
@@ -6176,11 +6187,68 @@ static void sched_init_numa(void)
        }
 
        sched_domain_topology = tl;
+
+       sched_domains_numa_levels = level;
+}
+
+static void sched_domains_numa_masks_set(int cpu)
+{
+       int i, j;
+       int node = cpu_to_node(cpu);
+
+       for (i = 0; i < sched_domains_numa_levels; i++) {
+               for (j = 0; j < nr_node_ids; j++) {
+                       if (node_distance(j, node) <= sched_domains_numa_distance[i])
+                               cpumask_set_cpu(cpu, sched_domains_numa_masks[i][j]);
+               }
+       }
+}
+
+static void sched_domains_numa_masks_clear(int cpu)
+{
+       int i, j;
+       for (i = 0; i < sched_domains_numa_levels; i++) {
+               for (j = 0; j < nr_node_ids; j++)
+                       cpumask_clear_cpu(cpu, sched_domains_numa_masks[i][j]);
+       }
+}
+
+/*
+ * Update sched_domains_numa_masks[level][node] array when new cpus
+ * are onlined.
+ */
+static int sched_domains_numa_masks_update(struct notifier_block *nfb,
+                                          unsigned long action,
+                                          void *hcpu)
+{
+       int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_ONLINE:
+               sched_domains_numa_masks_set(cpu);
+               break;
+
+       case CPU_DEAD:
+               sched_domains_numa_masks_clear(cpu);
+               break;
+
+       default:
+               return NOTIFY_DONE;
+       }
+
+       return NOTIFY_OK;
 }
 #else
 static inline void sched_init_numa(void)
 {
 }
+
+static int sched_domains_numa_masks_update(struct notifier_block *nfb,
+                                          unsigned long action,
+                                          void *hcpu)
+{
+       return 0;
+}
 #endif /* CONFIG_NUMA */
 
 static int __sdt_alloc(const struct cpumask *cpu_map)
@@ -6629,6 +6697,7 @@ void __init sched_init_smp(void)
        mutex_unlock(&sched_domains_mutex);
        put_online_cpus();
 
+       hotcpu_notifier(sched_domains_numa_masks_update, CPU_PRI_SCHED_ACTIVE);
        hotcpu_notifier(cpuset_cpu_active, CPU_PRI_CPUSET_ACTIVE);
        hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE);
 
index ba744cf80696203b65406c7aef8faae3a23048d0..d226c6a3fd28933d02edd485a9c8353db2212c02 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/export.h>
 #include <linux/timex.h>
 #include <linux/capability.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/errno.h>
 #include <linux/syscalls.h>
 #include <linux/security.h>
index fd42bd452b7528642495e6b619715ccb424b5e2e..8601f0db12612a1e18a3a11968b9444630f94ad5 100644 (file)
@@ -16,6 +16,10 @@ config ARCH_CLOCKSOURCE_DATA
 config GENERIC_TIME_VSYSCALL
        bool
 
+# Timekeeping vsyscall support
+config GENERIC_TIME_VSYSCALL_OLD
+       bool
+
 # ktime_t scalar 64bit nsec representation
 config KTIME_SCALAR
        bool
index aa27d391bfc8b408ced23985bc4946067b5eba87..f11d83b1294992db1e13c5f9266fb14f1bbde573 100644 (file)
@@ -37,7 +37,6 @@
 static struct alarm_base {
        spinlock_t              lock;
        struct timerqueue_head  timerqueue;
-       struct hrtimer          timer;
        ktime_t                 (*gettime)(void);
        clockid_t               base_clockid;
 } alarm_bases[ALARM_NUMTYPE];
@@ -46,6 +45,8 @@ static struct alarm_base {
 static ktime_t freezer_delta;
 static DEFINE_SPINLOCK(freezer_delta_lock);
 
+static struct wakeup_source *ws;
+
 #ifdef CONFIG_RTC_CLASS
 /* rtc timer and device for setting alarm wakeups at suspend */
 static struct rtc_timer                rtctimer;
@@ -130,50 +131,35 @@ static inline void alarmtimer_rtc_timer_init(void) { }
  * @base: pointer to the base where the timer is being run
  * @alarm: pointer to alarm being enqueued.
  *
- * Adds alarm to a alarm_base timerqueue and if necessary sets
- * an hrtimer to run.
+ * Adds alarm to a alarm_base timerqueue
  *
  * Must hold base->lock when calling.
  */
 static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
 {
+       if (alarm->state & ALARMTIMER_STATE_ENQUEUED)
+               timerqueue_del(&base->timerqueue, &alarm->node);
+
        timerqueue_add(&base->timerqueue, &alarm->node);
        alarm->state |= ALARMTIMER_STATE_ENQUEUED;
-
-       if (&alarm->node == timerqueue_getnext(&base->timerqueue)) {
-               hrtimer_try_to_cancel(&base->timer);
-               hrtimer_start(&base->timer, alarm->node.expires,
-                               HRTIMER_MODE_ABS);
-       }
 }
 
 /**
- * alarmtimer_remove - Removes an alarm timer from an alarm_base timerqueue
+ * alarmtimer_dequeue - Removes an alarm timer from an alarm_base timerqueue
  * @base: pointer to the base where the timer is running
  * @alarm: pointer to alarm being removed
  *
- * Removes alarm to a alarm_base timerqueue and if necessary sets
- * a new timer to run.
+ * Removes alarm to a alarm_base timerqueue
  *
  * Must hold base->lock when calling.
  */
-static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
+static void alarmtimer_dequeue(struct alarm_base *base, struct alarm *alarm)
 {
-       struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue);
-
        if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED))
                return;
 
        timerqueue_del(&base->timerqueue, &alarm->node);
        alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
-
-       if (next == &alarm->node) {
-               hrtimer_try_to_cancel(&base->timer);
-               next = timerqueue_getnext(&base->timerqueue);
-               if (!next)
-                       return;
-               hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS);
-       }
 }
 
 
@@ -188,42 +174,23 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
  */
 static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
 {
-       struct alarm_base *base = container_of(timer, struct alarm_base, timer);
-       struct timerqueue_node *next;
+       struct alarm *alarm = container_of(timer, struct alarm, timer);
+       struct alarm_base *base = &alarm_bases[alarm->type];
        unsigned long flags;
-       ktime_t now;
        int ret = HRTIMER_NORESTART;
        int restart = ALARMTIMER_NORESTART;
 
        spin_lock_irqsave(&base->lock, flags);
-       now = base->gettime();
-       while ((next = timerqueue_getnext(&base->timerqueue))) {
-               struct alarm *alarm;
-               ktime_t expired = next->expires;
-
-               if (expired.tv64 > now.tv64)
-                       break;
-
-               alarm = container_of(next, struct alarm, node);
-
-               timerqueue_del(&base->timerqueue, &alarm->node);
-               alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
-
-               alarm->state |= ALARMTIMER_STATE_CALLBACK;
-               spin_unlock_irqrestore(&base->lock, flags);
-               if (alarm->function)
-                       restart = alarm->function(alarm, now);
-               spin_lock_irqsave(&base->lock, flags);
-               alarm->state &= ~ALARMTIMER_STATE_CALLBACK;
+       alarmtimer_dequeue(base, alarm);
+       spin_unlock_irqrestore(&base->lock, flags);
 
-               if (restart != ALARMTIMER_NORESTART) {
-                       timerqueue_add(&base->timerqueue, &alarm->node);
-                       alarm->state |= ALARMTIMER_STATE_ENQUEUED;
-               }
-       }
+       if (alarm->function)
+               restart = alarm->function(alarm, base->gettime());
 
-       if (next) {
-               hrtimer_set_expires(&base->timer, next->expires);
+       spin_lock_irqsave(&base->lock, flags);
+       if (restart != ALARMTIMER_NORESTART) {
+               hrtimer_set_expires(&alarm->timer, alarm->node.expires);
+               alarmtimer_enqueue(base, alarm);
                ret = HRTIMER_RESTART;
        }
        spin_unlock_irqrestore(&base->lock, flags);
@@ -250,6 +217,7 @@ static int alarmtimer_suspend(struct device *dev)
        unsigned long flags;
        struct rtc_device *rtc;
        int i;
+       int ret;
 
        spin_lock_irqsave(&freezer_delta_lock, flags);
        min = freezer_delta;
@@ -279,8 +247,10 @@ static int alarmtimer_suspend(struct device *dev)
        if (min.tv64 == 0)
                return 0;
 
-       /* XXX - Should we enforce a minimum sleep time? */
-       WARN_ON(min.tv64 < NSEC_PER_SEC);
+       if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
+               __pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
+               return -EBUSY;
+       }
 
        /* Setup an rtc timer to fire that far in the future */
        rtc_timer_cancel(rtc, &rtctimer);
@@ -288,9 +258,11 @@ static int alarmtimer_suspend(struct device *dev)
        now = rtc_tm_to_ktime(tm);
        now = ktime_add(now, min);
 
-       rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
-
-       return 0;
+       /* Set alarm, if in the past reject suspend briefly to handle */
+       ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
+       if (ret < 0)
+               __pm_wakeup_event(ws, MSEC_PER_SEC);
+       return ret;
 }
 #else
 static int alarmtimer_suspend(struct device *dev)
@@ -324,6 +296,9 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
                enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
 {
        timerqueue_init(&alarm->node);
+       hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid,
+                       HRTIMER_MODE_ABS);
+       alarm->timer.function = alarmtimer_fired;
        alarm->function = function;
        alarm->type = type;
        alarm->state = ALARMTIMER_STATE_INACTIVE;
@@ -334,17 +309,19 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
  * @alarm: ptr to alarm to set
  * @start: time to run the alarm
  */
-void alarm_start(struct alarm *alarm, ktime_t start)
+int alarm_start(struct alarm *alarm, ktime_t start)
 {
        struct alarm_base *base = &alarm_bases[alarm->type];
        unsigned long flags;
+       int ret;
 
        spin_lock_irqsave(&base->lock, flags);
-       if (alarmtimer_active(alarm))
-               alarmtimer_remove(base, alarm);
        alarm->node.expires = start;
        alarmtimer_enqueue(base, alarm);
+       ret = hrtimer_start(&alarm->timer, alarm->node.expires,
+                               HRTIMER_MODE_ABS);
        spin_unlock_irqrestore(&base->lock, flags);
+       return ret;
 }
 
 /**
@@ -358,18 +335,12 @@ int alarm_try_to_cancel(struct alarm *alarm)
 {
        struct alarm_base *base = &alarm_bases[alarm->type];
        unsigned long flags;
-       int ret = -1;
-       spin_lock_irqsave(&base->lock, flags);
-
-       if (alarmtimer_callback_running(alarm))
-               goto out;
+       int ret;
 
-       if (alarmtimer_is_queued(alarm)) {
-               alarmtimer_remove(base, alarm);
-               ret = 1;
-       } else
-               ret = 0;
-out:
+       spin_lock_irqsave(&base->lock, flags);
+       ret = hrtimer_try_to_cancel(&alarm->timer);
+       if (ret >= 0)
+               alarmtimer_dequeue(base, alarm);
        spin_unlock_irqrestore(&base->lock, flags);
        return ret;
 }
@@ -802,10 +773,6 @@ static int __init alarmtimer_init(void)
        for (i = 0; i < ALARM_NUMTYPE; i++) {
                timerqueue_init_head(&alarm_bases[i].timerqueue);
                spin_lock_init(&alarm_bases[i].lock);
-               hrtimer_init(&alarm_bases[i].timer,
-                               alarm_bases[i].base_clockid,
-                               HRTIMER_MODE_ABS);
-               alarm_bases[i].timer.function = alarmtimer_fired;
        }
 
        error = alarmtimer_rtc_interface_setup();
@@ -821,6 +788,7 @@ static int __init alarmtimer_init(void)
                error = PTR_ERR(pdev);
                goto out_drv;
        }
+       ws = wakeup_source_register("alarmtimer");
        return 0;
 
 out_drv:
index 46da0537c10b4d78e3c5645d8b709bb3503cc2af..6629bf7b52856849899c348156b65ce3cc732cd4 100644 (file)
@@ -37,7 +37,7 @@
  * requested HZ value. It is also not recommended
  * for "tick-less" systems.
  */
-#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/SHIFTED_HZ))
+#define NSEC_PER_JIFFY ((NSEC_PER_SEC+HZ/2)/HZ)
 
 /* Since jiffies uses a simple NSEC_PER_JIFFY multiplier
  * conversion, the .shift value could be zero. However
@@ -95,3 +95,33 @@ struct clocksource * __init __weak clocksource_default_clock(void)
 {
        return &clocksource_jiffies;
 }
+
+struct clocksource refined_jiffies;
+
+int register_refined_jiffies(long cycles_per_second)
+{
+       u64 nsec_per_tick, shift_hz;
+       long cycles_per_tick;
+
+
+
+       refined_jiffies = clocksource_jiffies;
+       refined_jiffies.name = "refined-jiffies";
+       refined_jiffies.rating++;
+
+       /* Calc cycles per tick */
+       cycles_per_tick = (cycles_per_second + HZ/2)/HZ;
+       /* shift_hz stores hz<<8 for extra accuracy */
+       shift_hz = (u64)cycles_per_second << 8;
+       shift_hz += cycles_per_tick/2;
+       do_div(shift_hz, cycles_per_tick);
+       /* Calculate nsec_per_tick using shift_hz */
+       nsec_per_tick = (u64)NSEC_PER_SEC << 8;
+       nsec_per_tick += (u32)shift_hz/2;
+       do_div(nsec_per_tick, (u32)shift_hz);
+
+       refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT;
+
+       clocksource_register(&refined_jiffies);
+       return 0;
+}
index f423bdd035c2234fb91910b60d096992405a28ba..a40260885265707603d72dee9df79f030e973221 100644 (file)
@@ -835,7 +835,7 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
                 */
                if (ts->tick_stopped) {
                        touch_softlockup_watchdog();
-                       if (idle_cpu(cpu))
+                       if (is_idle_task(current))
                                ts->idle_jiffies++;
                }
                update_process_times(user_mode(regs));
index 5ce06a3fa91e01af6a3cfc7fbbc828af2824fae8..e424970bb562657af3d37de69320ba0f07ed9b70 100644 (file)
@@ -8,6 +8,7 @@
  *
  */
 
+#include <linux/timekeeper_internal.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/tick.h>
 #include <linux/stop_machine.h>
 
-/* Structure holding internal timekeeping values. */
-struct timekeeper {
-       /* Current clocksource used for timekeeping. */
-       struct clocksource      *clock;
-       /* NTP adjusted clock multiplier */
-       u32                     mult;
-       /* The shift value of the current clocksource. */
-       u32                     shift;
-       /* Number of clock cycles in one NTP interval. */
-       cycle_t                 cycle_interval;
-       /* Number of clock shifted nano seconds in one NTP interval. */
-       u64                     xtime_interval;
-       /* shifted nano seconds left over when rounding cycle_interval */
-       s64                     xtime_remainder;
-       /* Raw nano seconds accumulated per NTP interval. */
-       u32                     raw_interval;
-
-       /* Current CLOCK_REALTIME time in seconds */
-       u64                     xtime_sec;
-       /* Clock shifted nano seconds */
-       u64                     xtime_nsec;
-
-       /* Difference between accumulated time and NTP time in ntp
-        * shifted nano seconds. */
-       s64                     ntp_error;
-       /* Shift conversion between clock shifted nano seconds and
-        * ntp shifted nano seconds. */
-       u32                     ntp_error_shift;
-
-       /*
-        * wall_to_monotonic is what we need to add to xtime (or xtime corrected
-        * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
-        * at zero at system boot time, so wall_to_monotonic will be negative,
-        * however, we will ALWAYS keep the tv_nsec part positive so we can use
-        * the usual normalization.
-        *
-        * wall_to_monotonic is moved after resume from suspend for the
-        * monotonic time not to jump. We need to add total_sleep_time to
-        * wall_to_monotonic to get the real boot based time offset.
-        *
-        * - wall_to_monotonic is no longer the boot time, getboottime must be
-        * used instead.
-        */
-       struct timespec         wall_to_monotonic;
-       /* Offset clock monotonic -> clock realtime */
-       ktime_t                 offs_real;
-       /* time spent in suspend */
-       struct timespec         total_sleep_time;
-       /* Offset clock monotonic -> clock boottime */
-       ktime_t                 offs_boot;
-       /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
-       struct timespec         raw_time;
-       /* Seqlock for all timekeeper values */
-       seqlock_t               lock;
-};
 
 static struct timekeeper timekeeper;
 
@@ -96,15 +42,6 @@ static inline void tk_normalize_xtime(struct timekeeper *tk)
        }
 }
 
-static struct timespec tk_xtime(struct timekeeper *tk)
-{
-       struct timespec ts;
-
-       ts.tv_sec = tk->xtime_sec;
-       ts.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
-       return ts;
-}
-
 static void tk_set_xtime(struct timekeeper *tk, const struct timespec *ts)
 {
        tk->xtime_sec = ts->tv_sec;
@@ -246,14 +183,11 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
 /* must hold write on timekeeper.lock */
 static void timekeeping_update(struct timekeeper *tk, bool clearntp)
 {
-       struct timespec xt;
-
        if (clearntp) {
                tk->ntp_error = 0;
                ntp_clear();
        }
-       xt = tk_xtime(tk);
-       update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);
+       update_vsyscall(tk);
 }
 
 /**
@@ -1113,7 +1047,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
        accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
-       raw_nsecs = tk->raw_interval << shift;
+       raw_nsecs = (u64)tk->raw_interval << shift;
        raw_nsecs += tk->raw_time.tv_nsec;
        if (raw_nsecs >= NSEC_PER_SEC) {
                u64 raw_secs = raw_nsecs;
@@ -1130,6 +1064,33 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
        return offset;
 }
 
+#ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD
+static inline void old_vsyscall_fixup(struct timekeeper *tk)
+{
+       s64 remainder;
+
+       /*
+       * Store only full nanoseconds into xtime_nsec after rounding
+       * it up and add the remainder to the error difference.
+       * XXX - This is necessary to avoid small 1ns inconsistnecies caused
+       * by truncating the remainder in vsyscalls. However, it causes
+       * additional work to be done in timekeeping_adjust(). Once
+       * the vsyscall implementations are converted to use xtime_nsec
+       * (shifted nanoseconds), and CONFIG_GENERIC_TIME_VSYSCALL_OLD
+       * users are removed, this can be killed.
+       */
+       remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1);
+       tk->xtime_nsec -= remainder;
+       tk->xtime_nsec += 1ULL << tk->shift;
+       tk->ntp_error += remainder << tk->ntp_error_shift;
+
+}
+#else
+#define old_vsyscall_fixup(tk)
+#endif
+
+
+
 /**
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
@@ -1141,7 +1102,6 @@ static void update_wall_time(void)
        cycle_t offset;
        int shift = 0, maxshift;
        unsigned long flags;
-       s64 remainder;
 
        write_seqlock_irqsave(&tk->lock, flags);
 
@@ -1183,20 +1143,11 @@ static void update_wall_time(void)
        /* correct the clock when NTP error is too big */
        timekeeping_adjust(tk, offset);
 
-
        /*
-       * Store only full nanoseconds into xtime_nsec after rounding
-       * it up and add the remainder to the error difference.
-       * XXX - This is necessary to avoid small 1ns inconsistnecies caused
-       * by truncating the remainder in vsyscalls. However, it causes
-       * additional work to be done in timekeeping_adjust(). Once
-       * the vsyscall implementations are converted to use xtime_nsec
-       * (shifted nanoseconds), this can be killed.
-       */
-       remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1);
-       tk->xtime_nsec -= remainder;
-       tk->xtime_nsec += 1ULL << tk->shift;
-       tk->ntp_error += remainder << tk->ntp_error_shift;
+        * XXX This can be killed once everyone converts
+        * to the new update_vsyscall.
+        */
+       old_vsyscall_fixup(tk);
 
        /*
         * Finally, make sure that after the rounding
index d5de1b2292aad651da76bfbd2c5d037ff9852237..367d008584823a6fe01ed013cda8c3693fcfd761 100644 (file)
@@ -63,6 +63,7 @@ EXPORT_SYMBOL(jiffies_64);
 #define TVR_SIZE (1 << TVR_BITS)
 #define TVN_MASK (TVN_SIZE - 1)
 #define TVR_MASK (TVR_SIZE - 1)
+#define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4*TVN_BITS)) - 1))
 
 struct tvec {
        struct list_head vec[TVN_SIZE];
@@ -359,11 +360,12 @@ __internal_add_timer(struct tvec_base *base, struct timer_list *timer)
                vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
        } else {
                int i;
-               /* If the timeout is larger than 0xffffffff on 64-bit
-                * architectures then we use the maximum timeout:
+               /* If the timeout is larger than MAX_TVAL (on 64-bit
+                * architectures or with CONFIG_BASE_SMALL=1) then we
+                * use the maximum timeout.
                 */
-               if (idx > 0xffffffffUL) {
-                       idx = 0xffffffffUL;
+               if (idx > MAX_TVAL) {
+                       idx = MAX_TVAL;
                        expires = idx + base->timer_jiffies;
                }
                i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
index 9c217255ac49374834689590f6e2bd9752e23da2..069a24e64403f19bd6f51c9d9a9ef4b56deef48d 100644 (file)
@@ -168,6 +168,7 @@ void kmem_cache_destroy(struct kmem_cache *s)
                list_del(&s->list);
 
                if (!__kmem_cache_shutdown(s)) {
+                       mutex_unlock(&slab_mutex);
                        if (s->flags & SLAB_DESTROY_BY_RCU)
                                rcu_barrier();
 
@@ -175,12 +176,14 @@ void kmem_cache_destroy(struct kmem_cache *s)
                        kmem_cache_free(kmem_cache, s);
                } else {
                        list_add(&s->list, &slab_caches);
+                       mutex_unlock(&slab_mutex);
                        printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
                                s->name);
                        dump_stack();
                }
+       } else {
+               mutex_unlock(&slab_mutex);
        }
-       mutex_unlock(&slab_mutex);
        put_online_cpus();
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
index c0ab72cbeed1288da505468e27e42b3dca984b3f..70d4848b5cd0ad25ce272877f9c759ed010dfc58 100644 (file)
@@ -5168,6 +5168,8 @@ EXPORT_SYMBOL_HDA(snd_hda_resume);
  */
 void *snd_array_new(struct snd_array *array)
 {
+       if (snd_BUG_ON(!array->elem_size))
+               return NULL;
        if (array->used >= array->alloced) {
                int num = array->alloced + array->alloc_align;
                int size = (num + 1) * array->elem_size;
index f09ff6c14041794bbd3d56e5d59a17410dddf037..6833835a218b9f581a58c5c0b3fe6aa36d8df51d 100644 (file)
@@ -554,7 +554,6 @@ enum {
 #define AZX_DCAPS_BUFSIZE      (1 << 21)       /* no buffer size alignment */
 #define AZX_DCAPS_ALIGN_BUFSIZE        (1 << 22)       /* buffer size alignment */
 #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)   /* BDLE in 4k boundary */
-#define AZX_DCAPS_POSFIX_COMBO  (1 << 24)      /* Use COMBO as default */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
 
 /* quirks for ATI SB / AMD Hudson */
@@ -2858,10 +2857,6 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
                snd_printd(SFX "Using LPIB position fix\n");
                return POS_FIX_LPIB;
        }
-       if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) {
-               snd_printd(SFX "Using COMBO position fix\n");
-               return POS_FIX_COMBO;
-       }
        return POS_FIX_AUTO;
 }
 
index fcfc9f0a056b82fcbe9b7deafbef3b2c9516f6c4..61a71131711c734556249b17fc61fc51f1218c1a 100644 (file)
@@ -897,7 +897,7 @@ static int build_digital_input(struct hda_codec *codec)
  * HP/SPK/SPDIF
  */
 
-static void cs_automute(struct hda_codec *codec)
+static void cs_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
 {
        struct cs_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -973,7 +973,7 @@ static void cs_automute(struct hda_codec *codec)
  * Switch max 3 inputs of a single ADC (nid 3)
 */
 
-static void cs_automic(struct hda_codec *codec)
+static void cs_automic(struct hda_codec *codec, struct hda_jack_tbl *tbl)
 {
        struct cs_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -1035,7 +1035,7 @@ static void init_output(struct hda_codec *codec)
                if (!cfg->speaker_outs)
                        continue;
                if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
-                       snd_hda_jack_detect_enable(codec, nid, HP_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, nid, HP_EVENT, cs_automute);
                        spec->hp_detect = 1;
                }
        }
@@ -1046,7 +1046,7 @@ static void init_output(struct hda_codec *codec)
 
        /* SPDIF is enabled on presence detect for CS421x */
        if (spec->hp_detect || spec->spdif_detect)
-               cs_automute(codec);
+               cs_automute(codec, NULL);
 }
 
 static void init_input(struct hda_codec *codec)
@@ -1070,13 +1070,13 @@ static void init_input(struct hda_codec *codec)
                                    AC_VERB_SET_AMP_GAIN_MUTE,
                                    AMP_IN_MUTE(spec->adc_idx[i]));
                if (spec->mic_detect && spec->automic_idx == i)
-                       snd_hda_jack_detect_enable(codec, pin, MIC_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, pin, MIC_EVENT, cs_automic);
        }
        /* CS420x has multiple ADC, CS421x has single ADC */
        if (spec->vendor_nid == CS420X_VENDOR_NID) {
                change_cur_input(codec, spec->cur_input, 1);
                if (spec->mic_detect)
-                       cs_automic(codec);
+                       cs_automic(codec, NULL);
 
                coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
                if (is_active_pin(codec, CS_DMIC2_PIN_NID))
@@ -1089,7 +1089,7 @@ static void init_input(struct hda_codec *codec)
                cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
        } else {
                if (spec->mic_detect)
-                       cs_automic(codec);
+                       cs_automic(codec, NULL);
                else  {
                        spec->cur_adc = spec->adc_nid[spec->cur_input];
                        cs_update_input_select(codec);
@@ -1243,28 +1243,16 @@ static void cs_free(struct hda_codec *codec)
        struct cs_spec *spec = codec->spec;
        kfree(spec->capture_bind[0]);
        kfree(spec->capture_bind[1]);
+       snd_hda_gen_free(&spec->gen);
        kfree(codec->spec);
 }
 
-static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       switch (snd_hda_jack_get_action(codec, res >> 26)) {
-       case HP_EVENT:
-               cs_automute(codec);
-               break;
-       case MIC_EVENT:
-               cs_automic(codec);
-               break;
-       }
-       snd_hda_jack_report_sync(codec);
-}
-
 static const struct hda_codec_ops cs_patch_ops = {
        .build_controls = cs_build_controls,
        .build_pcms = cs_build_pcms,
        .init = cs_init,
        .free = cs_free,
-       .unsol_event = cs_unsol_event,
+       .unsol_event = snd_hda_jack_unsol_event,
 };
 
 static int cs_parse_auto_config(struct hda_codec *codec)
@@ -1439,6 +1427,7 @@ static int patch_cs420x(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
        codec->spec = spec;
+       snd_hda_gen_init(&spec->gen);
 
        spec->vendor_nid = CS420X_VENDOR_NID;
 
@@ -1457,7 +1446,7 @@ static int patch_cs420x(struct hda_codec *codec)
        return 0;
 
  error:
-       kfree(codec->spec);
+       cs_free(codec);
        codec->spec = NULL;
        return err;
 }
@@ -1674,7 +1663,7 @@ static void init_cs421x_digital(struct hda_codec *codec)
                if (!cfg->speaker_outs)
                        continue;
                if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
-                       snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, nid, SPDIF_EVENT, cs_automute);
                        spec->spdif_detect = 1;
                }
        }
@@ -1889,21 +1878,6 @@ static int cs421x_build_controls(struct hda_codec *codec)
        return 0;
 }
 
-static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       switch (snd_hda_jack_get_action(codec, res >> 26)) {
-       case HP_EVENT:
-       case SPDIF_EVENT:
-               cs_automute(codec);
-               break;
-
-       case MIC_EVENT:
-               cs_automic(codec);
-               break;
-       }
-       snd_hda_jack_report_sync(codec);
-}
-
 static int parse_cs421x_input(struct hda_codec *codec)
 {
        struct cs_spec *spec = codec->spec;
@@ -1977,7 +1951,7 @@ static struct hda_codec_ops cs421x_patch_ops = {
        .build_pcms = cs_build_pcms,
        .init = cs421x_init,
        .free = cs_free,
-       .unsol_event = cs421x_unsol_event,
+       .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
        .suspend = cs421x_suspend,
 #endif
@@ -1992,6 +1966,7 @@ static int patch_cs4210(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
        codec->spec = spec;
+       snd_hda_gen_init(&spec->gen);
 
        spec->vendor_nid = CS4210_VENDOR_NID;
 
@@ -2017,7 +1992,7 @@ static int patch_cs4210(struct hda_codec *codec)
        return 0;
 
  error:
-       kfree(codec->spec);
+       cs_free(codec);
        codec->spec = NULL;
        return err;
 }
@@ -2031,6 +2006,7 @@ static int patch_cs4213(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
        codec->spec = spec;
+       snd_hda_gen_init(&spec->gen);
 
        spec->vendor_nid = CS4213_VENDOR_NID;
 
@@ -2042,7 +2018,7 @@ static int patch_cs4213(struct hda_codec *codec)
        return 0;
 
  error:
-       kfree(codec->spec);
+       cs_free(codec);
        codec->spec = NULL;
        return err;
 }
index 8568aee56e2daaef1c77a8d19df4227af57eccc3..8253b4eeb6a1bea0687675e8ac66ca41b9a84758 100644 (file)
@@ -611,6 +611,8 @@ static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack
 {
        struct alc_spec *spec = codec->spec;
 
+       if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
+               return;
        /* check LO jack only when it's different from HP */
        if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
                return;
@@ -4245,6 +4247,7 @@ static void alc_auto_init_std(struct hda_codec *codec)
        ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
 
 static const struct snd_pci_quirk beep_white_list[] = {
+       SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
        SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
        SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
        SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
index fe163547f906cae4f6d1d1ea88ee7a7a1b599951..770013ff556f6be0500b14039a8e60df2fa74b2a 100644 (file)
@@ -104,6 +104,7 @@ enum {
        STAC_92HD83XXX_HP_LED,
        STAC_92HD83XXX_HP_INV_LED,
        STAC_92HD83XXX_HP_MIC_LED,
+       STAC_92HD83XXX_HEADSET_JACK,
        STAC_92HD83XXX_MODELS
 };
 
@@ -204,6 +205,7 @@ struct sigmatel_spec {
        unsigned int check_volume_offset:1;
        unsigned int auto_mic:1;
        unsigned int linear_tone_beep:1;
+       unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */
 
        /* gpio lines */
        unsigned int eapd_mask;
@@ -1684,6 +1686,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
        [STAC_92HD83XXX_HP_LED] = "hp-led",
        [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led",
        [STAC_92HD83XXX_HP_MIC_LED] = "hp-mic-led",
+       [STAC_92HD83XXX_HEADSET_JACK] = "headset-jack",
 };
 
 static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1694,6 +1697,24 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                      "DFI LanParty", STAC_92HD83XXX_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
                      "unknown Dell", STAC_DELL_S14),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0532,
+                     "Dell Latitude E6230", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0533,
+                     "Dell Latitude E6330", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0534,
+                     "Dell Latitude E6430", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0535,
+                     "Dell Latitude E6530", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053c,
+                     "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053d,
+                     "Dell Latitude E5530", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0549,
+                     "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x057d,
+                     "Dell Latitude E6430s", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0584,
+                     "Dell Latitude E6430U", STAC_92HD83XXX_HEADSET_JACK),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028,
                      "Dell Vostro 3500", STAC_DELL_VOSTRO_3500),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
@@ -2855,6 +2876,9 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
        char name[22];
 
        if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
+               if (spec->headset_jack && snd_hda_get_input_pin_attr(def_conf)
+                       != INPUT_PIN_ATTR_DOCK)
+                       return 0;
                if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
                        && nid == spec->line_switch)
                        control = STAC_CTL_WIDGET_IO_SWITCH;
@@ -5626,6 +5650,9 @@ again:
        case STAC_92HD83XXX_HP_MIC_LED:
                spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
                break;
+       case STAC_92HD83XXX_HEADSET_JACK:
+               spec->headset_jack = 1;
+               break;
        }
 
        if (find_mute_led_cfg(codec, default_polarity))
index 5a45a912aedcc22ef543a57229fcfa26880c51b7..72a2f60b087c8ba066b52e5aaf4cda500227471f 100644 (file)
@@ -118,6 +118,8 @@ enum {
 };
 
 struct via_spec {
+       struct hda_gen_spec gen;
+
        /* codec parameterization */
        const struct snd_kcontrol_new *mixers[6];
        unsigned int num_mixers;
@@ -246,6 +248,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
        /* VT1708BCE & VT1708S are almost same */
        if (spec->codec_type == VT1708BCE)
                spec->codec_type = VT1708S;
+       snd_hda_gen_init(&spec->gen);
        return spec;
 }
 
@@ -299,7 +302,6 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
 
 #define VIA_JACK_EVENT         0x20
 #define VIA_HP_EVENT           0x01
-#define VIA_GPIO_EVENT         0x02
 #define VIA_LINE_EVENT         0x03
 
 enum {
@@ -1628,6 +1630,7 @@ static void via_free(struct hda_codec *codec)
        vt1708_stop_hp_work(spec);
        kfree(spec->bind_cap_vol);
        kfree(spec->bind_cap_sw);
+       snd_hda_gen_free(&spec->gen);
        kfree(spec);
 }
 
@@ -1685,69 +1688,6 @@ static void via_hp_automute(struct hda_codec *codec)
        via_line_automute(codec, present);
 }
 
-static void via_gpio_control(struct hda_codec *codec)
-{
-       unsigned int gpio_data;
-       unsigned int vol_counter;
-       unsigned int vol;
-       unsigned int master_vol;
-
-       struct via_spec *spec = codec->spec;
-
-       gpio_data = snd_hda_codec_read(codec, codec->afg, 0,
-                                      AC_VERB_GET_GPIO_DATA, 0) & 0x03;
-
-       vol_counter = (snd_hda_codec_read(codec, codec->afg, 0,
-                                         0xF84, 0) & 0x3F0000) >> 16;
-
-       vol = vol_counter & 0x1F;
-       master_vol = snd_hda_codec_read(codec, 0x1A, 0,
-                                       AC_VERB_GET_AMP_GAIN_MUTE,
-                                       AC_AMP_GET_INPUT);
-
-       if (gpio_data == 0x02) {
-               /* unmute line out */
-               snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0],
-                                   PIN_OUT);
-               if (vol_counter & 0x20) {
-                       /* decrease volume */
-                       if (vol > master_vol)
-                               vol = master_vol;
-                       snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT,
-                                                0, HDA_AMP_VOLMASK,
-                                                master_vol-vol);
-               } else {
-                       /* increase volume */
-                       snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0,
-                                        HDA_AMP_VOLMASK,
-                                        ((master_vol+vol) > 0x2A) ? 0x2A :
-                                         (master_vol+vol));
-               }
-       } else if (!(gpio_data & 0x02)) {
-               /* mute line out */
-               snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], 0);
-       }
-}
-
-/* unsolicited event for jack sensing */
-static void via_unsol_event(struct hda_codec *codec,
-                                 unsigned int res)
-{
-       res >>= 26;
-       res = snd_hda_jack_get_action(codec, res);
-
-       if (res & VIA_JACK_EVENT)
-               set_widgets_power_state(codec);
-
-       res &= ~VIA_JACK_EVENT;
-
-       if (res == VIA_HP_EVENT || res == VIA_LINE_EVENT)
-               via_hp_automute(codec);
-       else if (res == VIA_GPIO_EVENT)
-               via_gpio_control(codec);
-       snd_hda_jack_report_sync(codec);
-}
-
 #ifdef CONFIG_PM
 static int via_suspend(struct hda_codec *codec)
 {
@@ -1783,7 +1723,7 @@ static const struct hda_codec_ops via_patch_ops = {
        .build_pcms = via_build_pcms,
        .init = via_init,
        .free = via_free,
-       .unsol_event = via_unsol_event,
+       .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
        .suspend = via_suspend,
        .check_power_status = via_check_power_status,
@@ -2761,6 +2701,17 @@ static void via_auto_init_dig_in(struct hda_codec *codec)
        snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN);
 }
 
+static void via_jack_output_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
+{
+       set_widgets_power_state(codec);
+       via_hp_automute(codec);
+}
+
+static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
+{
+       set_widgets_power_state(codec);
+}
+
 /* initialize the unsolicited events */
 static void via_auto_init_unsol_event(struct hda_codec *codec)
 {
@@ -2768,26 +2719,31 @@ static void via_auto_init_unsol_event(struct hda_codec *codec)
        struct auto_pin_cfg *cfg = &spec->autocfg;
        unsigned int ev;
        int i;
+       hda_jack_callback cb;
 
        if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0]))
-               snd_hda_jack_detect_enable(codec, cfg->hp_pins[0],
-                                          VIA_HP_EVENT | VIA_JACK_EVENT);
+               snd_hda_jack_detect_enable_callback(codec, cfg->hp_pins[0],
+                                                   VIA_HP_EVENT | VIA_JACK_EVENT,
+                                                   via_jack_output_event);
 
        if (cfg->speaker_pins[0])
                ev = VIA_LINE_EVENT;
        else
                ev = 0;
+       cb = ev ? via_jack_output_event : via_jack_powerstate_event;
+
        for (i = 0; i < cfg->line_outs; i++) {
                if (cfg->line_out_pins[i] &&
                    is_jack_detectable(codec, cfg->line_out_pins[i]))
-                       snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i],
-                                                  ev | VIA_JACK_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, cfg->line_out_pins[i],
+                                                           ev | VIA_JACK_EVENT, cb);
        }
 
        for (i = 0; i < cfg->num_inputs; i++) {
                if (is_jack_detectable(codec, cfg->inputs[i].pin))
-                       snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin,
-                                                  VIA_JACK_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, cfg->inputs[i].pin,
+                                                           VIA_JACK_EVENT,
+                                                           via_jack_powerstate_event);
        }
 }
 
index d73ac9bc427298f0f35ddf3cea7245b201f55709..88d8cebbb244ade66eb43db91be9d9b5cf9669d5 100644 (file)
@@ -2780,6 +2780,52 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 
        }
 },
+{
+       /* Tascam US122 MKII - playback-only support */
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor = 0x0644,
+       .idProduct = 0x8021,
+       .bInterfaceClass = USB_CLASS_AUDIO,
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "TASCAM",
+               .product_name = "US122 MKII",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 2,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x02,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_88200 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 4,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000, 88200, 96000
+                                       }
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 /* Microsoft XboxLive Headset/Xbox Communicator */
 {